OSDN Git Service

PR c++/57047
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 89c76d5..e0c1c1f 100644 (file)
@@ -4,7 +4,7 @@
    and during the instantiation of template functions.
 
    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
    and during the instantiation of template functions.
 
    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-                2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+                2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
 
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
 
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
 #include "tree-inline.h"
 #include "c-family/c-common.h"
 #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"
 #include "toplev.h"
 #include "flags.h"
 #include "output.h"
@@ -423,7 +423,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.  */
 
    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 ())
 maybe_cleanup_point_expr_void (tree expr)
 {
   if (!processing_template_decl && stmts_are_full_exprs_p ())
@@ -994,6 +994,15 @@ finish_range_for_decl (tree range_for_stmt, tree decl, tree expr)
 tree
 finish_break_stmt (void)
 {
 tree
 finish_break_stmt (void)
 {
+  /* In switch statements break is sometimes stylistically used after
+     a return statement.  This can lead to spurious warnings about
+     control reaching the end of a non-void function when it is
+     inlined.  Note that we are calling block_may_fallthru with
+     language specific tree nodes; this works because
+     block_may_fallthru returns true when given something it does not
+     understand.  */
+  if (!block_may_fallthru (cur_stmt_list))
+    return void_zero_node;
   return add_stmt (build_stmt (input_location, BREAK_STMT));
 }
 
   return add_stmt (build_stmt (input_location, BREAK_STMT));
 }
 
@@ -1561,9 +1570,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
       else
        {
          /* Set the cv qualifiers.  */
       else
        {
          /* Set the cv qualifiers.  */
-         int quals = (current_class_ref
-                      ? cp_type_quals (TREE_TYPE (current_class_ref))
-                      : TYPE_UNQUALIFIED);
+         int quals = cp_type_quals (TREE_TYPE (object));
 
          if (DECL_MUTABLE_P (decl))
            quals &= ~TYPE_QUAL_CONST;
 
          if (DECL_MUTABLE_P (decl))
            quals &= ~TYPE_QUAL_CONST;
@@ -2312,19 +2319,6 @@ tree
 finish_unary_op_expr (enum tree_code code, tree expr)
 {
   tree result = build_x_unary_op (code, expr, tf_warning_or_error);
 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);
 
   if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
     overflow_warning (input_location, result);
 
@@ -2381,8 +2375,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);
       && check_array_initializer (NULL_TREE, type, compound_literal))
     return error_mark_node;
   compound_literal = reshape_init (type, compound_literal, complain);
-  if (cxx_dialect >= cxx0x && SCALAR_TYPE_P (type)
-      && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal))
+  if (SCALAR_TYPE_P (type)
+      && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)
+      && (complain & tf_warning_or_error))
     check_narrowing (type, compound_literal);
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == NULL_TREE)
     check_narrowing (type, compound_literal);
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == NULL_TREE)
@@ -2518,7 +2513,7 @@ check_template_template_default_arg (tree argument)
 /* Begin a class definition, as indicated by T.  */
 
 tree
 /* Begin a class definition, as indicated by T.  */
 
 tree
-begin_class_definition (tree t, tree attributes)
+begin_class_definition (tree t)
 {
   if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
     return error_mark_node;
 {
   if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
     return error_mark_node;
@@ -2575,9 +2570,6 @@ begin_class_definition (tree t, tree attributes)
   pushclass (t);
   TYPE_BEING_DEFINED (t) = 1;
 
   pushclass (t);
   TYPE_BEING_DEFINED (t) = 1;
 
-  cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
-  fixup_attribute_variants (t);
-
   if (flag_pack_struct)
     {
       tree v;
   if (flag_pack_struct)
     {
       tree v;
@@ -2670,9 +2662,15 @@ finish_member_declaration (tree decl)
        }
     }
   /* Enter the DECL into the scope of the class.  */
        }
     }
   /* Enter the DECL into the scope of the class.  */
-  else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
-          || pushdecl_class_level (decl))
+  else if (pushdecl_class_level (decl))
     {
     {
+      if (TREE_CODE (decl) == USING_DECL)
+       {
+         /* For now, ignore class-scope USING_DECLS, so that
+            debugging backends do not see them. */
+         DECL_IGNORED_P (decl) = 1;
+       }
+
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
         go at the beginning.  The reason is that lookup_field_1
         searches the list in order, and we want a field name to
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
         go at the beginning.  The reason is that lookup_field_1
         searches the list in order, and we want a field name to
@@ -2745,15 +2743,17 @@ finish_template_decl (tree parms)
 tree
 finish_template_type (tree name, tree args, int entering_scope)
 {
 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);
                                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.
 }
 
 /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
@@ -2802,39 +2802,44 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 tree
 baselink_for_fns (tree fns)
 {
 tree
 baselink_for_fns (tree fns)
 {
-  tree fn;
+  tree scope;
   tree cl;
 
   if (BASELINK_P (fns) 
       || error_operand_p (fns))
     return fns;
   tree cl;
 
   if (BASELINK_P (fns) 
       || error_operand_p (fns))
     return fns;
-  
-  fn = fns;
-  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-    fn = TREE_OPERAND (fn, 0);
-  fn = get_first_fn (fn);
-  if (!DECL_FUNCTION_MEMBER_P (fn))
+
+  scope = ovl_scope (fns);
+  if (!CLASS_TYPE_P (scope))
     return fns;
 
     return fns;
 
-  cl = currently_open_derived_class (DECL_CONTEXT (fn));
+  cl = currently_open_derived_class (scope);
   if (!cl)
   if (!cl)
-    cl = DECL_CONTEXT (fn);
+    cl = scope;
   cl = TYPE_BINFO (cl);
   return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
 }
 
   cl = TYPE_BINFO (cl);
   return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
 }
 
-/* Returns true iff DECL is an automatic variable from a function outside
+/* Returns true iff DECL is a variable from a function outside
    the current one.  */
 
 static bool
    the current one.  */
 
 static bool
-outer_automatic_var_p (tree decl)
+outer_var_p (tree decl)
 {
   return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
          && DECL_FUNCTION_SCOPE_P (decl)
 {
   return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
          && DECL_FUNCTION_SCOPE_P (decl)
-         && !TREE_STATIC (decl)
          && DECL_CONTEXT (decl) != current_function_decl);
 }
 
          && DECL_CONTEXT (decl) != current_function_decl);
 }
 
