OSDN Git Service

In gcc/:
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index e27a64d..5b4dfb7 100644 (file)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "target.h"
 #include "c-family/c-common.h"
+#include "c-family/c-objc.h"
 #include "c-family/c-pragma.h"
 #include "diagnostic.h"
 #include "intl.h"
@@ -475,7 +476,11 @@ poplevel_named_label_1 (void **slot, void *data)
     {
       tree decl;
 
-      for (decl = ent->names_in_scope; decl; decl = DECL_CHAIN (decl))
+      /* ENT->NAMES_IN_SCOPE may contain a mixture of DECLs and
+        TREE_LISTs representing OVERLOADs, so be careful.  */
+      for (decl = ent->names_in_scope; decl; decl = (DECL_P (decl)
+                                                    ? DECL_CHAIN (decl)
+                                                    : TREE_CHAIN (decl)))
        if (decl_jump_unsafe (decl))
          VEC_safe_push (tree, gc, ent->bad_decls, decl);
 
@@ -1128,6 +1133,32 @@ check_redeclaration_exception_specification (tree new_decl,
     }
 }
 
+/* Return true if OLD_DECL and NEW_DECL agree on constexprness.
+   Otherwise issue diagnostics.  */
+
+static bool
+validate_constexpr_redeclaration (tree old_decl, tree new_decl)
+{
+  old_decl = STRIP_TEMPLATE (old_decl);
+  new_decl = STRIP_TEMPLATE (new_decl);
+  if (!VAR_OR_FUNCTION_DECL_P (old_decl)
+      || !VAR_OR_FUNCTION_DECL_P (new_decl))
+    return true;
+  if (DECL_DECLARED_CONSTEXPR_P (old_decl)
+      == DECL_DECLARED_CONSTEXPR_P (new_decl))
+    return true;
+  if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl))
+    {
+      /* Hide a built-in declaration.  */
+      DECL_DECLARED_CONSTEXPR_P (old_decl)
+       = DECL_DECLARED_CONSTEXPR_P (new_decl);
+      return true;
+    }
+  error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+  error ("from previous declaration %q+D", old_decl);
+  return false;
+}
+
 #define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn)                  \
                          && lookup_attribute ("gnu_inline",            \
                                               DECL_ATTRIBUTES (fn)))
@@ -1607,6 +1638,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
      warn about it.  */
   warn_extern_redeclared_static (newdecl, olddecl);
 
+  if (!validate_constexpr_redeclaration (olddecl, newdecl))
+    return error_mark_node;
+
   /* We have committed to returning 1 at this point.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -2868,10 +2902,7 @@ pop_switch (void)
   location_t switch_location;
 
   /* Emit warnings as needed.  */
-  if (EXPR_HAS_LOCATION (cs->switch_stmt))
-    switch_location = EXPR_LOCATION (cs->switch_stmt);
-  else
-    switch_location = input_location;
+  switch_location = EXPR_LOC_OR_HERE (cs->switch_stmt);
   if (!processing_template_decl)
     c_do_switch_warnings (cs->cases, switch_location,
                          SWITCH_STMT_TYPE (cs->switch_stmt),
@@ -2909,6 +2940,11 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
   if (!check_switch_goto (switch_stack->level))
     return error_mark_node;
 
+  if (low_value)
+    low_value = cxx_constant_value (low_value);
+  if (high_value)
+    high_value = cxx_constant_value (high_value);
+
   r = c_add_case_label (loc, switch_stack->cases, cond,
                        SWITCH_STMT_TYPE (switch_stack->switch_stmt),
                        low_value, high_value);
@@ -3192,6 +3228,9 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
       if (MAYBE_CLASS_TYPE_P (context))
        tmpl = lookup_field (context, name, 0, false);
 
+      if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
+       tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+
       if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
        {
          if (complain & tf_error)
@@ -3649,6 +3688,8 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
   if (current_function_decl)
     {
       struct cp_binding_level *b = current_binding_level;
+      if (b->kind == sk_function_parms)
+       return error_mark_node;
       while (b->level_chain->kind != sk_function_parms)
        b = b->level_chain;
       pushdecl_with_scope (decl, b, /*is_friend=*/false);
@@ -4029,7 +4070,7 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
       else if (saw_typedef)
        warning (0, "%<typedef%> was ignored in this declaration");
       else if (declspecs->specs[(int) ds_constexpr])
-        error ("%<constexpr> cannot be used for type declarations");
+        error ("%<constexpr%> cannot be used for type declarations");
     }
 
   return declared_type;
@@ -4310,9 +4351,6 @@ start_decl (const cp_declarator *declarator,
          && !alias)
        permerror (input_location, "declaration of %q#D outside of class is not definition",
                   decl);
-
-      if (!ensure_literal_type_for_constexpr_object (decl))
-        return error_mark_node;
     }
 
   was_public = TREE_PUBLIC (decl);
@@ -4344,7 +4382,7 @@ start_decl (const cp_declarator *declarator,
       /* This is a const variable with implicit 'static'.  Set
         DECL_THIS_STATIC so we can tell it from variables that are
         !TREE_PUBLIC because of the anonymous namespace.  */
-      gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)));
+      gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)) || errorcount);
       DECL_THIS_STATIC (decl) = 1;
     }
 
