OSDN Git Service

PR target/27789
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index d0866dc..e3c9297 100644 (file)
@@ -106,9 +106,6 @@ static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
 static tree next_initializable_field (tree);
 
-/* Erroneous argument lists can use this *IFF* they do not modify it.  */
-tree error_mark_list;
-
 /* The following symbols are subsumed in the cp_global_trees array, and
    listed here individually for documentation purposes.
 
@@ -144,9 +141,7 @@ tree error_mark_list;
 
    Used by RTTI
        tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
-       tree tinfo_var_id;
-
-*/
+       tree tinfo_var_id;  */
 
 tree cp_global_trees[CPTI_MAX];
 
@@ -207,7 +202,7 @@ struct named_label_entry GTY(())
      This is initially set to the binding level in which the label
      is defined, but is modified as scopes are closed.  */
   struct cp_binding_level *binding_level;
-  /* The head of the names list that was current when the label was 
+  /* The head of the names list that was current when the label was
      defined, or the inner scope popped.  These are the decls that will
      be skipped when jumping to the label.  */
   tree names_in_scope;
@@ -220,7 +215,7 @@ struct named_label_entry GTY(())
 
   /* The following bits are set after the label is defined, and are
      updated as scopes are popped.  They indicate that a backward jump
-     to the label will illegally enter a scope of the given flavour.  */
+     to the label will illegally enter a scope of the given flavor.  */
   bool in_try_scope;
   bool in_catch_scope;
   bool in_omp_scope;