+/* As above, but also checks that DECL is automatic.  */
+
+static bool
+outer_automatic_var_p (tree decl)
+{
+  return (outer_var_p (decl)
+         && !TREE_STATIC (decl));
+}
+
 /* ID_EXPRESSION is a representation of parsed, but unprocessed,
    id-expression.  (See cp_parser_id_expression for details.)  SCOPE,
    if non-NULL, is the type or namespace used to explicitly qualify
 /* ID_EXPRESSION is a representation of parsed, but unprocessed,
    id-expression.  (See cp_parser_id_expression for details.)  SCOPE,
    if non-NULL, is the type or namespace used to explicitly qualify
@@ -2883,6 +2888,8 @@ finish_id_expression (tree id_expression,
                      const char **error_msg,
                      location_t location)
 {
                      const char **error_msg,
                      location_t location)
 {
+  decl = strip_using_decl (decl);
+
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
   *error_msg = NULL;
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
   *error_msg = NULL;
@@ -2939,9 +2946,18 @@ finish_id_expression (tree id_expression,
 
       /* Disallow uses of local variables from containing functions, except
         within lambda-expressions.  */
 
       /* Disallow uses of local variables from containing functions, except
         within lambda-expressions.  */
-      if (outer_automatic_var_p (decl)
+      if (!outer_var_p (decl)
          /* It's not a use (3.2) if we're in an unevaluated context.  */
          /* It's not a use (3.2) if we're in an unevaluated context.  */
-         && !cp_unevaluated_operand)
+         || cp_unevaluated_operand)
+       /* OK.  */;
+      else if (TREE_STATIC (decl))
+       {
+         if (processing_template_decl)
+           /* For a use of an outer static var, return the identifier so
+              that we'll look it up again in the instantiation.  */
+           return id_expression;
+       }
+      else
        {
          tree context = DECL_CONTEXT (decl);
          tree containing_function = current_function_decl;
        {
          tree context = DECL_CONTEXT (decl);
          tree containing_function = current_function_decl;
@@ -2960,7 +2976,14 @@ finish_id_expression (tree id_expression,
 
             FIXME update for final resolution of core issue 696.  */
          if (decl_constant_var_p (decl))
 
             FIXME update for final resolution of core issue 696.  */
          if (decl_constant_var_p (decl))
-           return integral_constant_value (decl);
+           {
+             if (processing_template_decl)
+               /* In a template, the constant value may not be in a usable
+                  form, so look it up again at instantiation time.  */
+               return id_expression;
+             else
+               return integral_constant_value (decl);
+           }
 
          /* If we are in a lambda function, we can move out until we hit
             1. the context,
 
          /* If we are in a lambda function, we can move out until we hit
             1. the context,
@@ -2998,8 +3021,8 @@ finish_id_expression (tree id_expression,
          else
            {
              error (TREE_CODE (decl) == VAR_DECL
          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;
            }
              error ("  %q+#D declared here", decl);
              return error_mark_node;
            }
@@ -3298,8 +3321,9 @@ finish_id_expression (tree id_expression,
          if (TREE_CODE (first_fn) == TEMPLATE_DECL)
            first_fn = DECL_TEMPLATE_RESULT (first_fn);
 
          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
 
          if (!template_arg_p
              && TREE_CODE (first_fn) == FUNCTION_DECL
@@ -3390,7 +3414,7 @@ finish_underlying_type (tree type)
 
   if (TREE_CODE (type) != ENUMERAL_TYPE)
     {
 
   if (TREE_CODE (type) != ENUMERAL_TYPE)
     {
-      error ("%qE is not an enumeration type", type);
+      error ("%qT is not an enumeration type", type);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -3407,6 +3431,149 @@ finish_underlying_type (tree type)
   return underlying_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.  */
 
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */
 
@@ -3437,7 +3604,7 @@ finish_offsetof (tree expr)
       if (!complete_type_or_else (TREE_TYPE (object), object))
        return error_mark_node;
     }
       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
 }
 
 /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  This
@@ -3910,6 +4077,8 @@ finish_omp_clauses (tree clauses)
          t = maybe_convert_cond (t);
          if (t == error_mark_node)
            remove = true;
          t = maybe_convert_cond (t);
          if (t == error_mark_node)
            remove = true;
+         else if (!processing_template_decl)
+           t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
          OMP_CLAUSE_IF_EXPR (c) = t;
          break;
 
          OMP_CLAUSE_IF_EXPR (c) = t;
          break;
 
@@ -3918,6 +4087,8 @@ finish_omp_clauses (tree clauses)
          t = maybe_convert_cond (t);
          if (t == error_mark_node)
            remove = true;
          t = maybe_convert_cond (t);
          if (t == error_mark_node)
            remove = true;
+         else if (!processing_template_decl)
+           t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
          OMP_CLAUSE_FINAL_EXPR (c) = t;
          break;
 
          OMP_CLAUSE_FINAL_EXPR (c) = t;
          break;
 
@@ -3931,6 +4102,13 @@ finish_omp_clauses (tree clauses)
              error ("num_threads expression must be integral");
              remove = true;
            }
              error ("num_threads expression must be integral");
              remove = true;
            }