@@ -4502,7 +4540,8 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
    grok_reference_init.  */
 
 static tree
-build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+build_init_list_var_init (tree decl, tree type, tree init, tree *array_init,
+                         tree *cleanup)
 {
   tree aggr_init, array, arrtype;
   init = perform_implicit_conversion (type, init, tf_warning_or_error);
@@ -4510,8 +4549,6 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
     return error_mark_node;
 
   aggr_init = TARGET_EXPR_INITIAL (init);
-  init = build2 (INIT_EXPR, type, decl, init);
-
   array = AGGR_INIT_EXPR_ARG (aggr_init, 1);
   arrtype = TREE_TYPE (array);
   STRIP_NOPS (array);
@@ -4521,12 +4558,10 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
      static variable and we don't need to do anything here.  */
   if (decl && TREE_CODE (array) == TARGET_EXPR)
     {
-      tree subinit;
-      tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit);
+      tree var = set_up_extended_ref_temp (decl, array, cleanup, array_init);
       var = build_address (var);
       var = convert (arrtype, var);
       AGGR_INIT_EXPR_ARG (aggr_init, 1) = var;
-      init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
     }
   return init;
 }
@@ -4662,7 +4697,7 @@ layout_var_decl (tree decl)
       /* An automatic variable with an incomplete type: that is an error.
         Don't talk about array types here, since we took care of that
         message in grokdeclarator.  */
-      error ("storage size of %qD isn't known", decl);
+      error ("storage size of %qD isn%'t known", decl);
       TREE_TYPE (decl) = error_mark_node;
     }
 #if 0
@@ -4685,7 +4720,7 @@ layout_var_decl (tree decl)
        constant_expression_warning (DECL_SIZE (decl));
       else
        {
-         error ("storage size of %qD isn't constant", decl);
+         error ("storage size of %qD isn%'t constant", decl);
          TREE_TYPE (decl) = error_mark_node;
        }
     }
