OSDN Git Service

Merge from transactional-memory branch.
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index fa22bc9..508e252 100644 (file)
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-objc.h"
 #include "tree-inline.h"
 #include "tree-mudflap.h"
+#include "intl.h"
 #include "toplev.h"
 #include "flags.h"
 #include "output.h"
@@ -423,7 +424,7 @@ maybe_cleanup_point_expr (tree expr)
    expression.  The reason why we do this is because the original type might be
    an aggregate and we cannot create a temporary variable for that type.  */
 
-static tree
+tree
 maybe_cleanup_point_expr_void (tree expr)
 {
   if (!processing_template_decl && stmts_are_full_exprs_p ())
@@ -2042,12 +2043,14 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
         expressions with no type as being dependent.  */
       if (type_dependent_expression_p (fn)
          || any_type_dependent_arguments_p (*args)
-         /* For a non-static member function, we need to specifically
+         /* For a non-static member function that doesn't have an
+            explicit object argument, we need to specifically
             test the type dependency of the "this" pointer because it
             is not included in *ARGS even though it is considered to
             be part of the list of arguments.  Note that this is
             related to CWG issues 515 and 1005.  */
-         || (non_static_member_function_p (fn)
+         || (TREE_CODE (fn) != COMPONENT_REF
+             && non_static_member_function_p (fn)
              && current_class_ref
              && type_dependent_expression_p (current_class_ref)))
        {
@@ -2310,19 +2313,6 @@ tree
 finish_unary_op_expr (enum tree_code code, tree expr)
 {
   tree result = build_x_unary_op (code, expr, tf_warning_or_error);
-  /* Inside a template, build_x_unary_op does not fold the
-     expression. So check whether the result is folded before
-     setting TREE_NEGATED_INT.  */
-  if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST
-      && TREE_CODE (result) == INTEGER_CST
-      && !TYPE_UNSIGNED (TREE_TYPE (result))
-      && INT_CST_LT (result, integer_zero_node))
-    {
-      /* RESULT may be a cached INTEGER_CST, so we must copy it before
-        setting TREE_NEGATED_INT.  */
-      result = copy_node (result);
-      TREE_NEGATED_INT (result) = 1;
-    }
   if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
     overflow_warning (input_location, result);
 
@@ -2379,6 +2369,9 @@ finish_compound_literal (tree type, tree compound_literal,
       && check_array_initializer (NULL_TREE, type, compound_literal))
     return error_mark_node;
   compound_literal = reshape_init (type, compound_literal, complain);
+  if (SCALAR_TYPE_P (type)
+      && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal))
+    check_narrowing (type, compound_literal);
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == NULL_TREE)
     {
@@ -2740,15 +2733,17 @@ finish_template_decl (tree parms)
 tree
 finish_template_type (tree name, tree args, int entering_scope)
 {
-  tree decl;
+  tree type;
 
-  decl = lookup_template_class (name, args,
+  type = lookup_template_class (name, args,
                                NULL_TREE, NULL_TREE, entering_scope,
                                tf_warning_or_error | tf_user);
-  if (decl != error_mark_node)
-    decl = TYPE_STUB_DECL (decl);
-
-  return decl;
+  if (type == error_mark_node)
+    return type;
+  else if (CLASS_TYPE_P (type) && !alias_type_or_template_p (type))
+    return TYPE_STUB_DECL (type);
+  else
+    return TYPE_NAME (type);
 }
 
 /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
@@ -2944,6 +2939,9 @@ finish_id_expression (tree id_expression,
          tree lambda_expr = NULL_TREE;
          tree initializer = convert_from_reference (decl);
 
+         /* Mark it as used now even if the use is ill-formed.  */
+         mark_used (decl);
+
          /* Core issue 696: "[At the July 2009 meeting] the CWG expressed
             support for an approach in which a reference to a local
             [constant] automatic variable in a nested class or lambda body
@@ -2990,8 +2988,8 @@ finish_id_expression (tree id_expression,
          else
            {
              error (TREE_CODE (decl) == VAR_DECL
-                    ? "use of %<auto%> variable from containing function"
-                    : "use of parameter from containing function");
+                    ? G_("use of %<auto%> variable from containing function")
+                    : G_("use of parameter from containing function"));
              error ("  %q+#D declared here", decl);
              return error_mark_node;
            }
@@ -3243,7 +3241,7 @@ finish_id_expression (tree id_expression,
       if (scope)
        {
          decl = (adjust_result_of_qualified_name_lookup
-                 (decl, scope, current_class_type));
+                 (decl, scope, current_nonlambda_class_type()));
 
          if (TREE_CODE (decl) == FUNCTION_DECL)
            mark_used (decl);
@@ -3290,8 +3288,9 @@ finish_id_expression (tree id_expression,
          if (TREE_CODE (first_fn) == TEMPLATE_DECL)
            first_fn = DECL_TEMPLATE_RESULT (first_fn);
 
-         if (!really_overloaded_fn (decl))
-           mark_used (first_fn);
+         if (!really_overloaded_fn (decl)
+             && !mark_used (first_fn))
+           return error_mark_node;
 
          if (!template_arg_p
              && TREE_CODE (first_fn) == FUNCTION_DECL
@@ -3399,6 +3398,149 @@ finish_underlying_type (tree type)
   return underlying_type;
 }
 
+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    }
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    }
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */
 
@@ -3429,7 +3571,7 @@ finish_offsetof (tree expr)
       if (!complete_type_or_else (TREE_TYPE (object), object))
        return error_mark_node;
     }
-  return fold_offsetof (expr, NULL_TREE);
+  return fold_offsetof (expr);
 }
 
 /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  This
@@ -3551,7 +3693,7 @@ emit_associated_thunks (tree fn)
 static inline bool
 is_instantiation_of_constexpr (tree fun)
 {
-  return (DECL_TEMPLATE_INFO (fun)
+  return (DECL_TEMPLOID_INSTANTIATION (fun)
          && DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
                                        (DECL_TI_TEMPLATE (fun))));
 }
@@ -3633,7 +3775,10 @@ expand_or_defer_fn_1 (tree fn)
           && !DECL_REALLY_EXTERN (fn))
          || (flag_keep_inline_dllexport
              && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn))))