+         else
+           {
+             t = mark_rvalue_use (t);
+             if (!processing_template_decl)
+               t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+             OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+           }
          break;
 
        case OMP_CLAUSE_SCHEDULE:
          break;
 
        case OMP_CLAUSE_SCHEDULE:
@@ -3945,6 +4123,13 @@ finish_omp_clauses (tree clauses)
              error ("schedule chunk size expression must be integral");
              remove = true;
            }
              error ("schedule chunk size expression must be integral");
              remove = true;
            }
+         else
+           {
+             t = mark_rvalue_use (t);
+             if (!processing_template_decl)
+               t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+             OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+           }
          break;
 
        case OMP_CLAUSE_NOWAIT:
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -4797,7 +4982,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
 void
 finish_omp_barrier (void)
 {
 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);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4807,7 +4992,7 @@ finish_omp_barrier (void)
 void
 finish_omp_flush (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);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4817,7 +5002,7 @@ finish_omp_flush (void)
 void
 finish_omp_taskwait (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);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4827,13 +5012,91 @@ finish_omp_taskwait (void)
 void
 finish_omp_taskyield (void)
 {
 void
 finish_omp_taskyield (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  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
   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.  If NOEX is non-NULL, we wrap the body in
+   a MUST_NOT_THROW_EXPR with NOEX as condition.  */
+
+void
+finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex)
+{
+  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;
+
+  /* noexcept specifications are not allowed for function transactions.  */
+  gcc_assert (!(noex && compound_stmt));
+  if (noex)
+    {
+      tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt),
+                                            noex);
+      SET_EXPR_LOCATION (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt)));
+      TREE_SIDE_EFFECTS (body) = 1;
+      TRANSACTION_EXPR_BODY (stmt) = body;
+    }
+
+  if (compound_stmt)
+    finish_compound_stmt (compound_stmt);
+  finish_stmt ();
+}
+
+/* Build a __transaction_atomic or __transaction_relaxed expression.  If
+   NOEX is non-NULL, we wrap the body in a MUST_NOT_THROW_EXPR with NOEX as
+   condition.  */
+
+tree
+build_transaction_expr (location_t loc, tree expr, int flags, tree noex)
+{
+  tree ret;
+  if (noex)
+    {
+      expr = build_must_not_throw_expr (expr, noex);
+      SET_EXPR_LOCATION (expr, loc);
+      TREE_SIDE_EFFECTS (expr) = 1;
+    }
+  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)
 {
 void
 init_cp_semantics (void)
 {
@@ -4888,7 +5151,7 @@ finish_static_assert (tree condition, tree message, location_t location,
       if (TREE_CODE (condition) == INTEGER_CST 
           && integer_zerop (condition))
         /* Report the error. */
       if (TREE_CODE (condition) == INTEGER_CST 
           && integer_zerop (condition))
         /* Report the error. */
-        error ("static assertion failed: %E", message);
+        error ("static assertion failed: %s", TREE_STRING_POINTER (message));
       else if (condition && condition != error_mark_node)
        {
          error ("non-constant condition for static assertion");
       else if (condition && condition != error_mark_node)
        {
          error ("non-constant condition for static assertion");
@@ -4984,7 +5247,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
            step.  */
         expr = TREE_OPERAND (expr, 1);
 
            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);
 
         /* See through BASELINK nodes to the underlying function.  */
         expr = BASELINK_FUNCTIONS (expr);
 
@@ -5023,8 +5286,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
           gcc_unreachable ();
 
         case INTEGER_CST:
           gcc_unreachable ();
 
         case INTEGER_CST:
+       case PTRMEM_CST:
           /* We can get here when the id-expression refers to an
           /* We can get here when the id-expression refers to an
-             enumerator.  */
+             enumerator or non-type template parameter.  */
           type = TREE_TYPE (expr);
           break;
 
           type = TREE_TYPE (expr);
           break;
 
@@ -5109,6 +5373,7 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
       else if (copy_fn_p (fn) <= 0)
        continue;
 
       else if (copy_fn_p (fn) <= 0)
        continue;
 
+      maybe_instantiate_noexcept (fn);
       if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
        return false;
     }
       if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
        return false;
     }
@@ -5150,7 +5415,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
       return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
              || (CLASS_TYPE_P (type1)
                  && (t = locate_ctor (type1))
       return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
              || (CLASS_TYPE_P (type1)
                  && (t = locate_ctor (type1))
-                 && TYPE_NOTHROW_P (TREE_TYPE (t))));
+                 && (maybe_instantiate_noexcept (t),
+                     TYPE_NOTHROW_P (TREE_TYPE (t)))));
 
     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
       type1 = strip_array_types (type1);
 
     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
       type1 = strip_array_types (type1);