@@ -4732,7 +4767,7 @@ maybe_commonize_var (tree decl)
              DECL_COMMON (decl) = 0;
              warning_at (input_location, 0,
                          "sorry: semantics of inline function static "
-                         "data %q+#D are wrong (you'll wind up "
+                         "data %q+#D are wrong (you%'ll wind up "
                          "with multiple copies)", decl);
              warning_at (DECL_SOURCE_LOCATION (decl), 0, 
                          "  you can work around this by removing "
@@ -4753,14 +4788,10 @@ check_for_uninitialized_const_var (tree decl)
 {
   tree type = strip_array_types (TREE_TYPE (decl));
 
-  if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
-      && DECL_INITIAL (decl) == NULL)
-    error ("missing initializer for constexpr %qD", decl);
-
   /* ``Unless explicitly declared extern, a const object does not have
      external linkage and must be initialized. ($8.4; $12.1)'' ARM
      7.1.6 */
-  else if (TREE_CODE (decl) == VAR_DECL
+  if (TREE_CODE (decl) == VAR_DECL
       && TREE_CODE (type) != REFERENCE_TYPE
       && CP_TYPE_CONST_P (type)
       && (!TYPE_NEEDS_CONSTRUCTING (type)
@@ -5226,6 +5257,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
 {
   tree type = TREE_TYPE (decl);
   tree init_code = NULL;
+  tree extra_init = NULL_TREE;
   tree core_type;
 
   /* Things that are going to be initialized need to have complete
@@ -5280,16 +5312,21 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
       gcc_assert (init != NULL_TREE);
       init = NULL_TREE;
     }
-  else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
+  else if (!init && DECL_REALLY_EXTERN (decl))
+    ;
+  else if (TREE_CODE (type) == REFERENCE_TYPE)
     init = grok_reference_init (decl, type, init, cleanup);
-  else if (init)
+  else if (init || TYPE_NEEDS_CONSTRUCTING (type))
     {
+      if (!init)
+       check_for_uninitialized_const_var (decl);
       /* Do not reshape constructors of vectors (they don't need to be
         reshaped.  */
-      if (BRACE_ENCLOSED_INITIALIZER_P (init))
+      else if (BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          if (is_std_init_list (type))
-           return build_init_list_var_init (decl, type, init, cleanup);
+           init = build_init_list_var_init (decl, type, init,
+                                            &extra_init, cleanup);
          else if (TYPE_NON_AGGREGATE_CLASS (type))
            {
              /* Don't reshape if the class has constructors.  */
@@ -5316,9 +5353,46 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
 
       if (TYPE_NEEDS_CONSTRUCTING (type)
          || (CLASS_TYPE_P (type)
-             && !BRACE_ENCLOSED_INITIALIZER_P (init)))
-       return build_aggr_init_full_exprs (decl, init, flags);
-      else if (TREE_CODE (init) != TREE_VEC)
+             && !(init && BRACE_ENCLOSED_INITIALIZER_P (init))))
+       {
+         init_code = build_aggr_init_full_exprs (decl, init, flags);
+
+         /* If this is a constexpr initializer, expand_default_init will
+            have returned an INIT_EXPR rather than a CALL_EXPR.  In that
+            case, pull the initializer back out and pass it down into
+            store_init_value.  */
+         while (TREE_CODE (init_code) == EXPR_STMT
+                || TREE_CODE (init_code) == CONVERT_EXPR)
+           init_code = TREE_OPERAND (init_code, 0);
+         if (TREE_CODE (init_code) == INIT_EXPR)
+           {
+             init = TREE_OPERAND (init_code, 1);
+             init_code = NULL_TREE;
+             /* Don't call digest_init; it's unnecessary and will complain
+                about aggregate initialization of non-aggregate classes.  */
+             flags |= LOOKUP_ALREADY_DIGESTED;
+           }
+         else if (DECL_DECLARED_CONSTEXPR_P (decl))
+           {
+             /* Declared constexpr, but no suitable initializer; massage
+                init appropriately so we can pass it into store_init_value
+                for the error.  */
+             if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
+               init = finish_compound_literal (type, init);
+             else if (CLASS_TYPE_P (type)
+                      && (!init || TREE_CODE (init) == TREE_LIST))
+               {
+                 init = build_functional_cast (type, init, tf_none);
+                 if (init != error_mark_node)
+                   TARGET_EXPR_DIRECT_INIT_P (init) = true;
+               }
+             init_code = NULL_TREE;
+           }
+         else
+           init = NULL_TREE;
+       }
+
+      if (init && TREE_CODE (init) != TREE_VEC)
        {
          init_code = store_init_value (decl, init, flags);
          if (pedantic && TREE_CODE (type) == ARRAY_TYPE
@@ -5330,28 +5404,39 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
          init = NULL;
        }
     }
-  else if (DECL_EXTERNAL (decl))
-    ;
-  else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
-    {
-      check_for_uninitialized_const_var (decl);
-      return build_aggr_init_full_exprs (decl, init, flags);
-    }
-  else if (MAYBE_CLASS_TYPE_P (core_type = strip_array_types (type)))
+  else
     {
-      if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
-         || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+      if (CLASS_TYPE_P (core_type = strip_array_types (type))
+         && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+             || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
        diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false,
                                                  /*complain=*/true);
 
       check_for_uninitialized_const_var (decl);
     }
-  else
-    check_for_uninitialized_const_var (decl);
 
   if (init && init != error_mark_node)
     init_code = build2 (INIT_EXPR, type, decl, init);
 
+  if (extra_init)
+    init_code = add_stmt_to_compound (extra_init, init_code);
+
+  if (init_code && DECL_IN_AGGR_P (decl))
+    {
+      static int explained = 0;
+
+      if (cxx_dialect < cxx0x)
+       error ("initializer invalid for static member with constructor");
+      else
+       error ("non-constant in-class initialization invalid for static "
+              "member %qD", decl);
+      if (!explained)
+       {
+         error ("(an out of class initialization is required)");
+         explained = 1;
+       }
+    }
+
   return init_code;
 }
 
@@ -5682,6 +5767,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       if (TREE_CODE (d_init) == TREE_LIST)
        d_init = build_x_compound_expr_from_list (d_init, ELK_INIT,
                                                  tf_warning_or_error);
+      d_init = resolve_nondeduced_context (d_init);
       if (describable_type (d_init))
        {
          type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
@@ -5691,6 +5777,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
        }
     }
 
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    validate_constexpr_fundecl (decl);
+
+  else if (!ensure_literal_type_for_constexpr_object (decl))
+    DECL_DECLARED_CONSTEXPR_P (decl) = 0;
+
   if (init && TREE_CODE (decl) == FUNCTION_DECL)
     {
       tree clone;
@@ -5716,7 +5808,22 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            DECL_INITIAL (decl) = NULL_TREE;
        }
     }
-    
+
+  if (init && TREE_CODE (decl) == VAR_DECL)
+    {
+      DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+      /* FIXME we rely on TREE_CONSTANT below; basing that on
+        init_const_expr_p is probably wrong for C++0x.  */
+      if (init_const_expr_p)
+       {
+         /* Set these flags now for C++98 templates.  We'll update the
+            flags in store_init_value for instantiations and C++0x.  */
+         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+         if (decl_maybe_constant_var_p (decl))
+           TREE_CONSTANT (decl) = 1;
+       }
+    }
+
   if (processing_template_decl)
     {
       bool type_dependent_p;
@@ -5733,22 +5840,16 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          DECL_INITIAL (decl) = NULL_TREE;
        }
 
-      if (init && init_const_expr_p && TREE_CODE (decl) == VAR_DECL)
-       {
-         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
-         if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
-           TREE_CONSTANT (decl) = 1;
-       }
-
       /* Generally, initializers in templates are expanded when the
-        template is instantiated.  But, if DECL is an integral
-        constant static data member, then it can be used in future
-        integral constant expressions, and its value must be
-        available. */
+        template is instantiated.  But, if DECL is a variable constant
+        then it can be used in future constant expressions, so its value
+        must be available. */
       if (!(init
            && DECL_CLASS_SCOPE_P (decl)
-           && DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+           /* We just set TREE_CONSTANT appropriately; see above.  */
+           && TREE_CONSTANT (decl)
            && !type_dependent_p
+           /* FIXME non-value-dependent constant expression  */
            && !value_dependent_init_p (init)))
        {
          if (init)
@@ -5862,16 +5963,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                error ("Java object %qD not allocated with %<new%>", decl);
              init = NULL_TREE;
            }
-         if (init)
-           {
-             DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
-             if (init_const_expr_p)
-               {
-                 DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
-                 if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
-                   TREE_CONSTANT (decl) = 1;
-               }
-           }
          init = check_initializer (decl, init, flags, &cleanup);
          /* Thread-local storage cannot be dynamically initialized.  */
          if (DECL_THREAD_LOCAL_P (decl) && init)
@@ -6377,9 +6468,8 @@ expand_static_init (tree decl, tree init)
   gcc_assert (TREE_CODE (decl) == VAR_DECL);
   gcc_assert (TREE_STATIC (decl));
 
-  /* Some variables require no initialization.  */
+  /* Some variables require no dynamic initialization.  */
   if (!init
-      && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
       && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
 
@@ -6959,6 +7049,8 @@ grokfndecl (tree ctype,
   /* If the declaration was declared inline, mark it as such.  */
   if (inlinep)
     DECL_DECLARED_INLINE_P (decl) = 1;
+  if (inlinep & 2)
+    DECL_DECLARED_CONSTEXPR_P (decl) = true;
 
   DECL_EXTERNAL (decl) = 1;
   if (quals && TREE_CODE (type) == FUNCTION_TYPE)
@@ -7341,6 +7433,21 @@ build_ptrmem_type (tree class_type, tree member_type)
 int
 check_static_variable_definition (tree decl, tree type)
 {
+  /* If DECL is declared constexpr, we'll do the appropriate checks
+     in check_initializer.  */
+  if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
+    return 0;
+  else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+    {
+      if (literal_type_p (type))
+       error ("%<constexpr%> needed for in-class initialization of static "
+              "data member %q#D of non-integral type", decl);
+      else
+       error ("in-class initialization of static data member %q#D of "
+              "non-literal type", decl);
+      return 1;
+    }
+
   /* Motion 10 at San Diego: If a static const integral data member is
      initialized with an integral constant expression, the initializer
      may appear either in the declaration (within the class), or in
@@ -7352,10 +7459,6 @@ check_static_variable_definition (tree decl, tree type)
       error ("invalid in-class initialization of static data member "
             "of non-integral type %qT",
             type);
-      /* If we just return the declaration, crashes will sometimes
-        occur.  We therefore return void_type_node, as if this were a
-        friend declaration, to cause callers to completely ignore
-        this declaration.  */
       return 1;
     }
   else if (!CP_TYPE_CONST_P (type))
@@ -7374,36 +7477,67 @@ check_static_variable_definition (tree decl, tree type)
    name of the thing being declared.  */
 
 tree
-compute_array_index_type (tree name, tree size)
+compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 {
   tree type;
   tree itype;
+  tree osize = size;
   tree abi_1_itype = NULL_TREE;
 
   if (error_operand_p (size))
     return error_mark_node;
 
   type = TREE_TYPE (size);
-  /* The array bound must be an integer type.  */
-  if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+  /* type_dependent_expression_p? */
+  if (!dependent_type_p (type))
     {
-      if (name)
-       error ("size of array %qD has non-integral type %qT", name, type);
+      mark_rvalue_use (size);
+
+      if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR
+         && TREE_SIDE_EFFECTS (size))
+       /* In C++98, we mark a non-constant array bound with a magic
+          NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case.  */;
       else
-       error ("size of array has non-integral type %qT", type);
-      size = integer_one_node;
-      type = TREE_TYPE (size);
+       {
+         size = fold_non_dependent_expr (size);
+
+         if (CLASS_TYPE_P (type)
+             && CLASSTYPE_LITERAL_P (type))
+           {
+             size = build_expr_type_conversion (WANT_INT, size, true);
+             if (size == error_mark_node)
+               return error_mark_node;
+             type = TREE_TYPE (size);
+           }
+
+         size = maybe_constant_value (size);
+       }
+
+      if (error_operand_p (size))
+       return error_mark_node;
+
+      /* The array bound must be an integer type.  */
+      if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+       {
+         if (!(complain & tf_error))
+           return error_mark_node;
+         if (name)
+           error ("size of array %qD has non-integral type %qT", name, type);
+         else
+           error ("size of array has non-integral type %qT", type);
+         size = integer_one_node;
+         type = TREE_TYPE (size);
+       }
     }
 
   /* A type is dependent if it is...an array type constructed from any
      dependent type or whose size is specified by a constant expression
      that is value-dependent.  */
   /* We can only call value_dependent_expression_p on integral constant
-     expressions; the parser adds a dummy NOP_EXPR with TREE_SIDE_EFFECTS
-     set if this isn't one.  */
+     expressions; treat non-constant expressions as dependent, too.  */
   if (processing_template_decl
       && (dependent_type_p (type)
-         || TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size)))
+         || !TREE_CONSTANT (size) || value_dependent_expression_p (size)))
     {
       /* We cannot do any checking for a SIZE that isn't known to be
         constant. Just build the index type and mark that it requires
@@ -7424,17 +7558,7 @@ compute_array_index_type (tree name, tree size)
        would have, but with TYPE_CANONICAL set to the "right"
        value that the current ABI would provide. */
     abi_1_itype = build_index_type (build_min (MINUS_EXPR, sizetype,
-                                              size, integer_one_node));
-
-  /* The size might be the result of a cast.  */
-  STRIP_TYPE_NOPS (size);
-
-  size = mark_rvalue_use (size);
-
-  /* It might be a const variable or enumeration constant.  */
-  size = integral_constant_value (size);
-  if (error_operand_p (size))
-    return error_mark_node;
+                                              osize, integer_one_node));
 
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
@@ -7446,24 +7570,37 @@ compute_array_index_type (tree name, tree size)
       /* An array must have a positive number of elements.  */
       if (INT_CST_LT (size, integer_zero_node))
        {
+         if (!(complain & tf_error))
+           return error_mark_node;
          if (name)
            error ("size of array %qD is negative", name);
          else
            error ("size of array is negative");
          size = integer_one_node;
        }