@@ -245,10 +240,6 @@ enum deprecated_states {
 
 static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
-/* True if a declaration with an `extern' linkage specifier is being
-   processed.  */
-bool have_extern_spec;
-
 \f
 /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
    UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type.  At the
@@ -1004,7 +995,13 @@ decls_match (tree newdecl, tree olddecl)
       /* Need to check scope for variable declaration (VAR_DECL).
         For typedef (TYPE_DECL), scope is ignored.  */
       if (TREE_CODE (newdecl) == VAR_DECL
-         && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
+         && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
+         /* [dcl.link]
+            Two declarations for an object with C language linkage
+            with the same name (ignoring the namespace that qualify
+            it) that appear in different namespace scopes refer to
+            the same object.  */
+         && !(DECL_EXTERN_C_P (olddecl) && DECL_EXTERN_C_P (newdecl)))
        return 0;
 
       if (TREE_TYPE (newdecl) == error_mark_node)
@@ -1090,7 +1087,7 @@ check_redeclaration_exception_specification (tree new_decl,
   if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
       && ! DECL_IS_BUILTIN (old_decl)
       && flag_exceptions
-      && !comp_except_specs (new_exceptions, old_exceptions, 
+      && !comp_except_specs (new_exceptions, old_exceptions,
                             /*exact=*/true))
     {
       error ("declaration of %qF throws different exceptions", new_decl);
@@ -1458,14 +1455,42 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          warning (0, "prototype for %q+#D", newdecl);
          warning (0, "%Jfollows non-prototype definition here", olddecl);
        }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
+      else if ((TREE_CODE (olddecl) == FUNCTION_DECL
+               || TREE_CODE (olddecl) == VAR_DECL)
               && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
        {
-         /* extern "C" int foo ();
-            int foo () { bar (); }
-            is OK.  */
+         /* [dcl.link]
+            If two declarations of the same function or object
+            specify different linkage-specifications ..., the program
+            is ill-formed.... Except for functions with C++ linkage,
+            a function declaration without a linkage specification
+            shall not precede the first linkage specification for
+            that function.  A function can be declared without a
+            linkage specification after an explicit linkage
+            specification has been seen; the linkage explicitly
+            specified in the earlier declaration is not affected by
+            such a function declaration.
+
+            DR 563 raises the question why the restrictions on
+            functions should not also apply to objects.  Older
+            versions of G++ silently ignore the linkage-specification
+            for this example:
+
+              namespace N { 
+                 extern int i;
+                extern "C" int i;
+               }
+
+             which is clearly wrong.  Therefore, we now treat objects
+            like functions.  */
          if (current_lang_depth () == 0)
-           SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+           {
+             /* There is no explicit linkage-specification, so we use
+                the linkage from the previous declaration.  */
+             if (!DECL_LANG_SPECIFIC (newdecl))
+               retrofit_lang_decl (newdecl);
+             SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+           }
          else
            {
              error ("previous declaration of %q+#D with %qL linkage",
@@ -1641,7 +1666,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        {
          DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
          DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
-         DECL_NONTRIVIALLY_INITIALIZED_P (newdecl) 
+         DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
            |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
          DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
            |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
@@ -1917,7 +1942,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
       DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
     }
-  /* Init priority used to be merged from newdecl to olddecl by the memcpy, 
+  /* Init priority used to be merged from newdecl to olddecl by the memcpy,
      so keep this behavior.  */
   if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl))
     {
@@ -1979,7 +2004,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       memcpy ((char *) olddecl + sizeof (struct tree_common),
              (char *) newdecl + sizeof (struct tree_common),
              sizeof (struct tree_decl_common) - sizeof (struct tree_common));
-      switch (TREE_CODE (olddecl))       
+      switch (TREE_CODE (olddecl))
        {
        case LABEL_DECL:
        case VAR_DECL:
@@ -2285,7 +2310,7 @@ identify_goto (tree decl, const location_t *locus)
 /* Check that a single previously seen jump to a newly defined label
    is OK.  DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
    the jump context; NAMES are the names in scope in LEVEL at the jump
-   context; LOCUS is the source position of the jump or 0.  Returns 
+   context; LOCUS is the source position of the jump or 0.  Returns
    true if all is well.  */
 
 static bool
@@ -3118,9 +3143,6 @@ cxx_init_decl_processing (void)
   /* Initially, C.  */
   current_lang_name = lang_name_c;
 
-  error_mark_list = build_tree_list (error_mark_node, error_mark_node);
-  TREE_TYPE (error_mark_list) = error_mark_node;
-
   /* Create the `std' namespace.  */
   push_namespace (std_identifier);
   std_node = current_namespace;
@@ -3317,7 +3339,6 @@ cp_make_fname_decl (tree id, int type_dep)
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
-  DECL_INITIAL (decl) = init;
 
   TREE_USED (decl) = 1;
 
@@ -3327,7 +3348,7 @@ cp_make_fname_decl (tree id, int type_dep)
       while (b->level_chain->kind != sk_function_parms)
        b = b->level_chain;
       pushdecl_with_scope (decl, b, /*is_friend=*/false);
-      cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE, 
+      cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
                      LOOKUP_ONLYCONVERTING);
     }
   else
@@ -3789,13 +3810,6 @@ start_decl (const cp_declarator *declarator,
 
   *pushed_scope_p = NULL_TREE;
 
-  /* This should only be done once on the top most decl.  */
-  if (have_extern_spec)
-    {
-      declspecs->storage_class = sc_extern;
-      have_extern_spec = false;
-    }
-
   /* An object declared as __attribute__((deprecated)) suppresses
      warnings of uses of other deprecated items.  */
   if (lookup_attribute ("deprecated", attributes))
@@ -3854,16 +3868,21 @@ start_decl (const cp_declarator *declarator,
       DECL_EXTERNAL (decl) = 0;
       if (toplevel_bindings_p ())
        TREE_STATIC (decl) = 1;
-
-      /* Tell `pushdecl' this is an initialized decl
-        even though we don't yet have the initializer expression.
-        Also tell `cp_finish_decl' it may store the real initializer.  */
-      DECL_INITIAL (decl) = error_mark_node;
     }
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   cplus_decl_attributes (&decl, attributes, 0);
 
+  /* Dllimported symbols cannot be defined.  Static data members (which
+     can be initialized in-class and dllimported) go through grokfield,
+     not here, so we don't need to exclude those decls when checking for
+     a definition.  */
+  if (initialized && DECL_DLLIMPORT_P (decl))
+    {
+      error ("definition of %q#D is marked %<dllimport%>", decl);
+      DECL_DLLIMPORT_P (decl) = 0;
+    }
+
   /* If #pragma weak was used, mark the decl weak now.  */
   maybe_apply_pragma_weak (decl);
 
@@ -3901,8 +3920,7 @@ start_decl (const cp_declarator *declarator,
                 declaration will have DECL_EXTERNAL set, but will have an
                 initialization.  Thus, duplicate_decls won't warn
                 about this situation, and so we check here.  */
-             if (DECL_INITIAL (decl) 
-                 && DECL_INITIALIZED_IN_CLASS_P (field))
+             if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
                error ("duplicate initialization of %qD", decl);
              if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
                decl = field;
@@ -3936,8 +3954,7 @@ start_decl (const cp_declarator *declarator,
 
             We check for processing_specialization so this only applies
             to the new specialization syntax.  */
-         if (!DECL_INITIAL (decl)
-             && processing_specialization)
+         if (!initialized && processing_specialization)
            DECL_EXTERNAL (decl) = 1;
        }
 
@@ -3966,21 +3983,25 @@ start_decl (const cp_declarator *declarator,
       && !have_global_bss_p ())
     DECL_COMMON (tem) = 1;
 
-  if (! processing_template_decl)
-    start_decl_1 (tem);
+  if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
+    start_decl_1 (tem, initialized);
 
   return tem;
 }
 
 void
-start_decl_1 (tree decl)
+start_decl_1 (tree decl, bool initialized)
 {
-  tree type = TREE_TYPE (decl);
-  int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+  tree type;
 
-  if (type == error_mark_node)
+  gcc_assert (!processing_template_decl);
+
+  if (error_operand_p (decl))
     return;
 
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  type = TREE_TYPE (decl);
+
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -4004,16 +4025,10 @@ start_decl_1 (tree decl)
          initialized = 0;
        }
     }
-
-  if (!initialized
-      && TREE_CODE (decl) != TYPE_DECL
-      && TREE_CODE (decl) != TEMPLATE_DECL
-      && type != error_mark_node
-      && IS_AGGR_TYPE (type)
-      && ! DECL_EXTERNAL (decl))
+  else if (IS_AGGR_TYPE (type)
+          && ! DECL_EXTERNAL (decl))
     {
-      if ((! processing_template_decl || ! uses_template_parms (type))
-         && !COMPLETE_TYPE_P (complete_type (type)))
+      if (!COMPLETE_TYPE_P (complete_type (type)))
        {
          error ("aggregate %q#D has incomplete type and cannot be defined",
                 decl);
@@ -4033,9 +4048,6 @@ start_decl_1 (tree decl)
        }
     }
 
-  if (! initialized)
-    DECL_INITIAL (decl) = NULL_TREE;
-
   /* Create a new scope to hold this declaration if necessary.
      Whether or not a new scope is necessary cannot be determined
      until after the type has been completed; if the type is a
@@ -4130,12 +4142,17 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
                                            do_default);
 
       if (failure == 1)
-       error ("initializer fails to determine size of %qD", decl);
-
-      if (failure == 2)
+       {
+         error ("initializer fails to determine size of %qD", decl);
+         TREE_TYPE (decl) = error_mark_node;
+       }
+      else if (failure == 2)
        {
          if (do_default)
-           error ("array size missing in %qD", decl);
+           {
+             error ("array size missing in %qD", decl);
+             TREE_TYPE (decl) = error_mark_node;
+           }
          /* If a `static' var's size isn't known, make it extern as
             well as static, so it does not get allocated.  If it's not
             `static', then don't mark it extern; finish_incomplete_decl
@@ -4143,9 +4160,11 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
          else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
            DECL_EXTERNAL (decl) = 1;
        }
-
-      if (failure == 3)
-       error ("zero-size array %qD", decl);
+      else if (failure == 3)
+       {
+         error ("zero-size array %qD", decl);
+         TREE_TYPE (decl) = error_mark_node;
+       }
 
       cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
 
@@ -4159,7 +4178,17 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
 static void
 layout_var_decl (tree decl)
 {
-  tree type = TREE_TYPE (decl);
+  tree type;
+
+  if (TREE_STATIC (decl)
+      && !DECL_ARTIFICIAL (decl)
+      && current_function_decl
+      && DECL_CONTEXT (decl) == current_function_decl)
+    push_local_name (decl);
+
+  type = TREE_TYPE (decl);
+  if (type == error_mark_node)
+    return;
 
   /* If we haven't already layed out this declaration, do so now.
      Note that we must not call complete type for an external object
@@ -4205,12 +4234,6 @@ layout_var_decl (tree decl)
       else
        error ("storage size of %qD isn't constant", decl);
     }
-
-  if (TREE_STATIC (decl)
-      && !DECL_ARTIFICIAL (decl)
-      && current_function_decl
-      && DECL_CONTEXT (decl) == current_function_decl)
-    push_local_name (decl);
 }
 
 /* If a local static variable is declared in an inline function, or if
@@ -4371,6 +4394,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
        }
 
       elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
+      if (elt_init == error_mark_node)
+       return error_mark_node;
       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init);
     }
 
@@ -4411,7 +4436,7 @@ reshape_init_vector (tree type, reshape_iter *d)
        {
          error ("invalid type %qT as initializer for a vector of type %qT",
                TREE_TYPE (d->cur->value), type);
-         value = error_mark_node;
+         value = error_mark_node;
        }
       ++d->cur;
       return value;
@@ -4467,7 +4492,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
        {
          if (pedantic)
            pedwarn ("ISO C++ does not allow designated initializers");
-       
+
          field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
 
          if (!field || TREE_CODE (field) != FIELD_DECL)
@@ -4523,7 +4548,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
          error ("braces around scalar initializer for type %qT", type);
          init = error_mark_node;
        }
-       
+
       d->cur++;
       return init;
     }
@@ -4556,7 +4581,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
       tree str_init = init;
 
       /* Strip one level of braces if and only if they enclose a single
-         element (as allowed by [dcl.init.string]).  */
+        element (as allowed by [dcl.init.string]).  */
       if (!first_initializer_p
          && TREE_CODE (str_init) == CONSTRUCTOR
          && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1)
@@ -4564,9 +4589,9 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
          str_init = VEC_index (constructor_elt,
                                CONSTRUCTOR_ELTS (str_init), 0)->value;
        }
-  
+
       /* If it's a string literal, then it's the initializer for the array
-         as a whole. Otherwise, continue with normal initialization for
+        as a whole. Otherwise, continue with normal initialization for
         array types (one value per array element).  */
       if (TREE_CODE (str_init) == STRING_CST)
        {
@@ -4649,6 +4674,8 @@ reshape_init (tree type, tree init)
   d.end = d.cur + VEC_length (constructor_elt, v);
 
   new_init = reshape_init_r (type, &d, true);
+  if (new_init == error_mark_node)
+    return error_mark_node;
 
   /* Make sure all the element of the constructor were used. Otherwise,
      issue an error about exceeding initializers.  */
@@ -4671,16 +4698,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   tree type = TREE_TYPE (decl);
   tree init_code = NULL;
 
-  /* If `start_decl' didn't like having an initialization, ignore it now.  */
-  if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
-    init = NULL_TREE;
-
-  /* If an initializer is present, DECL_INITIAL has been
-     error_mark_node, to indicate that an as-of-yet unevaluated
-     initialization will occur.  From now on, DECL_INITIAL reflects
-     the static initialization -- if any -- of DECL.  */
-  DECL_INITIAL (decl) = NULL_TREE;
-
   /* Things that are going to be initialized need to have complete
      type.  */
   TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
@@ -4721,7 +4738,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   else if (init)
     {
       /* Do not reshape constructors of vectors (they don't need to be
-         reshaped.  */
+        reshaped.  */
       if (TREE_CODE (init) == CONSTRUCTOR
          && !COMPOUND_LITERAL_P (init)
          && !TREE_TYPE (init))  /* ptrmemfunc */
@@ -4739,6 +4756,8 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
         array size from the initializer.  */
       maybe_deduce_size_from_array_init (decl, init);
       type = TREE_TYPE (decl);
+      if (type == error_mark_node)
+       return NULL_TREE;
 
       if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
        {
@@ -4994,7 +5013,7 @@ initialize_artificial_var (tree decl, tree init)
    if the (init) syntax was used.  */
 
 void
-cp_finish_decl (tree decl, tree init, bool init_const_expr_p, 
+cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                tree asmspec_tree, int flags)
 {
   tree type;
@@ -5002,6 +5021,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   const char *asmspec = NULL;
   int was_readonly = 0;
   bool var_definition_p = false;
+  int saved_processing_template_decl;
 
   if (decl == error_mark_node)
     return;
@@ -5013,9 +5033,16 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
     }
 
   gcc_assert (TREE_CODE (decl) != RESULT_DECL);
+  /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
+  gcc_assert (TREE_CODE (decl) != PARM_DECL);
+
+  type = TREE_TYPE (decl);
+  if (type == error_mark_node)
+    return;
 
   /* Assume no cleanup is required.  */
   cleanup = NULL_TREE;
+  saved_processing_template_decl = processing_template_decl;
 
   /* If a name was specified, get the string.  */
   if (global_scope_p (current_binding_level))
@@ -5023,51 +5050,48 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
-  if (init && TREE_CODE (init) == NAMESPACE_DECL)
-    {
-      error ("cannot initialize %qD to namespace %qD", decl, init);
-      init = NULL_TREE;
-    }
-
   if (current_class_type
       && CP_DECL_CONTEXT (decl) == current_class_type
       && TYPE_BEING_DEFINED (current_class_type)
       && (DECL_INITIAL (decl) || init))
     DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
 
-  type = TREE_TYPE (decl);
-
-  if (type == error_mark_node)
-    goto finish_end;
-
   if (processing_template_decl)
     {
+      bool type_dependent_p;
+
       /* Add this declaration to the statement-tree.  */
       if (at_function_scope_p ())
        add_decl_expr (decl);
 
-      if (init && DECL_INITIAL (decl))
+      type_dependent_p = dependent_type_p (type);
+
+      if (init && init_const_expr_p)
        {
-         DECL_INITIAL (decl) = init;
-         if (init_const_expr_p)
-           {
-             DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
-             if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
-               TREE_CONSTANT (decl) = 1;
-           }
+         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+         if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+           TREE_CONSTANT (decl) = 1;
        }
 
-      if (TREE_CODE (decl) == VAR_DECL
-         && !DECL_PRETTY_FUNCTION_P (decl)
-         && !dependent_type_p (TREE_TYPE (decl)))
-       maybe_deduce_size_from_array_init (decl, init);
+      if (!init
+         || !DECL_CLASS_SCOPE_P (decl)
+         || !DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+         || type_dependent_p
+         || value_dependent_expression_p (init))
+       {
+         if (init)
+           DECL_INITIAL (decl) = init;
+         if (TREE_CODE (decl) == VAR_DECL
+             && !DECL_PRETTY_FUNCTION_P (decl)
+             && !type_dependent_p)
+           maybe_deduce_size_from_array_init (decl, init);
+         goto finish_end;
+       }
 
-      goto finish_end;
+      init = fold_non_dependent_expr (init);
+      processing_template_decl = 0;
     }
 
-  /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
-  gcc_assert (TREE_CODE (decl) != PARM_DECL);
-
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -5142,7 +5166,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
             occurs.  Therefore, in:
 
               struct S { static const int i = 7 / 0; };
-              
+
             we issue an error at this point.  It would
             probably be better to forbid division by zero in
             integral constant expressions.  */
@@ -5178,9 +5202,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
             the class specifier.  */
          if (!DECL_EXTERNAL (decl))
            var_definition_p = true;
-         /* The variable is being defined, so determine its
-            visibility.  */
-         determine_visibility (decl);
        }
       /* If the variable has an array type, lay out the type, even if
         there is no initializer.  It is valid to index through the
@@ -5196,16 +5217,17 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   if (at_function_scope_p ())
     add_decl_expr (decl);
 
-  if (TREE_CODE (decl) == VAR_DECL)
-    layout_var_decl (decl);
-
-  /* Output the assembler code and/or RTL code for variables and functions,
-     unless the type is an undefined structure or union.
-     If not, it will get done when the type is completed.  */
-  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+  /* Let the middle end know about variables and functions -- but not
+     static data members in uninstantiated class templates.  */
+  if (!saved_processing_template_decl
+      && (TREE_CODE (decl) == VAR_DECL 
+         || TREE_CODE (decl) == FUNCTION_DECL))
     {
       if (TREE_CODE (decl) == VAR_DECL)
-       maybe_commonize_var (decl);
+       {
+         layout_var_decl (decl);
+         maybe_commonize_var (decl);
+       }
 
       make_rtl_for_nonlocal_decl (decl, init, asmspec);
 
@@ -5236,14 +5258,15 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            {
              /* Initialize the local variable.  */
              if (processing_template_decl)
-               {
-                 if (init || DECL_INITIAL (decl) == error_mark_node)
-                   DECL_INITIAL (decl) = init;
-               }
+               DECL_INITIAL (decl) = init;
              else if (!TREE_STATIC (decl))
                initialize_local_var (decl, init);
            }
 
+         /* The variable is being defined, so determine its visibility.
+            This needs to happen after the linkage is set. */
+         determine_visibility (decl);
+
          /* If a variable is defined, and then a subsequent
             definition with external linkage is encountered, we will
             get here twice for the same variable.  We want to avoid
@@ -5263,6 +5286,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
     push_cleanup (decl, cleanup, false);
 
  finish_end:
+  processing_template_decl = saved_processing_template_decl;
 
   if (was_readonly)
     TREE_READONLY (decl) = 1;
@@ -5813,6 +5837,28 @@ check_class_member_definition_namespace (tree decl)
             decl, DECL_CONTEXT (decl));
 }
 
+/* Build a PARM_DECL for the "this" parameter.  TYPE is the
+   METHOD_TYPE for a non-static member function; QUALS are the
+   cv-qualifiers that apply to the function.  */
+
+tree
+build_this_parm (tree type, cp_cv_quals quals)
+{
+  tree this_type;
+  tree qual_type;
+  tree parm;
+  cp_cv_quals this_quals;
+
+  this_type = TREE_VALUE (TYPE_ARG_TYPES (type));
+  /* The `this' parameter is implicitly `const'; it cannot be
+     assigned to.  */
+  this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST;
+  qual_type = cp_build_qualified_type (this_type, this_quals);
+  parm = build_artificial_parm (this_identifier, qual_type);
+  cp_apply_type_quals_to_decl (this_quals, parm);
+  return parm;
+}
+
 /* CTYPE is class type, or null if non-class.
    TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
    or METHOD_TYPE.
@@ -5859,6 +5905,13 @@ grokfndecl (tree ctype,
     type = build_exception_variant (type, raises);
 
   decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+  if (TREE_CODE (type) == METHOD_TYPE)
+    {
+      tree parm;
+      parm = build_this_parm (type, quals);
+      TREE_CHAIN (parm) = parms;
+      parms = parm;
+    }
   DECL_ARGUMENTS (decl) = parms;
   /* Propagate volatile out from type to decl.  */
   if (TYPE_VOLATILE (type))
@@ -5972,7 +6025,7 @@ grokfndecl (tree ctype,
          tree newtype;
          error ("%<::main%> must return %<int%>");
          newtype =  build_function_type (integer_type_node,
-                                         oldtypeargs);
+                                         oldtypeargs);
          TREE_TYPE (decl) = newtype;
        }
       inlinep = 0;
@@ -6062,7 +6115,7 @@ grokfndecl (tree ctype,
       if (sfk == sfk_constructor)
        DECL_CONSTRUCTOR_P (decl) = 1;
 
-      grokclassfn (ctype, decl, flags, quals);
+      grokclassfn (ctype, decl, flags);
     }
 
   decl = check_explicit_specialization (orig_declarator, decl,
@@ -6770,12 +6823,11 @@ grokdeclarator (const cp_declarator *declarator,
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int type_quals;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
-  tree dependant_name = NULL_TREE;
+  tree dependent_name = NULL_TREE;
 
   tree typedef_decl = NULL_TREE;
   const char *name = NULL;
@@ -6797,7 +6849,11 @@ grokdeclarator (const cp_declarator *declarator,
   tree dname = NULL_TREE;
   tree ctor_return_type = NULL_TREE;
   enum overload_flags flags = NO_SPECIAL;
-  cp_cv_quals quals = TYPE_UNQUALIFIED;
+  /* cv-qualifiers that apply to the declarator, for a declaration of
+     a member function.  */
+  cp_cv_quals memfn_quals = TYPE_UNQUALIFIED;
+  /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
+  int type_quals;
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -6955,7 +7011,7 @@ grokdeclarator (const cp_declarator *declarator,
            break;
 
          case cdk_error:
-           break;
+           return error_mark_node;
 
          default:
            gcc_unreachable ();
@@ -6965,11 +7021,15 @@ grokdeclarator (const cp_declarator *declarator,
        break;
     }
 
-  /* A function definition's declarator must have the form of
-     a function declarator.  */
+  /* [dcl.fct.edf]
 
+     The declarator in a function-definition shall have the form
+     D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
-    return NULL_TREE;
+    {
+      error ("function definition does not declare parameters");
+      return error_mark_node;
+    }
 
   if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
       && innermost_code != cdk_function
@@ -7085,7 +7145,7 @@ grokdeclarator (const cp_declarator *declarator,
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
-  if (long_p && TYPE_MAIN_VARIANT (type) == double_type_node)
+  if (long_p && !longlong && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
       long_p = false;
       type = build_qualified_type (long_double_type_node,
@@ -7098,18 +7158,20 @@ grokdeclarator (const cp_declarator *declarator,
     {
       int ok = 0;
 
-      if (TREE_CODE (type) == REAL_TYPE)
-       error ("short, signed or unsigned invalid for %qs", name);
-      else if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for %qs", name);
-      else if (long_p && short_p)
-       error ("long and short specified together for %qs", name);
-      else if ((long_p || short_p) && explicit_char)
-       error ("long or short specified with char for %qs", name);
-      else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
-       error ("long or short specified with floating type for %qs", name);
+      if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE)
+       error ("%<signed%> or %<unsigned%> invalid for %qs", name);
       else if (signed_p && unsigned_p)
-       error ("signed and unsigned given together for %qs", name);
+       error ("%<signed%> and %<unsigned%> specified together for %qs", name);
+      else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
+       error ("%<long long%> invalid for %qs", name);
+      else if (long_p && TREE_CODE (type) == REAL_TYPE)
+       error ("%<long%> invalid for %qs", name);
+      else if (short_p && TREE_CODE (type) == REAL_TYPE)
+       error ("%<short%> invalid for %qs", name);
+      else if ((long_p || short_p) && explicit_char)
+       error ("%<long%> or %<short%> specified with char for %qs", name);
+      else if (long_p && short_p)
+       error ("%<long%> and %<short%> specified together for %qs", name);
       else
        {
          ok = 1;
@@ -7249,10 +7311,10 @@ grokdeclarator (const cp_declarator *declarator,
     }
   friendp = !! declspecs->specs[(int)ds_friend];
 
-  if (dependant_name && !friendp)
+  if (dependent_name && !friendp)
     {
-      error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name);
-      return void_type_node;
+      error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
+      return error_mark_node;
     }
 
   /* Issue errors about use of storage classes for parameters.  */
@@ -7450,7 +7512,7 @@ grokdeclarator (const cp_declarator *declarator,
              }
 
            /* Pick up type qualifiers which should be applied to `this'.  */
-           quals = declarator->u.function.qualifiers;
+           memfn_quals = declarator->u.function.qualifiers;
 
            /* Pick up the exception specifications.  */
            raises = declarator->u.function.exception_specification;
@@ -7473,56 +7535,44 @@ grokdeclarator (const cp_declarator *declarator,
                   a function, then it is a constructor/destructor, and
                   therefore returns a void type.  */
 
-               if (flags == DTOR_FLAG)
+               /* ISO C++ 12.4/2.  A destructor may not be declared
+                  const or volatile.  A destructor may not be
+                  static.
+
+                  ISO C++ 12.1.  A constructor may not be declared
+                  const or volatile.  A constructor may not be
+                  virtual.  A constructor may not be static.  */
+               if (staticp == 2)
+                 error ((flags == DTOR_FLAG)
+                        ? "destructor cannot be static member function"
+                        : "constructor cannot be static member function");
+               if (memfn_quals)
                  {
-                   /* ISO C++ 12.4/2.  A destructor may not be
-                      declared const or volatile.  A destructor may
-                      not be static.  */
-                   if (staticp == 2)
-                     error ("destructor cannot be static member function");
-                   if (quals)
-                     {
-                       error ("destructors may not be cv-qualified");
-                       quals = TYPE_UNQUALIFIED;
-                     }
-                   if (decl_context == FIELD)
-                     {
-                       if (! member_function_or_else (ctype,
-                                                      current_class_type,
-                                                      flags))
-                         return void_type_node;
-                     }
+                   error ((flags == DTOR_FLAG)
+                          ? "destructors may not be cv-qualified"
+                          : "constructors may not be cv-qualified");
+                   memfn_quals = TYPE_UNQUALIFIED;
                  }
-               else /* It's a constructor.  */
+
+               if (decl_context == FIELD
+                   && !member_function_or_else (ctype,
+                                                current_class_type,
+                                                flags))
+                 return error_mark_node;
+
+               if (flags != DTOR_FLAG)
                  {
+                   /* It's a constructor.  */
                    if (explicitp == 1)
                      explicitp = 2;
-                   /* ISO C++ 12.1.  A constructor may not be
-                      declared const or volatile.  A constructor may
-                      not be virtual.  A constructor may not be
-                      static.  */
-                   if (staticp == 2)
-                     error ("constructor cannot be static member function");
                    if (virtualp)
                      {
                        pedwarn ("constructors cannot be declared virtual");
                        virtualp = 0;
                      }
-                   if (quals)
-                     {
-                       error ("constructors may not be cv-qualified");
-                       quals = TYPE_UNQUALIFIED;
-                     }
-                   if (decl_context == FIELD)
-                     {
-                       if (! member_function_or_else (ctype,
-                                                      current_class_type,
-                                                      flags))
-                         return void_type_node;
-                       TYPE_HAS_CONSTRUCTOR (ctype) = 1;
-                       if (sfk != sfk_constructor)
-                         return NULL_TREE;
-                     }
+                   if (decl_context == FIELD
+                       && sfk != sfk_constructor)
+                     return error_mark_node;
                  }
                if (decl_context == FIELD)
                  staticp = 0;
@@ -7559,7 +7609,6 @@ grokdeclarator (const cp_declarator *declarator,
              }
 
            type = build_function_type (type, arg_types);
-           type = cp_build_qualified_type (type, quals);
          }
          break;
 
@@ -7589,22 +7638,13 @@ grokdeclarator (const cp_declarator *declarator,
          type_quals = TYPE_UNQUALIFIED;
 
          if (declarator->kind == cdk_ptrmem
-             && (TREE_CODE (type) == FUNCTION_TYPE
-                 || (quals && TREE_CODE (type) == METHOD_TYPE)))
+             && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
            {
-             tree dummy;
-
-             /* If the type is a FUNCTION_TYPE, pick up the
-                qualifiers from that function type. No other
-                qualifiers may be supplied. */
-             if (TREE_CODE (type) == FUNCTION_TYPE)
-               quals = cp_type_quals (type);
-
-             dummy = build_decl (TYPE_DECL, NULL_TREE, type);
-             grok_method_quals (declarator->u.pointer.class_type,
-                                dummy, quals);
-             type = TREE_TYPE (dummy);
-             quals = TYPE_UNQUALIFIED;
+             memfn_quals |= cp_type_quals (type);
+             type = build_memfn_type (type,
+                                      declarator->u.pointer.class_type,
+                                      memfn_quals);
+             memfn_quals = TYPE_UNQUALIFIED;
            }
 
          if (declarator->kind == cdk_reference)
@@ -7616,15 +7656,9 @@ grokdeclarator (const cp_declarator *declarator,
            type = build_ptrmemfunc_type (build_pointer_type (type));
          else if (declarator->kind == cdk_ptrmem)
            {
-             /* We might have parsed a namespace as the class type.  */
-             if (TREE_CODE (declarator->u.pointer.class_type)
-                 == NAMESPACE_DECL)
-               {
-                 error ("%qD is a namespace",
-                        declarator->u.pointer.class_type);
-                 type = build_pointer_type (type);
-               }
-             else if (declarator->u.pointer.class_type == error_mark_node)
+             gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
+                         != NAMESPACE_DECL);
+             if (declarator->u.pointer.class_type == error_mark_node)
                /* We will already have complained.  */
                type = error_mark_node;
              else
@@ -7714,6 +7748,27 @@ grokdeclarator (const cp_declarator *declarator,
            pedwarn ("extra qualification %<%T::%> on member %qs",
                     ctype, name);
        }
+      else if (/* If the qualifying type is already complete, then we
+                 can skip the following checks.  */
+              !COMPLETE_TYPE_P (ctype)
+              && (/* If the function is being defined, then
+                     qualifying type must certainly be complete.  */
+                  funcdef_flag
+                  /* A friend declaration of "T::f" is OK, even if
+                     "T" is a template parameter.  But, if this
+                     function is not a friend, the qualifying type
+                     must be a class.  */
+                  || (!friendp && !CLASS_TYPE_P (ctype))
+                  /* For a declaration, the type need not be
+                     complete, if either it is dependent (since there
+                     is no meaningful definition of complete in that
+                     case) or the qualifying class is currently being
+                     defined.  */
+                  || !(dependent_type_p (ctype)
+                       || currently_open_class (ctype)))
+              /* Check that the qualifying type is complete.  */
+              && !complete_type_or_else (ctype, NULL_TREE))
+       return error_mark_node;
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        {
          tree sname = declarator->u.id.unqualified_name;
@@ -7734,28 +7789,13 @@ grokdeclarator (const cp_declarator *declarator,
               are always static functions.  */
            ;
          else
-           type = build_method_type_directly (ctype,
-                                              TREE_TYPE (type),
-                                              TYPE_ARG_TYPES (type));
+           type = build_memfn_type (type, ctype, memfn_quals);
        }
       else if (declspecs->specs[(int)ds_typedef]
-              || COMPLETE_TYPE_P (complete_type (ctype)))
+              && current_class_type)
        {
-         /* Have to move this code elsewhere in this function.
-            this code is used for i.e., typedef int A::M; M *pm;
-
-            It is?  How? jason 10/2/94 */
-
-         if (current_class_type)
-           {
-             error ("cannot declare member %<%T::%s%> within %qT",
-                    ctype, name, current_class_type);
-             return void_type_node;
-           }
-       }
-      else
-       {
-         cxx_incomplete_type_error (NULL_TREE, ctype);
+         error ("cannot declare member %<%T::%s%> within %qT",
+                ctype, name, current_class_type);
          return error_mark_node;
        }
     }
@@ -7842,6 +7882,18 @@ grokdeclarator (const cp_declarator *declarator,
       if (current_lang_name == lang_name_java)
        TYPE_FOR_JAVA (type) = 1;
 
+      /* This declaration:
+
+          typedef void f(int) const;
+
+        declares a function type which is not a member of any
+        particular class, but which is cv-qualified; for
+        example "f S::*" declares a pointer to a const-qualified
+        member function of S.  We record the cv-qualification in the
+        function type.  */
+      if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
+       type = cp_build_qualified_type (type, memfn_quals);
+
       if (decl_context == FIELD)
        decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
       else
@@ -7902,26 +7954,17 @@ grokdeclarator (const cp_declarator *declarator,
             type with external linkage have external linkage.  */
        }
 
-      if (quals)
-       {
-         if (ctype == NULL_TREE)
-           {
-             if (TREE_CODE (type) == METHOD_TYPE)
-               ctype = TYPE_METHOD_BASETYPE (type);
-             /* Any qualifiers on a function type typedef have
-                already been dealt with. */
-             else if (TREE_CODE (type) == FUNCTION_TYPE)
-               quals = TYPE_UNQUALIFIED;
-           }
-         if (ctype != NULL_TREE)
-           grok_method_quals (ctype, decl, quals);
-       }
+       /* Any qualifiers on a function type typedef have already been
+          dealt with. */
+      if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
+       memfn_quals = TYPE_UNQUALIFIED;
 
       if (signed_p
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
 
-      bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
+      bad_specifiers (decl, "type", virtualp,
+                     memfn_quals != TYPE_UNQUALIFIED,
                      inlinep, friendp, raises != NULL_TREE);
 
       return decl;
@@ -7969,7 +8012,7 @@ grokdeclarator (const cp_declarator *declarator,
 
          /* The qualifiers on the function type become the qualifiers on
             the non-static member function. */
-         quals |= cp_type_quals (type);
+         memfn_quals |= cp_type_quals (type);
        }
     }
 
@@ -8026,7 +8069,7 @@ grokdeclarator (const cp_declarator *declarator,
              type = void_type_node;
            }
        }
-      else if (quals)
+      else if (memfn_quals)
        {
          if (ctype == NULL_TREE)
            {
@@ -8036,11 +8079,7 @@ grokdeclarator (const cp_declarator *declarator,
                ctype = TYPE_METHOD_BASETYPE (type);
            }
          if (ctype)
-           {
-             tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
-             grok_method_quals (ctype, dummy, quals);
-             type = TREE_TYPE (dummy);
-           }
+           type = build_memfn_type (type, ctype, memfn_quals);
        }
 
       return type;
@@ -8098,7 +8137,8 @@ grokdeclarator (const cp_declarator *declarator,
       {
        decl = cp_build_parm_decl (unqualified_id, type);
 
-       bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
+       bad_specifiers (decl, "parameter", virtualp,
+                       memfn_quals != TYPE_UNQUALIFIED,
                        inlinep, friendp, raises != NULL_TREE);
       }
     else if (decl_context == FIELD)
@@ -8121,7 +8161,7 @@ grokdeclarator (const cp_declarator *declarator,
          {
            /* Something like struct S { int N::j; };  */
            error ("invalid use of %<::%>");
-           decl = NULL_TREE;
+           return error_mark_node;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
          {
@@ -8137,7 +8177,7 @@ grokdeclarator (const cp_declarator *declarator,
                  {
                    error ("can't make %qD into a method -- not in a class",
                           unqualified_id);
-                   return void_type_node;
+                   return error_mark_node;
                  }
 
                /* ``A union may [ ... ] not [ have ] virtual functions.''
@@ -8146,7 +8186,7 @@ grokdeclarator (const cp_declarator *declarator,
                  {
                    error ("function %qD declared virtual inside a union",
                           unqualified_id);
-                   return void_type_node;
+                   return error_mark_node;
                  }
 
                if (NEW_DELETE_OPNAME_P (unqualified_id))
@@ -8160,9 +8200,7 @@ grokdeclarator (const cp_declarator *declarator,
                      }
                  }
                else if (staticp < 2)
-                 type = build_method_type_directly (ctype,
-                                                    TREE_TYPE (type),
-                                                    TYPE_ARG_TYPES (type));
+                 type = build_memfn_type (type, ctype, memfn_quals);
              }
 
            /* Check that the name used for a destructor makes sense.  */
@@ -8197,12 +8235,12 @@ grokdeclarator (const cp_declarator *declarator,
                               ? unqualified_id : dname,
                               parms,
                               unqualified_id,
-                              virtualp, flags, quals, raises,
+                              virtualp, flags, memfn_quals, raises,
                               friendp ? -1 : 0, friendp, publicp, inlinep,
                               sfk,
                               funcdef_flag, template_count, in_namespace, attrlist);
            if (decl == NULL_TREE)
-             return decl;
+             return error_mark_node;
 #if 0
            /* This clobbers the attrs stored in `decl' from `attrlist'.  */
            /* The decl and setting of decl_attr is also turned off.  */
@@ -8245,12 +8283,12 @@ grokdeclarator (const cp_declarator *declarator,
                               ? unqualified_id : dname,
                               parms,
                               unqualified_id,
-                              virtualp, flags, quals, raises,
+                              virtualp, flags, memfn_quals, raises,
                               friendp ? -1 : 0, friendp, 1, 0, sfk,
                               funcdef_flag, template_count, in_namespace,
                               attrlist);
            if (decl == NULL_TREE)
-             return NULL_TREE;
+             return error_mark_node;
          }
        else if (!staticp && !dependent_type_p (type)
                 && !COMPLETE_TYPE_P (complete_type (type))
@@ -8302,11 +8340,12 @@ grokdeclarator (const cp_declarator *declarator,
                  }
 
                decl = do_friend (ctype, unqualified_id, decl,
-                                 *attrlist, flags, quals, funcdef_flag);
+                                 *attrlist, flags,
+                                 funcdef_flag);
                return decl;
              }
            else
-             return void_type_node;
+             return error_mark_node;
          }
 
        /* Structure field.  It may not be a function, except for C++.  */
@@ -8345,7 +8384,7 @@ grokdeclarator (const cp_declarator *declarator,
                     void_type_node, as if this was a friend
                     declaration, to cause callers to completely
                     ignore this declaration.  */
-                 return void_type_node;
+                 return error_mark_node;
              }
 
            if (staticp)
@@ -8381,7 +8420,8 @@ grokdeclarator (const cp_declarator *declarator,
                  }
              }
 
-           bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
+           bad_specifiers (decl, "field", virtualp,
+                           memfn_quals != TYPE_UNQUALIFIED,
                            inlinep, friendp, raises != NULL_TREE);
          }
       }
@@ -8392,7 +8432,7 @@ grokdeclarator (const cp_declarator *declarator,
        int publicp = 0;
 
        if (!unqualified_id)
-         return NULL_TREE;
+         return error_mark_node;
 
        if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
          original_name = dname;
@@ -8442,12 +8482,12 @@ grokdeclarator (const cp_declarator *declarator,
                   || storage_class != sc_static);
 
        decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
-                          virtualp, flags, quals, raises,
+                          virtualp, flags, memfn_quals, raises,
                           1, friendp,
                           publicp, inlinep, sfk, funcdef_flag,
                           template_count, in_namespace, attrlist);
        if (decl == NULL_TREE)
-         return NULL_TREE;
+         return error_mark_node;
 
        if (staticp == 1)
          {
@@ -8485,7 +8525,8 @@ grokdeclarator (const cp_declarator *declarator,
                            initialized,
                            (type_quals & TYPE_QUAL_CONST) != 0,
                            ctype ? ctype : in_namespace);
-       bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
+       bad_specifiers (decl, "variable", virtualp,
+                       memfn_quals != TYPE_UNQUALIFIED,
                        inlinep, friendp, raises != NULL_TREE);
 
        if (ctype)
@@ -8806,10 +8847,13 @@ copy_fn_p (tree d)
   tree arg_type;
   int result = 1;
 
-  gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+  if (!DECL_FUNCTION_MEMBER_P (d))
+    /* Non-members are invalid.  We complained, but kept the declaration.  */
+    return 0;
 
-  if (DECL_TEMPLATE_INFO (d)
-      && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d)))
+  if (TREE_CODE (d) == TEMPLATE_DECL
+      || (DECL_TEMPLATE_INFO (d)
+         && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
     /* Instantiations of template member functions are never copy
        functions.  Note that member functions of templated classes are
        represented as template functions internally, and we must
@@ -8821,6 +8865,8 @@ copy_fn_p (tree d)
     return 0;
 
   arg_type = TREE_VALUE (args);
+  if (arg_type == error_mark_node)
+    return 0;
 
   if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
     {
@@ -8849,12 +8895,18 @@ copy_fn_p (tree d)
 
 void grok_special_member_properties (tree decl)
 {
+  tree class_type;
+
   if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
-    ; /* Not special.  */
-  else if (DECL_CONSTRUCTOR_P (decl))
+    return;
+
+  class_type = DECL_CONTEXT (decl);
+  if (DECL_CONSTRUCTOR_P (decl))
     {
       int ctor = copy_fn_p (decl);
 
+      TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+
       if (ctor > 0)
        {
          /* [class.copy]
@@ -8864,12 +8916,12 @@ void grok_special_member_properties (tree decl)
             X&, volatile X& or const volatile X&, and either there
             are no other parameters or else all other parameters have
             default arguments.  */
-         TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
+         TYPE_HAS_INIT_REF (class_type) = 1;
          if (ctor > 1)
-           TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
+           TYPE_HAS_CONST_INIT_REF (class_type) = 1;
        }
       else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
-       TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
+       TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
     }
   else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
     {
@@ -8883,9 +8935,9 @@ void grok_special_member_properties (tree decl)
 
       if (assop)
        {
-         TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+         TYPE_HAS_ASSIGN_REF (class_type) = 1;
          if (assop != 1)
-           TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+           TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
        }
     }
 }
@@ -9076,6 +9128,9 @@ grok_op_properties (tree decl, bool complain)
              for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
                {
                  tree arg = non_reference (TREE_VALUE (p));
+                 if (arg == error_mark_node)
+                   return;
+
                  /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
                     because these checks are performed even on
                     template functions.  */
@@ -10192,7 +10247,7 @@ check_function_type (tree decl, tree current_function_parms)
   if (!COMPLETE_OR_VOID_TYPE_P (return_type))
     {
       tree args = TYPE_ARG_TYPES (fntype);
-         
+
       error ("return type %q#T is incomplete", return_type);
 
       /* Make it return void instead.  */
@@ -10420,12 +10475,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        maybe_apply_pragma_weak (decl1);
     }
 
-  /* Determine the ELF visibility attribute for the function.  We must
-     not do this before calling "pushdecl", as we must allow
-     "duplicate_decls" to merge any attributes appropriately.  */
-  if (!DECL_CLONED_FUNCTION_P (decl1))
-    determine_visibility (decl1);
-
   /* Reset these in case the call to pushdecl changed them.  */
   current_function_decl = decl1;
   cfun->decl = decl1;
@@ -10473,7 +10522,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
                        ignore interface specifications for
                        compiler-generated functions.  */
                     && !DECL_ARTIFICIAL (decl1));
-                    
+
   if (DECL_INTERFACE_KNOWN (decl1))
     {
       tree ctx = decl_function_context (decl1);
@@ -10544,6 +10593,13 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        DECL_INTERFACE_KNOWN (decl1) = 1;
     }
 
+  /* Determine the ELF visibility attribute for the function.  We must not
+     do this before calling "pushdecl", as we must allow "duplicate_decls"
+     to merge any attributes appropriately.  We also need to wait until
+     linkage is set.  */
+  if (!DECL_CLONED_FUNCTION_P (decl1))
+    determine_visibility (decl1);
+
   begin_scope (sk_function_parms, decl1);
 
   ++function_depth;
@@ -10576,13 +10632,6 @@ start_function (cp_decl_specifier_seq *declspecs,
 {
   tree decl1;
 
-  if (have_extern_spec)
-    {
-      declspecs->storage_class = sc_extern;
-      /* This should only be done once on the outermost decl.  */
-      have_extern_spec = false;
-    }
-
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
@@ -10766,7 +10815,7 @@ begin_destructor_body (void)
         tables.  */
       initialize_vtbl_ptrs (current_class_ptr);
       finish_compound_stmt (compound_stmt);
-      
+
       /* And insert cleanups for our bases and members so that they
         will be properly destroyed if we throw.  */
       push_base_cleanups ();
@@ -10797,9 +10846,11 @@ finish_destructor_body (void)
       an implicit definition), non-placement operator delete shall
       be looked up in the scope of the destructor's class and if
       found shall be accessible and unambiguous.  */
-      exprstmt = build_op_delete_call
-       (DELETE_EXPR, current_class_ptr, virtual_size,
-        /*global_p=*/false, NULL_TREE);
+      exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr,
+                                     virtual_size,
+                                     /*global_p=*/false,
+                                     /*placement=*/NULL_TREE,
+                                     /*alloc_fn=*/NULL_TREE);
 
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
@@ -10869,7 +10920,7 @@ finish_function_body (tree compstmt)
 {
   if (compstmt == NULL_TREE)
     return;
-  
+
   /* Close the block.  */
   finish_compound_stmt (compstmt);
 
@@ -11078,6 +11129,7 @@ finish_function (int flags)
       f->x_vtt_parm = NULL;
       f->x_return_value = NULL;
       f->bindings = NULL;
+      f->extern_decl_map = NULL;
 
       /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
       c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
@@ -11187,7 +11239,6 @@ start_method (cp_decl_specifier_seq *declspecs,
          fndecl = copy_node (fndecl);
          TREE_CHAIN (fndecl) = NULL_TREE;
        }
-      grok_special_member_properties (fndecl);
     }
 
   finish_decl (fndecl, NULL_TREE, NULL_TREE);