@@ -5199,6 +5465,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return (type_code1 == ENUMERAL_TYPE);
 
     case CPTK_IS_ENUM:
       return (type_code1 == ENUMERAL_TYPE);
 
+    case CPTK_IS_FINAL:
+      return (CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1));
+
     case CPTK_IS_LITERAL_TYPE:
       return (literal_type_p (type1));
 
     case CPTK_IS_LITERAL_TYPE:
       return (literal_type_p (type1));
 
@@ -5223,23 +5492,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)
 {
 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)))
   if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
       && COMPLETE_TYPE_P (TREE_TYPE (type)))
-    return true;
+    return type;
 
   if (VOID_TYPE_P (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.  */
 }
 
 /* Process a trait expression.  */
@@ -5261,6 +5527,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
              || kind == CPTK_IS_CONVERTIBLE_TO
              || kind == CPTK_IS_EMPTY
              || kind == CPTK_IS_ENUM
              || kind == CPTK_IS_CONVERTIBLE_TO
              || kind == CPTK_IS_EMPTY
              || kind == CPTK_IS_ENUM
+             || kind == CPTK_IS_FINAL
              || kind == CPTK_IS_LITERAL_TYPE
              || kind == CPTK_IS_POD
              || kind == CPTK_IS_POLYMORPHIC
              || kind == CPTK_IS_LITERAL_TYPE
              || kind == CPTK_IS_POD
              || kind == CPTK_IS_POLYMORPHIC
@@ -5289,10 +5556,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       return trait_expr;
     }
 
       return trait_expr;
     }
 
-  complete_type (type1);
-  if (type2)
-    complete_type (type2);
-
   switch (kind)
     {
     case CPTK_HAS_NOTHROW_ASSIGN:
   switch (kind)
     {
     case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5305,26 +5568,22 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
     case CPTK_IS_ABSTRACT:
     case CPTK_IS_EMPTY:
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
     case CPTK_IS_ABSTRACT:
     case CPTK_IS_EMPTY:
+    case CPTK_IS_FINAL:
     case CPTK_IS_LITERAL_TYPE:
     case CPTK_IS_POD:
     case CPTK_IS_POLYMORPHIC:
     case CPTK_IS_STD_LAYOUT:
     case CPTK_IS_TRIVIAL:
       if (!check_trait_type (type1))
     case CPTK_IS_LITERAL_TYPE:
     case CPTK_IS_POD:
     case CPTK_IS_POLYMORPHIC:
     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)
       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:
       break;
 
     case CPTK_IS_CLASS:
@@ -5497,6 +5756,12 @@ is_valid_constexpr_fn (tree fun, bool complain)
            }
        }
     }
            }
        }
     }
+  else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun)))
+    {
+      ret = false;
+      if (complain)
+       error ("%q#T has virtual base classes", DECL_CONTEXT (fun));
+    }
 
   return ret;
 }
 
   return ret;
 }
@@ -5544,15 +5809,19 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
       member = TREE_OPERAND (t, 0);
       init = unshare_expr (TREE_OPERAND (t, 1));
     }
       member = TREE_OPERAND (t, 0);
       init = unshare_expr (TREE_OPERAND (t, 1));
     }
-  else
+  else if (TREE_CODE (t) == CALL_EXPR)
     {
     {
-      gcc_assert (TREE_CODE (t) == CALL_EXPR);
       member = CALL_EXPR_ARG (t, 0);
       /* We don't use build_cplus_new here because it complains about
         abstract bases.  Leaving the call unwrapped means that it has the
         wrong type, but cxx_eval_constant_expression doesn't care.  */
       init = unshare_expr (t);
     }
       member = CALL_EXPR_ARG (t, 0);
       /* We don't use build_cplus_new here because it complains about
         abstract bases.  Leaving the call unwrapped means that it has the
         wrong type, but cxx_eval_constant_expression doesn't care.  */
       init = unshare_expr (t);
     }
+  else if (TREE_CODE (t) == DECL_EXPR)
+    /* Declaring a temporary, don't add it to the CONSTRUCTOR.  */
+    return true;
+  else
+    gcc_unreachable ();
   if (TREE_CODE (member) == INDIRECT_REF)
     member = TREE_OPERAND (member, 0);
   if (TREE_CODE (member) == NOP_EXPR)
   if (TREE_CODE (member) == INDIRECT_REF)
     member = TREE_OPERAND (member, 0);
   if (TREE_CODE (member) == NOP_EXPR)
@@ -5568,14 +5837,17 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
             the const_cast.  */
          member = op;
        }
             the const_cast.  */
          member = op;
        }
+      else if (op == current_class_ptr
+              && (same_type_ignoring_top_level_qualifiers_p
+                  (TREE_TYPE (TREE_TYPE (member)),
+                   current_class_type)))
+       /* Delegating constructor.  */
+       member = op;
       else
        {
       else
        {
-         /* We don't put out anything for an empty base.  */
+         /* This is an initializer for an empty base; keep it for now so
+            we can check it in cxx_eval_bare_aggregate.  */
          gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
          gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
-         /* But if the initializer isn't constexpr, leave it in so we
-            complain later.  */
-         if (potential_constant_expression (init))
-           return true;
        }
     }
   if (TREE_CODE (member) == ADDR_EXPR)
        }
     }
   if (TREE_CODE (member) == ADDR_EXPR)
@@ -5632,6 +5904,44 @@ check_constexpr_ctor_body (tree last, tree list)
   return ok;
 }
 
   return ok;
 }
 