-       mark_needed (fn);
+       {
+         mark_needed (fn);
+         DECL_EXTERNAL (fn) = 0;
+       }
     }
 
   /* There's no reason to do any of the work here if we're only doing
@@ -3902,6 +4047,14 @@ finish_omp_clauses (tree clauses)
          OMP_CLAUSE_IF_EXPR (c) = t;
          break;
 
+       case OMP_CLAUSE_FINAL:
+         t = OMP_CLAUSE_FINAL_EXPR (c);
+         t = maybe_convert_cond (t);
+         if (t == error_mark_node)
+           remove = true;
+         OMP_CLAUSE_FINAL_EXPR (c) = t;
+         break;
+
        case OMP_CLAUSE_NUM_THREADS:
          t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
          if (t == error_mark_node)
@@ -3933,6 +4086,7 @@ finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -4027,6 +4181,8 @@ finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                default:
                  error ("%qE has invalid type for %<reduction(%s)%>",
@@ -4071,6 +4227,10 @@ finish_omp_clauses (tree clauses)
            case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
              break;
            case OMP_CLAUSE_DEFAULT_SHARED:
+             /* const vars may be specified in firstprivate clause.  */
+             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                 && cxx_omp_const_qual_no_mutable (t))
+               break;
              share_name = "shared";
              break;
            case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -4694,15 +4854,22 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
 }
 
 void
-finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
+finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
+                  tree rhs, tree v, tree lhs1, tree rhs1)
 {
   tree orig_lhs;
   tree orig_rhs;
+  tree orig_v;
+  tree orig_lhs1;
+  tree orig_rhs1;
   bool dependent_p;
   tree stmt;
 
   orig_lhs = lhs;
   orig_rhs = rhs;
+  orig_v = v;
+  orig_lhs1 = lhs1;
+  orig_rhs1 = rhs1;
   dependent_p = false;
   stmt = NULL_TREE;
 
@@ -4711,29 +4878,60 @@ finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
   if (processing_template_decl)
     {
       dependent_p = (type_dependent_expression_p (lhs)
-                    || type_dependent_expression_p (rhs));
+                    || (rhs && type_dependent_expression_p (rhs))
+                    || (v && type_dependent_expression_p (v))
+                    || (lhs1 && type_dependent_expression_p (lhs1))
+                    || (rhs1 && type_dependent_expression_p (rhs1)));
       if (!dependent_p)
        {
          lhs = build_non_dependent_expr (lhs);
-         rhs = build_non_dependent_expr (rhs);
+         if (rhs)
+           rhs = build_non_dependent_expr (rhs);
+         if (v)
+           v = build_non_dependent_expr (v);
+         if (lhs1)
+           lhs1 = build_non_dependent_expr (lhs1);
+         if (rhs1)
+           rhs1 = build_non_dependent_expr (rhs1);
        }
     }
   if (!dependent_p)
     {
-      stmt = c_finish_omp_atomic (input_location, code, lhs, rhs);
+      stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
+                                 v, lhs1, rhs1);
       if (stmt == error_mark_node)
        return;
     }
   if (processing_template_decl)