-      /* As an extension we allow zero-sized arrays.  We always allow
-        them in system headers because glibc uses them.  */
-      else if (integer_zerop (size) && !in_system_header)
+      /* As an extension we allow zero-sized arrays.  */
+      else if (integer_zerop (size))
        {
-         if (name)
+         if (!(complain & tf_error))
+           /* We must fail if performing argument deduction (as
+              indicated by the state of complain), so that
+              another substitution can be found.  */
+           return error_mark_node;
+         else if (in_system_header)
+           /* Allow them in system headers because glibc uses them.  */;
+         else if (name)
            pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
          else
            pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array");
        }
     }
-  else if (TREE_CONSTANT (size))
+  else if (TREE_CONSTANT (size)
+          /* We don't allow VLAs at non-function scopes, or during
+             tentative template substitution.  */
+          || !at_function_scope_p () || !(complain & tf_error))
     {
+      if (!(complain & tf_error))
+       return error_mark_node;
       /* `(int) &fn' is not a valid array bound.  */
       if (name)
        error ("size of array %qD is not an integral constant-expression",
@@ -7519,6 +7656,8 @@ compute_array_index_type (tree name, tree size)
       else if (TREE_CODE (itype) == INTEGER_CST
               && TREE_OVERFLOW (itype))
        {
+         if (!(complain & tf_error))
+           return error_mark_node;
          error ("overflow in array dimension");
          TREE_OVERFLOW (itype) = 0;
        }
@@ -7630,7 +7769,7 @@ create_array_type_for_decl (tree name, tree type, tree size)
 
   /* Figure out the index type for the array.  */
   if (size)
-    itype = compute_array_index_type (name, size);
+    itype = compute_array_index_type (name, size, tf_warning_or_error);
 
   /* [dcl.array]
      T is called the array element type; this type shall not be [...] an
@@ -8046,6 +8185,12 @@ grokdeclarator (const cp_declarator *declarator,
   if (name == NULL)
     name = decl_context == PARM ? "parameter" : "type name";
 
+  if (constexpr_p && declspecs->specs[(int)ds_typedef])
+    {
+      error ("%<constexpr%> cannot appear in a typedef declaration");
+      return error_mark_node;
+    }
+
   /* If there were multiple types specified in the decl-specifier-seq,
      issue an error message.  */
   if (declspecs->multiple_types_p)
@@ -8299,17 +8444,6 @@ grokdeclarator (const cp_declarator *declarator,
   type_quals = TYPE_UNQUALIFIED;
   if (declspecs->specs[(int)ds_const])
     type_quals |= TYPE_QUAL_CONST;
-  /* A `constexpr' specifier used in an object declaration declares
-     the object as `const'.  */
-  if (constexpr_p)
-    {
-      if (innermost_code == cdk_function)
-        ;
-      else if (declspecs->specs[(int)ds_const] != 0)
-        error ("both %<const%> and %<constexpr%> cannot be used here");
-      else
-        type_quals |= TYPE_QUAL_CONST;
-    }
   if (declspecs->specs[(int)ds_volatile])
     type_quals |= TYPE_QUAL_VOLATILE;
   if (declspecs->specs[(int)ds_restrict])
@@ -8663,7 +8797,7 @@ grokdeclarator (const cp_declarator *declarator,
            else if (friendp)
              {
                if (initialized)
-                 error ("can't initialize friend function %qs", name);
+                 error ("can%'t initialize friend function %qs", name);
                if (virtualp)
                  {
                    /* Cannot be both friend and virtual.  */
@@ -8673,7 +8807,7 @@ grokdeclarator (const cp_declarator *declarator,
                if (decl_context == NORMAL)
                  error ("friend declaration not in class definition");
                if (current_function_decl && funcdef_flag)
-                 error ("can't define friend function %qs in a local "
+                 error ("can%'t define friend function %qs in a local "
                         "class definition",
                         name);
              }
@@ -8686,21 +8820,6 @@ grokdeclarator (const cp_declarator *declarator,
                  }
              }
 
-            /* It is not allowed to use `constexpr' in a function
-               declaration that is not a definition.
-               That is too strict, though.  */
-            if (constexpr_p && !funcdef_flag)
-              {
-                error ("the %<constexpr%> specifier cannot be used in "
-                       "a function declaration that is not a definition");
-                constexpr_p = false;
-              }
-
-            /* A constexpr non-static member function is implicitly const.  */
-            if (constexpr_p && decl_context == FIELD && staticp == 0
-                && sfk != sfk_constructor && sfk != sfk_destructor)
-              memfn_quals |= TYPE_QUAL_CONST;
-
            arg_types = grokparms (declarator->u.function.parameters,
                                   &parms);
 
@@ -8878,6 +8997,18 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
+  /* A `constexpr' specifier used in an object declaration declares
+     the object as `const'.  */
+  if (constexpr_p && innermost_code != cdk_function)
+    {
+      if (type_quals & TYPE_QUAL_CONST)
+        error ("both %<const%> and %<constexpr%> cannot be used here");
+      if (type_quals & TYPE_QUAL_VOLATILE)
+        error ("both %<volatile%> and %<constexpr%> cannot be used here");
+      type_quals |= TYPE_QUAL_CONST;
+      type = cp_build_qualified_type (type, type_quals);
+    }
+
   if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
       && TREE_CODE (type) != FUNCTION_TYPE
       && TREE_CODE (type) != METHOD_TYPE)
@@ -8964,8 +9095,6 @@ grokdeclarator (const cp_declarator *declarator,
        return error_mark_node;
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        {
-         tree sname = declarator->u.id.unqualified_name;
-
          if (current_class_type
              && (!friendp || funcdef_flag))
            {
@@ -8975,20 +9104,6 @@ grokdeclarator (const cp_declarator *declarator,
                     ctype, name, current_class_type);
              return error_mark_node;
            }
-
-          /* It is not permitted to define a member function outside ist
-             membership class as `constexpr'.  */
-          if (constexpr_p)
-            error ("a constexpr function cannot be defined "
-                   "outside of its class");
-
-         if (TREE_CODE (sname) == IDENTIFIER_NODE
-             && NEW_DELETE_OPNAME_P (sname))
-           /* Overloaded operator new and operator delete
-              are always static functions.  */
-           ;
-         else
-           type = build_memfn_type (type, ctype, memfn_quals);
        }
       else if (declspecs->specs[(int)ds_typedef]
               && current_class_type)
@@ -8999,6 +9114,15 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
+  if (ctype == NULL_TREE && decl_context == FIELD && friendp == 0)
+    ctype = current_class_type;
+
+  /* A constexpr non-static member function is implicitly const.  */
+  if (constexpr_p && ctype && staticp == 0
+      && TREE_CODE (type) == FUNCTION_TYPE
+      && sfk != sfk_constructor && sfk != sfk_destructor)
+    memfn_quals |= TYPE_QUAL_CONST;
+
   /* Now TYPE has the actual type.  */
 
   if (returned_attrs)
@@ -9362,6 +9486,10 @@ grokdeclarator (const cp_declarator *declarator,
        type = build_pointer_type (type);
     }
 
+  if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
+      && !NEW_DELETE_OPNAME_P (unqualified_id))
+    type = build_memfn_type (type, ctype, memfn_quals);
+
   {
     tree decl;
 
@@ -9379,7 +9507,8 @@ grokdeclarator (const cp_declarator *declarator,
        if (!staticp && TREE_CODE (type) == ARRAY_TYPE
            && TYPE_DOMAIN (type) == NULL_TREE)
          {
-           tree itype = compute_array_index_type (dname, integer_zero_node);
+           tree itype = compute_array_index_type (dname, integer_zero_node,
+                                                  tf_warning_or_error);
            type = build_cplus_array_type (TREE_TYPE (type), itype);
          }
 
@@ -9395,19 +9524,26 @@ grokdeclarator (const cp_declarator *declarator,
            error ("invalid use of %<::%>");
            return error_mark_node;
          }
-       else if (TREE_CODE (type) == FUNCTION_TYPE)
+       else if (TREE_CODE (type) == FUNCTION_TYPE
+                || TREE_CODE (type) == METHOD_TYPE)
          {
            int publicp = 0;
            tree function_context;
 
            if (friendp == 0)
              {
-               if (ctype == NULL_TREE)
-                 ctype = current_class_type;
-
-               if (ctype == NULL_TREE)
+               /* This should never happen in pure C++ (the check
+                  could be an assert).  It could happen in
+                  Objective-C++ if someone writes invalid code that
+                  uses a function declaration for an instance
+                  variable or property (instance variables and
+                  properties are parsed as FIELD_DECLs, but they are
+                  part of an Objective-C class, not a C++ class).
+                  That code is invalid and is caught by this
+                  check.  */
+               if (!ctype)
                  {
-                   error ("can't make %qD into a method -- not in a class",
+                   error ("declaration of function %qD in invalid context",
                           unqualified_id);
                    return error_mark_node;
                  }
@@ -9431,8 +9567,6 @@ grokdeclarator (const cp_declarator *declarator,
                        virtualp = 0;
                      }
                  }
-               else if (staticp < 2)
-                 type = build_memfn_type (type, ctype, memfn_quals);
              }
 
            /* Check that the name used for a destructor makes sense.  */
@@ -9455,9 +9589,12 @@ grokdeclarator (const cp_declarator *declarator,
                    return error_mark_node;
                  }
                 if (constexpr_p)
-                  error ("a destructor cannot be %<constexpr%>");
+                  {
+                    error ("a destructor cannot be %<constexpr%>");
+                    return error_mark_node;
+                  }
              }
-           else if (sfk == sfk_constructor && friendp)
+           else if (sfk == sfk_constructor && friendp && !ctype)
              {
                error ("expected qualified name in friend declaration "
                       "for constructor %qD",
@@ -9477,7 +9614,7 @@ grokdeclarator (const cp_declarator *declarator,
                               unqualified_id,
                               virtualp, flags, memfn_quals, raises,
                               friendp ? -1 : 0, friendp, publicp,
-                               inlinep || constexpr_p,
+                               inlinep | (2 * constexpr_p),
                               sfk,
                               funcdef_flag, template_count, in_namespace,
                               attrlist, declarator->id_loc);
@@ -9499,25 +9636,6 @@ grokdeclarator (const cp_declarator *declarator,
            if (explicitp == 2)
              DECL_NONCONVERTING_P (decl) = 1;
          }
-       else if (TREE_CODE (type) == METHOD_TYPE)
-         {
-           /* We only get here for friend declarations of
-              members of other classes.  */
-           /* All method decls are public, so tell grokfndecl to set
-              TREE_PUBLIC, also.  */
-           decl = grokfndecl (ctype, type,
-                              TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
-                              ? unqualified_id : dname,
-                              parms,
-                              unqualified_id,
-                              virtualp, flags, memfn_quals, raises,
-                              friendp ? -1 : 0, friendp, 1, 0, sfk,
-                              funcdef_flag, template_count, in_namespace,
-                              attrlist,
-                              declarator->id_loc);
-           if (decl == NULL_TREE)
-             return error_mark_node;
-         }
        else if (!staticp && !dependent_type_p (type)
                 && !COMPLETE_TYPE_P (complete_type (type))
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
@@ -9596,15 +9714,25 @@ grokdeclarator (const cp_declarator *declarator,
                       the rest of the compiler does not correctly
                       handle the initialization unless the member is
                       static so we make it static below.  */
-                   permerror (input_location, "ISO C++ forbids initialization of member %qD",
-                              unqualified_id);
-                   permerror (input_location, "making %qD static", unqualified_id);
-                   staticp = 1;
+                   if (cxx_dialect >= cxx0x)
+                     {
+                       sorry ("non-static data member initializers");
+                     }
+                   else
+                     {
+                       permerror (input_location, "ISO C++ forbids initialization of member %qD",
+                                  unqualified_id);
+                       permerror (input_location, "making %qD static", unqualified_id);
+                       staticp = 1;
+                     }
                  }
 
                if (uses_template_parms (type))
                  /* We'll check at instantiation time.  */
                  ;
+               else if (constexpr_p)
+                 /* constexpr has the same requirements.  */
+                 ;
                else if (check_static_variable_definition (unqualified_id,
                                                           type))
                  /* If we just return the declaration, crashes
@@ -9632,8 +9760,11 @@ grokdeclarator (const cp_declarator *declarator,
            else
              {
                 if (constexpr_p)
-                  error ("non-static data member %qE declared %<constexpr%>",
-                         unqualified_id);
+                 {
+                   error ("non-static data member %qE declared %<constexpr%>",
+                          unqualified_id);
+                   constexpr_p = false;
+                 }
                decl = build_decl (input_location,
                                   FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
@@ -9714,11 +9845,6 @@ grokdeclarator (const cp_declarator *declarator,
                sfk = sfk_none;
              }
          }
-       else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
-                && !NEW_DELETE_OPNAME_P (original_name))
-         type = build_method_type_directly (ctype,
-                                            TREE_TYPE (type),
-                                            TYPE_ARG_TYPES (type));
 
        /* Record presence of `static'.  */
        publicp = (ctype != NULL_TREE
@@ -9728,7 +9854,8 @@ grokdeclarator (const cp_declarator *declarator,
        decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
                           virtualp, flags, memfn_quals, raises,
                           1, friendp,
-                          publicp, inlinep || constexpr_p, sfk, funcdef_flag,
+                          publicp, inlinep | (2 * constexpr_p), sfk,
+                           funcdef_flag,
                           template_count, in_namespace, attrlist,
                           declarator->id_loc);
        if (decl == NULL_TREE)
@@ -9797,6 +9924,9 @@ grokdeclarator (const cp_declarator *declarator,
                storage_class = sc_none;
              }
          }
+       else if (constexpr_p && DECL_EXTERNAL (decl))
+         error ("declaration of constexpr variable %qD is not a definition",
+                decl);
       }
 
     if (storage_class == sc_extern && initialized && !funcdef_flag)
@@ -9826,8 +9956,8 @@ grokdeclarator (const cp_declarator *declarator,
       DECL_THIS_STATIC (decl) = 1;
 
     /* Don't forget constexprness.  */
-    if (VAR_OR_FUNCTION_DECL_P (decl))
-      DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
+    if (constexpr_p)
+      DECL_DECLARED_CONSTEXPR_P (decl) = true;
 
     /* Record constancy and volatility on the DECL itself .  There's
        no need to do this when processing a template; we'll do this
@@ -11713,12 +11843,11 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
       /* Validate and default VALUE.  */
       if (value != NULL_TREE)
        {
-         value = integral_constant_value (value);
+         value = cxx_constant_value (value);
 
          if (TREE_CODE (value) == INTEGER_CST)
            {
              value = perform_integral_promotions (value);
-             constant_expression_warning (value);
            }
          else
            {
@@ -11863,10 +11992,6 @@ check_function_type (tree decl, tree current_function_parms)
   /* In a function definition, arg types must be complete.  */
   require_complete_types_for_parms (current_function_parms);
 
-  /* constexpr functions must have literal argument types and
-     literal return type.  */
-  validate_constexpr_fundecl (decl);
-
   if (dependent_type_p (return_type))
     return;
   if (!COMPLETE_OR_VOID_TYPE_P (return_type)
@@ -12126,6 +12251,10 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        maybe_apply_pragma_weak (decl1);
     }
 
+  /* constexpr functions must have literal argument types and
+     literal return type.  */
+  validate_constexpr_fundecl (decl1);
+
   /* Reset this in case the call to pushdecl changed it.  */
   current_function_decl = decl1;
 
@@ -12648,6 +12777,19 @@ record_key_method_defined (tree fndecl)
     }
 }
 
+/* Subroutine of finish_function.
+   Save the body of constexpr functions for possible
+   future compile time evaluation.  */
+
+static void
+maybe_save_function_definition (tree fun)
+{
+  if (!processing_template_decl
+      && DECL_DECLARED_CONSTEXPR_P (fun)
+      && !DECL_CLONED_FUNCTION_P (fun))
+    register_constexpr_fundef (fun, DECL_SAVED_TREE (fun));
+}
+
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
    for the function definition.
@@ -12670,6 +12812,9 @@ finish_function (int flags)
   if (fndecl == NULL_TREE)
     return error_mark_node;
 
+  if (c_dialect_objc ())
+    objc_finish_function ();
+
   gcc_assert (!defer_mark_used_calls);
   defer_mark_used_calls = true;
 
@@ -12759,6 +12904,10 @@ finish_function (int flags)
      of curly braces for a function.  */
   gcc_assert (stmts_are_full_exprs_p ());
 
+  /* Save constexpr function body before it gets munged by
+     the NRV transformation.   */
+  maybe_save_function_definition (fndecl);
+
   /* Set up the named return value optimization, if we can.  Candidate
      variables are selected in check_return_expr.  */
   if (current_function_return_value)