+/* VEC is a vector of constructor elements built up for the base and member
+   initializers of a constructor for TYPE.  They need to be in increasing
+   offset order, which they might not be yet if TYPE has a primary base
+   which is not first in the base-clause or a vptr and at least one base
+   all of which are non-primary.  */
+
+static VEC(constructor_elt,gc) *
+sort_constexpr_mem_initializers (tree type, VEC(constructor_elt,gc) *vec)
+{
+  tree pri = CLASSTYPE_PRIMARY_BINFO (type);
+  tree field_type;
+  constructor_elt elt;
+  int i;
+
+  if (pri)
+    field_type = BINFO_TYPE (pri);
+  else if (TYPE_CONTAINS_VPTR_P (type))
+    field_type = vtbl_ptr_type_node;
+  else
+    return vec;
+
+  /* Find the element for the primary base or vptr and move it to the
+     beginning of the vec.  */
+  for (i = 0; ; ++i)
+    if (TREE_TYPE (VEC_index (constructor_elt, vec, i)->index) == field_type)
+      break;
+
+  if (i > 0)
+    {
+      elt = *VEC_index (constructor_elt, vec, i);
+      for (; i > 0; --i)
+       VEC_replace (constructor_elt, vec, i,
+                    VEC_index (constructor_elt, vec, i-1));
+      VEC_replace (constructor_elt, vec, 0, &elt);
+    }
+  return vec;
+}
+
 /* Build compile-time evalable representations of member-initializer list
    for a constexpr constructor.  */
 
 /* Build compile-time evalable representations of member-initializer list
    for a constexpr constructor.  */
 
@@ -5671,10 +5981,26 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
            break;
        }
     }
            break;
        }
     }
+  else if (EXPR_P (body))
+    ok = build_data_member_initialization (body, &vec);
   else
     gcc_assert (errorcount > 0);
   if (ok)
   else
     gcc_assert (errorcount > 0);
   if (ok)
-    return build_constructor (type, vec);
+    {
+      if (VEC_length (constructor_elt, vec) > 0)
+       {
+         /* In a delegating constructor, return the target.  */
+         constructor_elt *ce = VEC_index (constructor_elt, vec, 0);
+         if (ce->index == current_class_ptr)
+           {
+             body = ce->value;
+             VEC_free (constructor_elt, gc, vec);
+             return body;
+           }
+       }
+      vec = sort_constexpr_mem_initializers (type, vec);
+      return build_constructor (type, vec);
+    }
   else
     return error_mark_node;
 }
   else
     return error_mark_node;
 }
@@ -5740,12 +6066,12 @@ massage_constexpr_body (tree fun, tree body)
       (DECL_CONTEXT (fun), body);
   else
     {
       (DECL_CONTEXT (fun), body);
   else
     {
-      if (TREE_CODE (body) == BIND_EXPR)
-       body = BIND_EXPR_BODY (body);
       if (TREE_CODE (body) == EH_SPEC_BLOCK)
         body = EH_SPEC_STMTS (body);
       if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
        body = TREE_OPERAND (body, 0);
       if (TREE_CODE (body) == EH_SPEC_BLOCK)
         body = EH_SPEC_STMTS (body);
       if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
        body = TREE_OPERAND (body, 0);
+      if (TREE_CODE (body) == BIND_EXPR)
+       body = BIND_EXPR_BODY (body);
       body = constexpr_fn_retval (body);
     }
   return body;
       body = constexpr_fn_retval (body);
     }
   return body;
@@ -5760,13 +6086,28 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
   bool bad;
   tree field;
   unsigned i, nelts;
   bool bad;
   tree field;
   unsigned i, nelts;
+  tree ctype;
 
   if (TREE_CODE (body) != CONSTRUCTOR)
     return false;
 
 
   if (TREE_CODE (body) != CONSTRUCTOR)
     return false;
 
-  bad = false;
   nelts = CONSTRUCTOR_NELTS (body);
   nelts = CONSTRUCTOR_NELTS (body);
-  field = TYPE_FIELDS (DECL_CONTEXT (fun));
+  ctype = DECL_CONTEXT (fun);
+  field = TYPE_FIELDS (ctype);
+
+  if (TREE_CODE (ctype) == UNION_TYPE)
+    {
+      if (nelts == 0 && next_initializable_field (field))
+       {
+         if (complain)
+           error ("%<constexpr%> constructor for union %qT must "
+                  "initialize exactly one non-static data member", ctype);
+         return true;
+       }
+      return false;
+    }
+
+  bad = false;
   for (i = 0; i <= nelts; ++i)
     {
       tree index;
   for (i = 0; i <= nelts; ++i)
     {
       tree index;
@@ -5776,26 +6117,29 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
        {
          index = CONSTRUCTOR_ELT (body, i)->index;
          /* Skip base and vtable inits.  */
        {
          index = CONSTRUCTOR_ELT (body, i)->index;
          /* Skip base and vtable inits.  */
-         if (TREE_CODE (index) != FIELD_DECL)
+         if (TREE_CODE (index) != FIELD_DECL
+             || DECL_ARTIFICIAL (index))
            continue;
        }
       for (; field != index; field = DECL_CHAIN (field))
        {
          tree ftype;
          if (TREE_CODE (field) != 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)))
+             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+             || DECL_ARTIFICIAL (field))
            continue;
            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.  */
          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));
+             gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype)
+                                  || errorcount != 0);
              continue;
            }
              continue;
            }