-    stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
-                  build2 (code, void_type_node, orig_lhs, orig_rhs));
+    {
+      if (code == OMP_ATOMIC_READ)
+       {
+         stmt = build_min_nt (OMP_ATOMIC_READ, orig_lhs);
+         stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+       }
+      else
+       {
+         if (opcode == NOP_EXPR)
+           stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
+         else 
+           stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
+         if (orig_rhs1)
+           stmt = build_min_nt (COMPOUND_EXPR, orig_rhs1, stmt);
+         if (code != OMP_ATOMIC)
+           {
+             stmt = build_min_nt (code, orig_lhs1, stmt);
+             stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+           }
+       }
+      stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
+    }
   add_stmt (stmt);
 }
 
 void
 finish_omp_barrier (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4743,7 +4941,7 @@ finish_omp_barrier (void)
 void
 finish_omp_flush (void)
 {
-  tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+  tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4753,12 +4951,80 @@ finish_omp_flush (void)
 void
 finish_omp_taskwait (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
+
+void
+finish_omp_taskyield (void)
+{
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
+  VEC(tree,gc) *vec = make_tree_vector ();
+  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  release_tree_vector (vec);
+  finish_expr_stmt (stmt);
+}
+\f
+/* Begin a __transaction_atomic or __transaction_relaxed statement.
+   If PCOMPOUND is non-null, this is for a function-transaction-block, and we
+   should create an extra compound stmt.  */
+
+tree
+begin_transaction_stmt (location_t loc, tree *pcompound, int flags)
+{
+  tree r;
+
+  if (pcompound)
+    *pcompound = begin_compound_stmt (0);
+
+  r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE);
+
+  /* Only add the statement to the function if support enabled.  */
+  if (flag_tm)
+    add_stmt (r);
+  else
+    error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0
+                   ? G_("%<__transaction_relaxed%> without "
+                        "transactional memory support enabled")
+                   : G_("%<__transaction_atomic%> without "
+                        "transactional memory support enabled")));
+
+  TRANSACTION_EXPR_BODY (r) = push_stmt_list ();
+  return r;
+}
+
+/* End a __transaction_atomic or __transaction_relaxed statement.
+   If COMPOUND_STMT is non-null, this is for a function-transaction-block,
+   and we should end the compound.  */
+
+void
+finish_transaction_stmt (tree stmt, tree compound_stmt, int flags)
+{
+  TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt));
+  TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0;
+  TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0;
+  TRANSACTION_EXPR_IS_STMT (stmt) = 1;
+
+  if (compound_stmt)
+    finish_compound_stmt (compound_stmt);
+  finish_stmt ();
+}
+
+/* Build a __transaction_atomic or __transaction_relaxed expression.  */
+
+tree
+build_transaction_expr (location_t loc, tree expr, int flags)
+{
+  tree ret;
+  ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
+  if (flags & TM_STMT_ATTR_RELAXED)
+       TRANSACTION_EXPR_RELAXED (ret) = 1;
+  SET_EXPR_LOCATION (ret, loc);
+  return ret;
+}
 \f
 void
 init_cp_semantics (void)
@@ -4879,6 +5145,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
       return error_mark_node;
     }
 
+  if (invalid_nonstatic_memfn_p (expr, complain))
+    return error_mark_node;
+
   /* To get the size of a static data member declared as an array of
      unknown bound, we need to instantiate it.  */
   if (TREE_CODE (expr) == VAR_DECL
@@ -4907,7 +5176,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
            step.  */
         expr = TREE_OPERAND (expr, 1);
 
-      if (TREE_CODE (expr) == BASELINK)
+      if (BASELINK_P (expr))
         /* See through BASELINK nodes to the underlying function.  */
         expr = BASELINK_FUNCTIONS (expr);
 
@@ -5146,23 +5415,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     }
 }
 
-/* Returns true if TYPE is a complete type, an array of unknown bound,
-   or (possibly cv-qualified) void, returns false otherwise.  */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+   void, or a complete type, returns it, otherwise NULL_TREE.  */
 
-static bool
+static tree
 check_trait_type (tree type)
 {
-  if (COMPLETE_TYPE_P (type))
-    return true;
-
   if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
       && COMPLETE_TYPE_P (TREE_TYPE (type)))
-    return true;
+    return type;
 
   if (VOID_TYPE_P (type))
-    return true;
+    return type;
 
-  return false;
+  return complete_type_or_else (strip_array_types (type), NULL_TREE);
 }
 
 /* Process a trait expression.  */
@@ -5212,10 +5478,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       return trait_expr;
     }
 
-  complete_type (type1);
-  if (type2)
-    complete_type (type2);
-
   switch (kind)
     {
     case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5234,20 +5496,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_STD_LAYOUT:
     case CPTK_IS_TRIVIAL:
       if (!check_trait_type (type1))
-       {
-         error ("incomplete type %qT not allowed", type1);
-         return error_mark_node;
-       }
+       return error_mark_node;
       break;
 
     case CPTK_IS_BASE_OF:
       if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
          && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
-         && !COMPLETE_TYPE_P (type2))
-       {
-         error ("incomplete type %qT not allowed", type2);
-         return error_mark_node;
-       }
+         && !complete_type_or_else (type2, NULL_TREE))
+       /* We already issued an error.  */
+       return error_mark_node;
       break;
 
     case CPTK_IS_CLASS:
@@ -5408,7 +5665,6 @@ is_valid_constexpr_fn (tree fun, bool complain)
            }
        }
 
-      /* Check this again here for cxx_eval_call_expression.  */
       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
          && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
        {
@@ -5425,29 +5681,6 @@ is_valid_constexpr_fn (tree fun, bool complain)
   return ret;
 }
 
-/* Return non-null if FUN certainly designates a valid constexpr function
-   declaration.  Otherwise return NULL.  Issue appropriate diagnostics
-   if necessary.  Note that we only check the declaration, not the body
-   of the function.  */
-
-tree
-validate_constexpr_fundecl (tree fun)
-{
-  if (processing_template_decl || !DECL_DECLARED_CONSTEXPR_P (fun))
-    return NULL;
-  else if (DECL_CLONED_FUNCTION_P (fun))
-    /* We already checked the original function.  */
-    return fun;
-
-  if (!is_valid_constexpr_fn (fun, !DECL_TEMPLATE_INFO (fun)))
-    {
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
-      return NULL;
-    }
-
-  return fun;
-}
-
 /* Subroutine of  build_constexpr_constructor_member_initializers.
    The expression tree T represents a data member initialization
    in a (constexpr) constructor definition.  Build a pairing of
@@ -5698,6 +5931,63 @@ massage_constexpr_body (tree fun, tree body)
   return body;
 }
 
+/* FUN is a constexpr constructor with massaged body BODY.  Return true
+   if some bases/fields are uninitialized, and complain if COMPLAIN.  */
+
+static bool
+cx_check_missing_mem_inits (tree fun, tree body, bool complain)
+{
+  bool bad;
+  tree field;
+  unsigned i, nelts;
+
+  if (TREE_CODE (body) != CONSTRUCTOR)
+    return false;
+
+  bad = false;
+  nelts = CONSTRUCTOR_NELTS (body);
+  field = TYPE_FIELDS (DECL_CONTEXT (fun));
+  for (i = 0; i <= nelts; ++i)
+    {
+      tree index;
+      if (i == nelts)
+       index = NULL_TREE;
+      else
+       {
+         index = CONSTRUCTOR_ELT (body, i)->index;
+         /* Skip base and vtable inits.  */
+         if (TREE_CODE (index) != FIELD_DECL)
+           continue;
+       }
+      for (; field != index; field = DECL_CHAIN (field))
+       {
+         tree ftype;
+         if (TREE_CODE (field) != FIELD_DECL
+             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
+           continue;
+         if (!complain)
+           return true;
+         ftype = strip_array_types (TREE_TYPE (field));
+         if (type_has_constexpr_default_constructor (ftype))
+           {
+             /* It's OK to skip a member with a trivial constexpr ctor.
+                A constexpr ctor that isn't trivial should have been
+                added in by now.  */
+             gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype));
+             continue;
+           }
+         error ("uninitialized member %qD in %<constexpr%> constructor",
+                field);
+         bad = true;
+       }
+      if (field == NULL_TREE)
+       break;
+      field = DECL_CHAIN (field);
+    }
+
+  return bad;
+}
+
 /* We are processing the definition of the constexpr function FUN.
    Check that its BODY fulfills the propriate requirements and
    enter it in the constexpr function definition table.
@@ -5710,22 +6000,28 @@ register_constexpr_fundef (tree fun, tree body)
   constexpr_fundef entry;
   constexpr_fundef **slot;
 
+  if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
+    return NULL;
+
   body = massage_constexpr_body (fun, body);
   if (body == NULL_TREE || body == error_mark_node)
     {
-      error ("body of constexpr function %qD not a return-statement", fun);
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
+      if (!DECL_CONSTRUCTOR_P (fun))
+       error ("body of constexpr function %qD not a return-statement", fun);
       return NULL;
     }
 
   if (!potential_rvalue_constant_expression (body))
     {
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
-      if (!DECL_TEMPLATE_INFO (fun))
+      if (!DECL_GENERATED_P (fun))
        require_potential_rvalue_constant_expression (body);
       return NULL;
     }
 
+  if (DECL_CONSTRUCTOR_P (fun)
+      && cx_check_missing_mem_inits (fun, body, !DECL_GENERATED_P (fun)))
+    return NULL;
+
   /* Create the constexpr function table if necessary.  */
   if (constexpr_fundef_table == NULL)
     constexpr_fundef_table = htab_create_ggc (101,
@@ -5754,8 +6050,9 @@ explain_invalid_constexpr_fn (tree fun)
   static struct pointer_set_t *diagnosed;
   tree body;
   location_t save_loc;
-  /* Only diagnose instantiations of constexpr templates.  */
-  if (!is_instantiation_of_constexpr (fun))
+  /* Only diagnose defaulted functions or instantiations.  */
+  if (!DECL_DEFAULTED_FN (fun)
+      && !is_instantiation_of_constexpr (fun))
     return;
   if (diagnosed == NULL)
     diagnosed = pointer_set_create ();
@@ -5765,8 +6062,7 @@ explain_invalid_constexpr_fn (tree fun)
 
   save_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fun);