+         if (!complain)
+           return true;
          error ("uninitialized member %qD in %<constexpr%> constructor",
                 field);
          bad = true;
          error ("uninitialized member %qD in %<constexpr%> constructor",
                 field);
          bad = true;
@@ -6303,7 +6647,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
   else
     {
       result = entry->result;
   else
     {
       result = entry->result;
-      if (!result || (result == error_mark_node && !allow_non_constant))
+      if (!result || result == error_mark_node)
        result = (cxx_eval_constant_expression
                  (&new_call, new_call.fundef->body,
                   allow_non_constant, addr,
        result = (cxx_eval_constant_expression
                  (&new_call, new_call.fundef->body,
                   allow_non_constant, addr,
@@ -6561,6 +6905,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
        error ("%qE is not a constant expression", orig_whole);
       *non_constant_p = true;
     }
        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)
   if (*non_constant_p)
     return t;
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
@@ -6753,6 +7103,12 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
          constructor_elt *inner = base_field_constructor_elt (n, ce->index);
          inner->value = elt;
        }
          constructor_elt *inner = base_field_constructor_elt (n, ce->index);
          inner->value = elt;
        }
+      else if (TREE_CODE (ce->index) == NOP_EXPR)
+       {
+         /* This is an initializer for an empty base; now that we've
+            checked that it's constant, we can ignore it.  */
+         gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (ce->index))));
+       }
       else
        CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
     }
       else
        CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
     }
@@ -6826,7 +7182,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
       if (TREE_CODE (elttype) == ARRAY_TYPE)
        {
          /* A multidimensional array; recurse.  */
       if (TREE_CODE (elttype) == ARRAY_TYPE)
        {
          /* A multidimensional array; recurse.  */
-         if (value_init)
+         if (value_init || init == NULL_TREE)
            eltinit = NULL_TREE;
          else
            eltinit = cp_build_array_ref (input_location, init, idx,
            eltinit = NULL_TREE;
          else
            eltinit = cp_build_array_ref (input_location, init, idx,
@@ -6915,7 +7271,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
   sub = op0;
   STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
   sub = op0;
   STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
-  gcc_assert (POINTER_TYPE_P (subtype));
+  if (!POINTER_TYPE_P (subtype))
+    return NULL_TREE;
 
   if (TREE_CODE (sub) == ADDR_EXPR)
     {
 
   if (TREE_CODE (sub) == ADDR_EXPR)
     {
@@ -7055,15 +7412,17 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
            }
        }
     }
            }
        }
     }
-  /* *(foo *)fooarrptreturn> (*fooarrptr)[0] */
+  /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
           && (same_type_ignoring_top_level_qualifiers_p
               (type, TREE_TYPE (TREE_TYPE (subtype)))))
     {
       tree type_domain;
       tree min_val = size_zero_node;
   else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
           && (same_type_ignoring_top_level_qualifiers_p
               (type, TREE_TYPE (TREE_TYPE (subtype)))))
     {
       tree type_domain;
       tree min_val = size_zero_node;
-      sub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
-      if (!sub)
+      tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
+      if (newsub)
+       sub = newsub;
+      else
        sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub);
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
        sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub);
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
@@ -7100,9 +7459,15 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t,
     {
       tree sub = op0;
       STRIP_NOPS (sub);
     {
       tree sub = op0;
       STRIP_NOPS (sub);
-      if (TREE_CODE (sub) == ADDR_EXPR
-         || TREE_CODE (sub) == POINTER_PLUS_EXPR)
+      if (TREE_CODE (sub) == POINTER_PLUS_EXPR)
+       {
+         sub = TREE_OPERAND (sub, 0);
+         STRIP_NOPS (sub);
+       }
+      if (TREE_CODE (sub) == ADDR_EXPR)
        {
        {
+         /* We couldn't fold to a constant value.  Make sure it's not
+            something we should have been able to fold.  */
          gcc_assert (!same_type_ignoring_top_level_qualifiers_p
                      (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
          /* DR 1188 says we don't have to deal with this.  */
          gcc_assert (!same_type_ignoring_top_level_qualifiers_p
                      (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
          /* DR 1188 says we don't have to deal with this.  */
@@ -7126,7 +7491,11 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t,
     }
 
   if (r == NULL_TREE)
     }
 
   if (r == NULL_TREE)
-    return t;
+    {
+      if (!addr)
+       VERIFY_CONSTANT (t);
+      return t;
+    }
   return r;
 }
 
   return r;
 }
 
@@ -7350,6 +7719,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
            /* Check that the LHS is constant and then discard it.  */
            cxx_eval_constant_expression (call, op0, allow_non_constant,
                                          false, non_constant_p);
            /* Check that the LHS is constant and then discard it.  */
            cxx_eval_constant_expression (call, op0, allow_non_constant,
                                          false, non_constant_p);
+           op1 = TREE_OPERAND (t, 1);
            r = cxx_eval_constant_expression (call, op1, allow_non_constant,
                                              addr, non_constant_p);
          }
            r = cxx_eval_constant_expression (call, op1, allow_non_constant,
                                              addr, non_constant_p);
          }
@@ -7459,17 +7829,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
        tree oldop = TREE_OPERAND (t, 0);
        tree op = oldop;
        tree to = TREE_TYPE (t);
        tree oldop = TREE_OPERAND (t, 0);
        tree op = oldop;
        tree to = TREE_TYPE (t);
-       tree source = TREE_TYPE (op);
-        if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (to)
-           && !(TREE_CODE (op) == COMPONENT_REF
-                && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (op, 0)))))
-          {
-            if (!allow_non_constant)
-              error ("conversion of expression %qE of pointer type "
-                     "cannot yield a constant expression", op);
-           *non_constant_p = true;
-           return t;
-          }
        op = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
                                           allow_non_constant, addr,
                                           non_constant_p);
        op = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
                                           allow_non_constant, addr,
                                           non_constant_p);