-  inform (0, "%q+D is not constexpr because it does not satisfy the "
-         "requirements:", fun);
+  inform (0, "%q+D is not usable as a constexpr function because:", fun);
   /* First check the declaration.  */
   if (is_valid_constexpr_fn (fun, true))
     {
@@ -5777,6 +6073,8 @@ explain_invalid_constexpr_fn (tree fun)
        {
          body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
          require_potential_rvalue_constant_expression (body);
+         if (DECL_CONSTRUCTOR_P (fun))
+           cx_check_missing_mem_inits (fun, body, true);
        }
     }
   input_location = save_loc;
@@ -6126,7 +6424,16 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
       if (new_call.fundef == NULL || new_call.fundef->body == NULL)
         {
          if (!allow_non_constant)
-           error_at (loc, "%qD used before its definition", fun);
+           {
+             if (DECL_INITIAL (fun))
+               {
+                 /* The definition of fun was somehow unsuitable.  */
+                 error_at (loc, "%qD called in a constant expression", fun);
+                 explain_invalid_constexpr_fn (fun);
+               }
+             else
+               error_at (loc, "%qD used before its definition", fun);
+           }
          *non_constant_p = true;
           return t;
         }
@@ -6359,12 +6666,19 @@ cxx_eval_array_reference (const constexpr_call *call, tree t,
   elem_type = TREE_TYPE (TREE_TYPE (ary));
   if (TREE_CODE (ary) == CONSTRUCTOR)
     len = CONSTRUCTOR_NELTS (ary);
-  else
+  else if (TREE_CODE (ary) == STRING_CST)
     {
       elem_nchars = (TYPE_PRECISION (elem_type)
                     / TYPE_PRECISION (char_type_node));
       len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
     }
+  else
+    {
+      /* We can't do anything with other tree codes, so use
+        VERIFY_CONSTANT to complain and fail.  */
+      VERIFY_CONSTANT (ary);
+      gcc_unreachable ();
+    }
   if (compare_tree_int (index, len) >= 0)
     {
       if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
@@ -6427,6 +6741,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
        error ("%qE is not a constant expression", orig_whole);
       *non_constant_p = true;
     }
+  if (DECL_MUTABLE_P (part))
+    {
+      if (!allow_non_constant)
+       error ("mutable %qD is not usable in a constant expression", part);
+      *non_constant_p = true;
+    }
   if (*non_constant_p)
     return t;
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
@@ -6434,7 +6754,8 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
       if (field == part)
         return value;
     }
-  if (TREE_CODE (TREE_TYPE (whole)) == UNION_TYPE)
+  if (TREE_CODE (TREE_TYPE (whole)) == UNION_TYPE
+      && CONSTRUCTOR_NELTS (whole) > 0)
     {
       /* DR 1188 says we don't have to deal with this.  */
       if (!allow_non_constant)
@@ -6443,8 +6764,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
       *non_constant_p = true;
       return t;
     }
-  gcc_unreachable();
-  return error_mark_node;
+
+  /* If there's no explicit init for this field, it's value-initialized.  */
+  value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
+  return cxx_eval_constant_expression (call, value,
+                                      allow_non_constant, addr,
+                                      non_constant_p);
 }
 
 /* Subroutine of cxx_eval_constant_expression.
@@ -6541,9 +6866,9 @@ cxx_eval_logical_expression (const constexpr_call *call, tree t,
                                           allow_non_constant, addr,
                                           non_constant_p);
   VERIFY_CONSTANT (lhs);
-  if (lhs == bailout_value)
+  if (tree_int_cst_equal (lhs, bailout_value))
     return lhs;
-  gcc_assert (lhs == continue_value);
+  gcc_assert (tree_int_cst_equal (lhs, continue_value));
   r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
                                    allow_non_constant, addr, non_constant_p);
   VERIFY_CONSTANT (r);
@@ -6648,6 +6973,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
   tree elttype = TREE_TYPE (atype);
   int max = tree_low_cst (array_type_nelts (atype), 0);
   VEC(constructor_elt,gc) *n = VEC_alloc (constructor_elt, gc, max + 1);
+  bool pre_init = false;
   int i;
 
   /* For the default constructor, build up a call to the default
@@ -6655,8 +6981,15 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
      here, as for a constructor to be constexpr, all members must be
      initialized, which for a defaulted default constructor means they must
      be of a class type with a constexpr default constructor.  */