@@ -7494,8 +7853,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
       return t;
 
     case LAMBDA_EXPR:
       return t;
 
     case LAMBDA_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case PSEUDO_DTOR_EXPR:
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
@@ -7548,6 +7905,32 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
 
   verify_constant (r, allow_non_constant, &non_constant_p);
 
 
   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;
+    }
+
+  /* Technically we should check this for all subexpressions, but that
+     runs into problems with our internal representation of pointer
+     subtraction and the 5.19 rules are still in flux.  */
+  if (CONVERT_EXPR_CODE_P (TREE_CODE (r))
+      && ARITHMETIC_TYPE_P (TREE_TYPE (r))
+      && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR)
+    {
+      if (!allow_non_constant)
+       error ("conversion from pointer type %qT "
+              "to arithmetic type %qT in a constant-expression",
+              TREE_TYPE (TREE_OPERAND (r, 0)), TREE_TYPE (r));
+      non_constant_p = true;
+    }
+
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
   else if (non_constant_p && TREE_CONSTANT (t))
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
   else if (non_constant_p && TREE_CONSTANT (t))
@@ -7748,6 +8131,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case TEMPLATE_PARM_INDEX:
     case TRAIT_EXPR:
     case IDENTIFIER_NODE:
     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:
     case PARM_DECL:
       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
     case FIELD_DECL:
     case PARM_DECL:
@@ -7854,25 +8238,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case NOP_EXPR:
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
-      /* -- an array-to-pointer conversion that is applied to an lvalue
-            that designates an object with thread or automatic storage
-            duration;  FIXME not implemented as it breaks constexpr arrays;
-           need to fix the standard
-         -- a type conversion from a pointer or pointer-to-member type
-            to a literal type.  */
+      /* -- a reinterpret_cast.  FIXME not implemented, and this rule
+        may change to something more specific to type-punning (DR 1312).  */
       {
         tree from = TREE_OPERAND (t, 0);
       {
         tree from = TREE_OPERAND (t, 0);
-        tree source = TREE_TYPE (from);
-        tree target = TREE_TYPE (t);
-        if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (target)
-           && !(TREE_CODE (from) == COMPONENT_REF
-                && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (from, 0)))))
-          {
-            if (flags & tf_error)
-              error ("conversion of expression %qE of pointer type "
-                     "cannot yield a constant expression", from);
-            return false;
-          }
         return (potential_constant_expression_1
                (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
       }
         return (potential_constant_expression_1
                (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
       }
@@ -7960,6 +8329,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case STMT_EXPR:
     case EXPR_STMT:
     case BIND_EXPR:
     case STMT_EXPR:
     case EXPR_STMT:
     case BIND_EXPR:
+    case TRANSACTION_EXPR:
+    case IF_STMT:
+    case DO_STMT:
+    case FOR_STMT:
+    case WHILE_STMT:
       if (flags & tf_error)
         error ("expression %qE is not a constant-expression", t);
       return false;
       if (flags & tf_error)
         error ("expression %qE is not a constant-expression", t);
       return false;
@@ -8036,6 +8410,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 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));
       return (potential_constant_expression_1
              (TREE_OPERAND (t, 0),
               TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
@@ -8168,6 +8543,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case UNGT_EXPR:
     case UNGE_EXPR:
     case UNEQ_EXPR:
     case UNGT_EXPR:
     case UNGE_EXPR:
     case UNEQ_EXPR:
+    case LTGT_EXPR:
     case RANGE_EXPR:
     case COMPLEX_EXPR:
       want_rval = true;
     case RANGE_EXPR:
     case COMPLEX_EXPR:
       want_rval = true;
@@ -8223,7 +8599,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       return false;
 
     default:
       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;
     }
       gcc_unreachable();
       return false;
     }
@@ -8338,7 +8714,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.  */
 
   /* 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;
   CLASSTYPE_NON_AGGREGATE (type) = 0;
   expr = finish_compound_literal (type, expr, tf_warning_or_error);
   CLASSTYPE_NON_AGGREGATE (type) = 1;
@@ -8376,10 +8752,12 @@ begin_lambda_type (tree lambda)
   xref_basetypes (type, /*bases=*/NULL_TREE);
 
   /* Start the class.  */
   xref_basetypes (type, /*bases=*/NULL_TREE);
 
   /* Start the class.  */
-  type = begin_class_definition (type, /*attributes=*/NULL_TREE);
+  type = begin_class_definition (type);
+  if (type == error_mark_node)
+    return error_mark_node;
 
   /* Cross-reference the expression and the type.  */
 
   /* Cross-reference the expression and the type.  */
-  TREE_TYPE (lambda) = type;
+  LAMBDA_EXPR_CLOSURE (lambda) = type;
   CLASSTYPE_LAMBDA_EXPR (type) = lambda;
 
   return type;
   CLASSTYPE_LAMBDA_EXPR (type) = lambda;
 
   return type;