-  if (value_init)
-    gcc_assert (!init);
+  if (TREE_CODE (elttype) == ARRAY_TYPE)
+    /* We only do this at the lowest level.  */;
+  else if (value_init)
+    {
+      init = build_value_init (elttype, tf_warning_or_error);
+      init = cxx_eval_constant_expression
+           (call, init, allow_non_constant, addr, non_constant_p);
+      pre_init = true;
+    }
   else if (!init)
     {
       VEC(tree,gc) *argvec = make_tree_vector ();
@@ -6666,6 +6999,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
       release_tree_vector (argvec);
       init = cxx_eval_constant_expression (call, init, allow_non_constant,
                                           addr, non_constant_p);
+      pre_init = true;
     }
 
   if (*non_constant_p && !allow_non_constant)
@@ -6687,17 +7021,14 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
                                         allow_non_constant, addr,
                                         non_constant_p);
        }
-      else if (value_init)
-       {
-         eltinit = build_value_init (elttype, tf_warning_or_error);
-         eltinit = cxx_eval_constant_expression
-           (call, eltinit, allow_non_constant, addr, non_constant_p);
-       }
-      else if (TREE_CODE (init) == CONSTRUCTOR)
+      else if (pre_init)
        {
-         /* Initializing an element using the call to the default
-            constructor we just built above.  */
-         eltinit = unshare_expr (init);
+         /* Initializing an element using value or default initialization
+            we just pre-built above.  */
+         if (i == 0)
+           eltinit = init;
+         else
+           eltinit = unshare_expr (init);
        }
       else
        {
@@ -7081,7 +7412,17 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
 
     case PARM_DECL:
       if (call && DECL_CONTEXT (t) == call->fundef->decl)
-       r = lookup_parameter_binding (call, t);
+       {
+         if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t)))
+           {
+             if (!allow_non_constant)
+               sorry ("use of the value of the object being constructed "
+                      "in a constant expression");
+             *non_constant_p = true;
+           }
+         else
+           r = lookup_parameter_binding (call, t);
+       }
       else if (addr)
        /* Defer in case this is only used for its type.  */;
       else
@@ -7339,8 +7680,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
       return t;
 
     case LAMBDA_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case PSEUDO_DTOR_EXPR:
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
@@ -7393,6 +7732,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
 
   verify_constant (r, allow_non_constant, &non_constant_p);
 
+  if (TREE_CODE (t) != CONSTRUCTOR
+      && cp_has_mutable_p (TREE_TYPE (t)))
+    {
+      /* We allow a mutable type if the original expression was a
+        CONSTRUCTOR so that we can do aggregate initialization of
+        constexpr variables.  */
+      if (!allow_non_constant)
+       error ("%qT cannot be the type of a complete constant expression "
+              "because it has mutable sub-objects", TREE_TYPE (t));
+      non_constant_p = true;
+    }
+
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
   else if (non_constant_p && TREE_CONSTANT (t))
@@ -7455,6 +7806,7 @@ maybe_constant_value (tree t)
 
   if (type_dependent_expression_p (t)
       || type_unknown_p (t)
+      || BRACE_ENCLOSED_INITIALIZER_P (t)
       || !potential_constant_expression (t)
       || value_dependent_expression_p (t))
     {
@@ -7520,32 +7872,6 @@ check_automatic_or_tls (tree ref)
 }
 #endif
 
-/* Return true if the DECL designates a builtin function that is
-   morally constexpr, in the sense that its parameter types and
-   return type are literal types and the compiler is allowed to
-   fold its invocations.  */
-
-static bool
-morally_constexpr_builtin_function_p (tree decl)
-{
-  tree funtype = TREE_TYPE (decl);
-  tree t;
-
-  if (!is_builtin_fn (decl))
-    return false;
-  if (!literal_type_p (TREE_TYPE (funtype)))
-    return false;
-  for (t = TYPE_ARG_TYPES (funtype); t != NULL ; t = TREE_CHAIN (t))
-    {
-      if (t == void_list_node)
-        return true;
-      if (!literal_type_p (TREE_VALUE (t)))
-        return false;
-    }
-  /* We assume no varargs builtins are suitable.  */
-  return t != NULL;
-}
-
 /* Return true if T denotes a potentially constant expression.  Issue
    diagnostic as appropriate under control of FLAGS.  If WANT_RVAL is true,
    an lvalue-rvalue conversion is implied.
@@ -7618,23 +7944,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case TEMPLATE_PARM_INDEX:
     case TRAIT_EXPR:
     case IDENTIFIER_NODE:
+    case USERDEF_LITERAL:
       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
     case FIELD_DECL:
-      return true;
-
     case PARM_DECL:
-      /* -- this (5.1) unless it appears as the postfix-expression in a
-            class member access expression, including the result of the
-            implicit transformation in the body of the non-static
-            member function (9.3.1);  */
-      /* FIXME this restriction seems pointless since the standard dropped
-        "potential constant expression".  */
-      if (is_this_parameter (t))
-        {
-          if (flags & tf_error)
-            error ("%qE is not a potential constant expression", t);
-          return false;
-        }
+    case USING_DECL:
       return true;
 
     case AGGR_INIT_EXPR:
@@ -7653,7 +7967,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
                if (builtin_valid_in_constant_expr_p (fun))
                  return true;
                if (!DECL_DECLARED_CONSTEXPR_P (fun)
-                   && !morally_constexpr_builtin_function_p (fun))
+                   /* Allow any built-in function; if the expansion
+                      isn't constant, we'll deal with that then.  */
+                   && !is_builtin_fn (fun))
                  {
                    if (flags & tf_error)
                      {
@@ -7672,7 +7988,17 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
                  {
                    tree x = get_nth_callarg (t, 0);
                    if (is_this_parameter (x))
-                     /* OK.  */;
+                     {
+                       if (DECL_CONSTRUCTOR_P (DECL_CONTEXT (x)))
+                         {
+                           if (flags & tf_error)
+                             sorry ("calling a member function of the "
+                                    "object being constructed in a constant "
+                                    "expression");
+                           return false;
+                         }
+                       /* Otherwise OK.  */;
+                     }
                    else if (!potential_constant_expression_1 (x, rval, flags))
                      return false;
                    i = 1;
@@ -7831,6 +8157,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case STMT_EXPR:
     case EXPR_STMT:
     case BIND_EXPR:
+    case TRANSACTION_EXPR:
       if (flags & tf_error)
         error ("expression %qE is not a constant-expression", t);
       return false;
@@ -7907,6 +8234,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case CONST_CAST_EXPR:
     case STATIC_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       return (potential_constant_expression_1
              (TREE_OPERAND (t, 0),
               TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
@@ -8054,6 +8382,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
          return false;
       return true;
 
+    case FMA_EXPR:
+     for (i = 0; i < 3; ++i)
+      if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
+                                           true, flags))
+       return false;
+     return true;
+
     case COND_EXPR:
     case VEC_COND_EXPR:
       /* If the condition is a known constant, we know which of the legs we
@@ -8087,7 +8422,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       return false;
 
     default:
-      sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]);
+      sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
       gcc_unreachable();
       return false;
     }
@@ -8202,7 +8537,7 @@ build_lambda_object (tree lambda_expr)
 
   /* N2927: "[The closure] class type is not an aggregate."
      But we briefly treat it as an aggregate to make this simpler.  */
-  type = TREE_TYPE (lambda_expr);
+  type = LAMBDA_EXPR_CLOSURE (lambda_expr);
   CLASSTYPE_NON_AGGREGATE (type) = 0;
   expr = finish_compound_literal (type, expr, tf_warning_or_error);
   CLASSTYPE_NON_AGGREGATE (type) = 1;
@@ -8243,7 +8578,7 @@ begin_lambda_type (tree lambda)
   type = begin_class_definition (type, /*attributes=*/NULL_TREE);
 
   /* Cross-reference the expression and the type.  */
-  TREE_TYPE (lambda) = type;
+  LAMBDA_EXPR_CLOSURE (lambda) = type;
   CLASSTYPE_LAMBDA_EXPR (type) = lambda;
 
   return type;
@@ -8256,18 +8591,14 @@ tree
 lambda_return_type (tree expr)
 {
   tree type;
-  if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+  if (type_unknown_p (expr)
+      || BRACE_ENCLOSED_INITIALIZER_P (expr))
     {
-      warning (0, "cannot deduce lambda return type from a braced-init-list");
+      cxx_incomplete_type_error (expr, TREE_TYPE (expr));
       return void_type_node;
     }
   if (type_dependent_expression_p (expr))
-    {
-      type = cxx_make_type (DECLTYPE_TYPE);
-      DECLTYPE_TYPE_EXPR (type) = expr;
-      DECLTYPE_FOR_LAMBDA_RETURN (type) = true;
-      SET_TYPE_STRUCTURAL_EQUALITY (type);
-    }
+    type = dependent_lambda_return_type_node;
   else
     type = cv_unqualified (type_decays_to (unlowered_expr_type (expr)));
   return type;
@@ -8281,7 +8612,7 @@ lambda_function (tree lambda)
 {
   tree type;
   if (TREE_CODE (lambda) == LAMBDA_EXPR)
-    type = TREE_TYPE (lambda);
+    type = LAMBDA_EXPR_CLOSURE (lambda);
   else
     type = lambda;
   gcc_assert (LAMBDA_TYPE_P (type));
@@ -8327,12 +8658,10 @@ apply_lambda_return_type (tree lambda, tree return_type)
 
   LAMBDA_EXPR_RETURN_TYPE (lambda) = return_type;
 
-  /* If we got a DECLTYPE_TYPE, don't stick it in the function yet,
-     it would interfere with instantiating the closure type.  */
-  if (dependent_type_p (return_type))
-    return;
   if (return_type == error_mark_node)
     return;
+  if (TREE_TYPE (TREE_TYPE (fco)) == return_type)
+    return;
 
   /* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE
      TREE_TYPE (METHOD_TYPE)   == return-type  */
@@ -8345,6 +8674,7 @@ apply_lambda_return_type (tree lambda, tree return_type)
   /* We already have a DECL_RESULT from start_preparsed_function.
      Now we need to redo the work it and allocate_struct_function
      did to reflect the new type.  */
+  gcc_assert (current_function_decl == fco);
   result = build_decl (input_location, RESULT_DECL, NULL_TREE,
                       TYPE_MAIN_VARIANT (return_type));
   DECL_ARTIFICIAL (result) = 1;
@@ -8449,7 +8779,7 @@ is_normal_capture_proxy (tree decl)
 static inline void
 insert_capture_proxy (tree var)
 {
-  cxx_scope *b;
+  cp_binding_level *b;
   int skip;
   tree stmt_list;
 
@@ -8458,7 +8788,7 @@ insert_capture_proxy (tree var)
   b = current_binding_level;
   for (skip = 0; ; ++skip)
     {
-      cxx_scope *n = b->level_chain;
+      cp_binding_level *n = b->level_chain;
       if (n->kind == sk_function_parms)
        break;
       b = n;
@@ -8581,6 +8911,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
       if (!real_lvalue_p (initializer))
        error ("cannot capture %qE by reference", initializer);
     }
+  else
+    /* Capture by copy requires a complete type.  */
+    type = complete_type (type);
 
   /* Add __ to the beginning of the field name so that user code
      won't find the field with name lookup.  We can't just leave the name
@@ -8594,7 +8927,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
 
   /* If TREE_TYPE isn't set, we're still in the introducer, so check
      for duplicates.  */
-  if (!TREE_TYPE (lambda))
+  if (!LAMBDA_EXPR_CLOSURE (lambda))
     {
       if (IDENTIFIER_MARKED (name))
        {
@@ -8620,13 +8953,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
     LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
 
   /* Add it to the appropriate closure class if we've started it.  */
-  if (current_class_type && current_class_type == TREE_TYPE (lambda))
+  if (current_class_type
+      && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
     finish_member_declaration (member);
 
   LAMBDA_EXPR_CAPTURE_LIST (lambda)
     = tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
 
-  if (TREE_TYPE (lambda))
+  if (LAMBDA_EXPR_CLOSURE (lambda))
     return build_capture_proxy (member);
   /* For explicit captures we haven't started the function yet, so we wait
      and build the proxy from cp_parser_lambda_body.  */
@@ -8669,7 +9003,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
     {
       tree lambda = TREE_VALUE (node);
 
-      current_class_type = TREE_TYPE (lambda);
+      current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
       var = add_capture (lambda,
                             id,
                             initializer,
@@ -8700,7 +9034,7 @@ lambda_expr_this_capture (tree lambda)
   if (!this_capture
       && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
     {
-      tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
+      tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
       tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
       tree init = NULL_TREE;
 
@@ -8750,7 +9084,8 @@ lambda_expr_this_capture (tree lambda)
   else
     {
       /* To make sure that current_class_ref is for the lambda.  */
-      gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
+      gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+                 == LAMBDA_EXPR_CLOSURE (lambda));
 
       result = this_capture;
 
@@ -8805,6 +9140,9 @@ maybe_add_lambda_conv_op (tree type)
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
     return;
 
+  if (processing_template_decl)
+    return;
+
   stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
                                  FUNCTION_ARG_CHAIN (callop));
 
@@ -8869,6 +9207,10 @@ maybe_add_lambda_conv_op (tree type)
 
   if (nested)
     push_function_context ();
+  else
+    /* Still increment function_depth so that we don't GC in the
+       middle of an expression.  */
+    ++function_depth;
 
   /* Generate the body of the thunk.  */
 
@@ -8877,14 +9219,8 @@ maybe_add_lambda_conv_op (tree type)
   if (DECL_ONE_ONLY (statfn))
     {
       /* Put the thunk in the same comdat group as the call op.  */
-      struct cgraph_node *callop_node, *thunk_node;
-      DECL_COMDAT_GROUP (statfn) = cxx_comdat_group (callop);
-      callop_node = cgraph_get_create_node (callop);
-      thunk_node = cgraph_get_create_node (statfn);
-      gcc_assert (callop_node->same_comdat_group == NULL);
-      gcc_assert (thunk_node->same_comdat_group == NULL);
-      callop_node->same_comdat_group = thunk_node;
-      thunk_node->same_comdat_group = callop_node;
+      cgraph_add_to_same_comdat_group (cgraph_get_create_node (statfn),
+                                      cgraph_get_create_node (callop));
     }
   body = begin_function_body ();
   compound_stmt = begin_compound_stmt (0);
@@ -8927,6 +9263,8 @@ maybe_add_lambda_conv_op (tree type)
 
   if (nested)
     pop_function_context ();
+  else
+    --function_depth;
 }
 
 /* Returns true iff VAL is a lambda-related declaration which should