@@ -8413,7 +8791,7 @@ lambda_function (tree lambda)
 {
   tree type;
   if (TREE_CODE (lambda) == LAMBDA_EXPR)
 {
   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));
   else
     type = lambda;
   gcc_assert (LAMBDA_TYPE_P (type));
@@ -8422,7 +8800,8 @@ lambda_function (tree lambda)
       && !COMPLETE_OR_OPEN_TYPE_P (type))
     return NULL_TREE;
   lambda = lookup_member (type, ansi_opname (CALL_EXPR),
       && !COMPLETE_OR_OPEN_TYPE_P (type))
     return NULL_TREE;
   lambda = lookup_member (type, ansi_opname (CALL_EXPR),
-                         /*protect=*/0, /*want_type=*/false);
+                         /*protect=*/0, /*want_type=*/false,
+                         tf_warning_or_error);
   if (lambda)
     lambda = BASELINK_FUNCTIONS (lambda);
   return lambda;
   if (lambda)
     lambda = BASELINK_FUNCTIONS (lambda);
   return lambda;
@@ -8436,7 +8815,8 @@ tree
 lambda_capture_field_type (tree expr)
 {
   tree type;
 lambda_capture_field_type (tree expr)
 {
   tree type;
-  if (type_dependent_expression_p (expr))
+  if (type_dependent_expression_p (expr)
+      && !(TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE))
     {
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
     {
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
@@ -8577,17 +8957,16 @@ is_normal_capture_proxy (tree decl)
 /* VAR is a capture proxy created by build_capture_proxy; add it to the
    current function, which is the operator() for the appropriate lambda.  */
 
 /* VAR is a capture proxy created by build_capture_proxy; add it to the
    current function, which is the operator() for the appropriate lambda.  */
 
-static inline void
+void
 insert_capture_proxy (tree var)
 {
   cp_binding_level *b;
 insert_capture_proxy (tree var)
 {
   cp_binding_level *b;
-  int skip;
   tree stmt_list;
 
   /* Put the capture proxy in the extra body block so that it won't clash
      with a later local variable.  */
   b = current_binding_level;
   tree stmt_list;
 
   /* Put the capture proxy in the extra body block so that it won't clash
      with a later local variable.  */
   b = current_binding_level;
-  for (skip = 0; ; ++skip)
+  for (;;)
     {
       cp_binding_level *n = b->level_chain;
       if (n->kind == sk_function_parms)
     {
       cp_binding_level *n = b->level_chain;
       if (n->kind == sk_function_parms)
@@ -8598,8 +8977,7 @@ insert_capture_proxy (tree var)
 
   /* And put a DECL_EXPR in the STATEMENT_LIST for the same block.  */
   var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var);
 
   /* And put a DECL_EXPR in the STATEMENT_LIST for the same block.  */
   var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var);
-  stmt_list = VEC_index (tree, stmt_list_stack,
-                        VEC_length (tree, stmt_list_stack) - 1 - skip);
+  stmt_list = VEC_index (tree, stmt_list_stack, 1);
   gcc_assert (stmt_list);
   append_to_statement_list_force (var, &stmt_list);
 }
   gcc_assert (stmt_list);
   append_to_statement_list_force (var, &stmt_list);
 }
@@ -8641,7 +9019,8 @@ lambda_proxy_type (tree ref)
   if (REFERENCE_REF_P (ref))
     ref = TREE_OPERAND (ref, 0);
   type = TREE_TYPE (ref);
   if (REFERENCE_REF_P (ref))
     ref = TREE_OPERAND (ref, 0);
   type = TREE_TYPE (ref);
-  if (!dependent_type_p (type))
+  if (!dependent_type_p (type)
+      || (type && TREE_CODE (type) == POINTER_TYPE))
     return type;
   type = cxx_make_type (DECLTYPE_TYPE);
   DECLTYPE_TYPE_EXPR (type) = ref;
     return type;
   type = cxx_make_type (DECLTYPE_TYPE);
   DECLTYPE_TYPE_EXPR (type) = ref;
@@ -8728,7 +9107,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 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))
        {
     {
       if (IDENTIFIER_MARKED (name))
        {
@@ -8754,13 +9133,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.  */
     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));
 
     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.  */
     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.  */
@@ -8803,7 +9183,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
     {
       tree lambda = TREE_VALUE (node);
 
     {
       tree lambda = TREE_VALUE (node);
 
-      current_class_type = TREE_TYPE (lambda);
+      current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
       var = add_capture (lambda,
                             id,
                             initializer,
       var = add_capture (lambda,
                             id,
                             initializer,
@@ -8834,7 +9214,7 @@ lambda_expr_this_capture (tree lambda)
   if (!this_capture
       && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
     {
   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;
 
       tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
       tree init = NULL_TREE;
 
@@ -8884,7 +9264,8 @@ lambda_expr_this_capture (tree lambda)
   else
     {
       /* To make sure that current_class_ref is for the 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;
 
 
       result = this_capture;
 
@@ -9053,6 +9434,8 @@ maybe_add_lambda_conv_op (tree type)
   body = begin_function_body ();
   compound_stmt = begin_compound_stmt (0);
 
   body = begin_function_body ();
   compound_stmt = begin_compound_stmt (0);
 
+  /* decl_needed_p needs to see that it's used.  */
+  TREE_USED (statfn) = 1;
   finish_return_stmt (decay_conversion (statfn));
 
   finish_compound_stmt (compound_stmt);
   finish_return_stmt (decay_conversion (statfn));
 
   finish_compound_stmt (compound_stmt);