OSDN Git Service

gcc/cp/
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 6172296..83d2c4e 100644 (file)
@@ -1,6 +1,7 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -356,12 +357,7 @@ pop_label (tree label, tree old_value)
          location_t location;
 
          error ("label %q+D used but not defined", label);
-#ifdef USE_MAPPED_LOCATION
          location = input_location; /* FIXME want (input_filename, (line)0) */
-#else
-         location.file = input_filename;
-         location.line = 0;
-#endif
          /* Avoid crashing later.  */
          define_label (location, DECL_NAME (label));
        }
@@ -587,7 +583,7 @@ poplevel (int keep, int reverse, int functionbody)
 
   /* In each subblock, record that this is its superior.  */
   if (keep >= 0)
-    for (link = subblocks; link; link = TREE_CHAIN (link))
+    for (link = subblocks; link; link = BLOCK_CHAIN (link))
       BLOCK_SUPERCONTEXT (link) = block;
 
   /* We still support the old for-scope rules, whereby the variables
@@ -1059,8 +1055,8 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
     return;
 
   name = DECL_ASSEMBLER_NAME (newdecl);
-  pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
-  pedwarn ("previous declaration of %q+D", olddecl);
+  permerror ("%qD was declared %<extern%> and later %<static%>", newdecl);
+  permerror ("previous declaration of %q+D", olddecl);
 }
 
 /* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
@@ -1098,6 +1094,10 @@ check_redeclaration_exception_specification (tree new_decl,
     }
 }
 
+#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn)                  \
+                         && lookup_attribute ("gnu_inline",            \
+                                              DECL_ATTRIBUTES (fn)))
+
 /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
    If the redeclaration is invalid, a diagnostic is issued, and the
    error_mark_node is returned.  Otherwise, OLDDECL is returned.
@@ -1276,6 +1276,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
        }
 
+      /* If a function is explicitly declared "throw ()", propagate that to
+        the corresponding builtin.  */
+      if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
+         && DECL_ANTICIPATED (olddecl)
+         && TREE_NOTHROW (newdecl)
+         && !TREE_NOTHROW (olddecl)
+         && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
+         && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
+         && types_match)
+       TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+
       /* Whether or not the builtin can throw exceptions has no
         bearing on this declarator.  */
       TREE_NOTHROW (olddecl) = 0;
@@ -1528,9 +1539,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
                if (1 == simple_cst_equal (TREE_PURPOSE (t1),
                                           TREE_PURPOSE (t2)))
                  {
-                   pedwarn ("default argument given for parameter %d of %q#D",
-                            i, newdecl);
-                   pedwarn ("after previous specification in %q+#D", olddecl);
+                   permerror ("default argument given for parameter %d of %q#D",
+                              i, newdecl);
+                   permerror ("after previous specification in %q+#D", olddecl);
                  }
                else
                  {
@@ -1634,20 +1645,51 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
                   DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
 
+      DECL_ATTRIBUTES (old_result)
+       = (*targetm.merge_decl_attributes) (old_result, new_result);
+
       if (DECL_FUNCTION_TEMPLATE_P (newdecl))
        {
-         DECL_INLINE (old_result)
-           |= DECL_INLINE (new_result);
-         DECL_DECLARED_INLINE_P (old_result)
-           |= DECL_DECLARED_INLINE_P (new_result);
-         check_redeclaration_exception_specification (newdecl, olddecl);
+         if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
+             && DECL_INITIAL (new_result))
+           {
+             if (DECL_INITIAL (old_result))
+               {
+                 DECL_INLINE (old_result) = 0;
+                 DECL_UNINLINABLE (old_result) = 1;
+               }
+             else
+               {
+                 DECL_INLINE (old_result) = DECL_INLINE (new_result);
+                 DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
+               }
+             DECL_EXTERNAL (old_result) = DECL_EXTERNAL (new_result);
+             DECL_NOT_REALLY_EXTERN (old_result)
+               = DECL_NOT_REALLY_EXTERN (new_result);
+             DECL_INTERFACE_KNOWN (old_result)
+               = DECL_INTERFACE_KNOWN (new_result);
+             DECL_DECLARED_INLINE_P (old_result)
+               = DECL_DECLARED_INLINE_P (new_result);
+             DECL_DISREGARD_INLINE_LIMITS (old_result)
+               |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+
+           }
+         else
+           {
+             DECL_INLINE (old_result)
+               |= DECL_INLINE (new_result);
+             DECL_DECLARED_INLINE_P (old_result)
+               |= DECL_DECLARED_INLINE_P (new_result);
+             DECL_DISREGARD_INLINE_LIMITS (old_result)
+               |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+             check_redeclaration_exception_specification (newdecl, olddecl);
+           }
        }
 
       /* If the new declaration is a definition, update the file and
         line information on the declaration, and also make
         the old declaration the same definition.  */
-      if (DECL_INITIAL (old_result) == NULL_TREE
-         && DECL_INITIAL (new_result) != NULL_TREE)
+      if (DECL_INITIAL (new_result) != NULL_TREE)
        {
          DECL_SOURCE_LOCATION (olddecl)
            = DECL_SOURCE_LOCATION (old_result)
@@ -1760,10 +1802,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
          DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
          TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
          TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
          DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
-         DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+         DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+         DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         DECL_LOOPING_CONST_OR_PURE_P (newdecl) 
+           |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
          /* Keep the old RTL.  */
          COPY_DECL_RTL (olddecl, newdecl);
        }
@@ -1805,9 +1850,29 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   new_template = NULL_TREE;
   if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
     {
-      DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
-      DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
-      DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+      bool new_redefines_gnu_inline = false;
+
+      if (new_defines_function
+         && ((DECL_INTERFACE_KNOWN (olddecl)
+              && TREE_CODE (olddecl) == FUNCTION_DECL)
+             || (TREE_CODE (olddecl) == TEMPLATE_DECL
+                 && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+                     == FUNCTION_DECL))))
+       {
+         tree fn = olddecl;
+
+         if (TREE_CODE (fn) == TEMPLATE_DECL)
+           fn = DECL_TEMPLATE_RESULT (olddecl);
+
+         new_redefines_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
+       }
+
+      if (!new_redefines_gnu_inline)
+       {
+         DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
+         DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+         DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+       }
       DECL_TEMPLATE_INSTANTIATED (newdecl)
        |= DECL_TEMPLATE_INSTANTIATED (olddecl);
 
@@ -1881,6 +1946,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          /* [temp.expl.spec/14] We don't inline explicit specialization
             just because the primary template says so.  */
        }
+      else if (new_defines_function && DECL_INITIAL (olddecl))
+       {
+         /* C++ is always in in unit-at-a-time mode, so we never
+            inline re-defined extern inline functions.  */
+         DECL_INLINE (newdecl) = 0;
+         DECL_UNINLINABLE (newdecl) = 1;
+       }
       else
        {
          if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
@@ -1896,6 +1968,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
          DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
            = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+         DECL_DISREGARD_INLINE_LIMITS (newdecl)
+           = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+           = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+              || DECL_DISREGARD_INLINE_LIMITS (olddecl));
        }
 
       /* Preserve abstractness on cloned [cd]tors.  */
@@ -2123,9 +2200,25 @@ redeclaration_error_message (tree newdecl, tree olddecl)
        {
          if (DECL_NAME (olddecl) == NULL_TREE)
            return "%q#D not declared in class";
-         else
+         else if (!GNU_INLINE_P (olddecl)
+                  || GNU_INLINE_P (newdecl))
            return "redefinition of %q#D";
        }
+
+      if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
+       {
+         bool olda = GNU_INLINE_P (olddecl);
+         bool newa = GNU_INLINE_P (newdecl);
+
+         if (olda != newa)
+           {
+             if (newa)
+               return "%q+D redeclared inline with %<gnu_inline%> attribute";
+             else
+               return "%q+D redeclared inline without %<gnu_inline%> attribute";
+           }
+       }
+
       return NULL;
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@@ -2151,9 +2244,24 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       ot = DECL_TEMPLATE_RESULT (olddecl);
       if (DECL_TEMPLATE_INFO (ot))
        ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
-      if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
+      if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
+         && (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
        return "redefinition of %q#D";
 
+      if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
+       {
+         bool olda = GNU_INLINE_P (ot);
+         bool newa = GNU_INLINE_P (nt);
+
+         if (olda != newa)
+           {
+             if (newa)
+               return "%q+D redeclared inline with %<gnu_inline%> attribute";
+             else
+               return "%q+D redeclared inline without %<gnu_inline%> attribute";
+           }
+       }
+
       /* Core issue #226 (C++0x): 
            
            If a friend function template declaration specifies a
@@ -2350,11 +2458,11 @@ static void
 identify_goto (tree decl, const location_t *locus)
 {
   if (decl)
-    pedwarn ("jump to label %qD", decl);
+    permerror ("jump to label %qD", decl);
   else
-    pedwarn ("jump to case label");
+    permerror ("jump to case label");
   if (locus)
-    pedwarn ("%H  from here", locus);
+    permerror ("%H  from here", locus);
 }
 
 /* Check that a single previously seen jump to a newly defined label
@@ -2396,7 +2504,7 @@ check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
          if (problem > 1)
            error ("  crosses initialization of %q+#D", new_decls);
          else
-           pedwarn ("  enters scope of non-POD %q+#D", new_decls);
+           permerror ("  enters scope of non-POD %q+#D", new_decls);
        }
 
       if (b == level)
@@ -2492,8 +2600,8 @@ check_goto (tree decl)
   if (ent->in_try_scope || ent->in_catch_scope
       || ent->in_omp_scope || ent->bad_decls)
     {
-      pedwarn ("jump to label %q+D", decl);
-      pedwarn ("  from here");
+      permerror ("jump to label %q+D", decl);
+      permerror ("  from here");
       identified = true;
     }
 
@@ -2511,7 +2619,7 @@ check_goto (tree decl)
       else if (u > 1)
        error ("  skips initialization of %q+#D", b);
       else
-       pedwarn ("  enters scope of non-POD %q+#D", b);
+       permerror ("  enters scope of non-POD %q+#D", b);
     }
 
   if (ent->in_try_scope)
@@ -2532,8 +2640,8 @@ check_goto (tree decl)
            {
              if (!identified)
                {
-                 pedwarn ("jump to label %q+D", decl);
-                 pedwarn ("  from here");
+                 permerror ("jump to label %q+D", decl);
+                 permerror ("  from here");
                  identified = true;
                }
              error ("  exits OpenMP structured block");
@@ -2585,7 +2693,7 @@ define_label (location_t location, tree name)
     p->more_cleanups_ok = 0;
 
   if (name == get_identifier ("wchar_t"))
-    pedwarn ("label named wchar_t");
+    permerror ("label named wchar_t");
 
   if (DECL_INITIAL (decl) != NULL_TREE)
     {
@@ -2785,7 +2893,7 @@ build_typename_type (tree context, tree name, tree fullname,
   else
     {
       /* Build the TYPENAME_TYPE.  */
-      t = make_aggr_type (TYPENAME_TYPE);
+      t = cxx_make_type (TYPENAME_TYPE);
       TYPE_CONTEXT (t) = ti.scope;
       TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
       TYPENAME_IS_ENUM_P (t) = ti.enum_p;
@@ -2873,7 +2981,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   if (dependent_type_p (context))
     return build_typename_type (context, name, fullname, tag_type);
 
-  if (!IS_AGGR_TYPE (context))
+  if (!MAYBE_CLASS_TYPE_P (context))
     {
       if (complain & tf_error)
        error ("%q#T is not a class", context);
@@ -2950,7 +3058,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
     {
       tree tmpl = NULL_TREE;
 
-      if (IS_AGGR_TYPE (context))
+      if (MAYBE_CLASS_TYPE_P (context))
        tmpl = lookup_field (context, name, 0, false);
 
       if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
@@ -2978,7 +3086,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
     }
 
   /* Build the UNBOUND_CLASS_TEMPLATE.  */
-  t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+  t = cxx_make_type (UNBOUND_CLASS_TEMPLATE);
   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
   TREE_TYPE (t) = NULL_TREE;
   SET_TYPE_STRUCTURAL_EQUALITY (t);
@@ -3236,6 +3344,9 @@ cxx_init_decl_processing (void)
   TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
   TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
 
+  init_list_type_node = make_node (UNKNOWN_TYPE);
+  record_unknown_type (init_list_type_node, "init list");
+
   {
     /* Make sure we get a unique function type, so we can give
        its pointer type a name.  (This wins for gdb.) */
@@ -3276,7 +3387,7 @@ cxx_init_decl_processing (void)
 
     push_namespace (std_identifier);
     bad_alloc_id = get_identifier ("bad_alloc");
-    bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
+    bad_alloc_type_node = make_class_type (RECORD_TYPE);
     TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
     bad_alloc_decl
       = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
@@ -3368,7 +3479,7 @@ cp_make_fname_decl (tree id, int type_dep)
   tree decl = build_decl (VAR_DECL, id, type);
 
   if (name)
-    free (CONST_CAST (name));
+    free (CONST_CAST (char *, name));
 
   /* As we're using pushdecl_with_scope, we must set the context.  */
   DECL_CONTEXT (decl) = current_function_decl;
@@ -3424,6 +3535,17 @@ builtin_function_1 (tree decl, tree context)
      anticipated but not actually declared.  */
   if (name[0] != '_' || name[1] != '_')
     DECL_ANTICIPATED (decl) = 1;
+  else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0)
+    {
+      size_t len = strlen (name);
+
+      /* Treat __*_chk fortification functions as anticipated as well,
+        unless they are __builtin_*.  */
+      if (len > strlen ("___chk")
+         && memcmp (name + len - strlen ("_chk"),
+                    "_chk", strlen ("_chk") + 1) == 0)
+       DECL_ANTICIPATED (decl) = 1;
+    }
 
   return decl;
 }
@@ -3569,7 +3691,7 @@ fixup_anonymous_aggr (tree t)
   tree *q;
 
   /* Wipe out memory of synthesized methods.  */
-  TYPE_HAS_CONSTRUCTOR (t) = 0;
+  TYPE_HAS_USER_CONSTRUCTOR (t) = 0;
   TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
   TYPE_HAS_INIT_REF (t) = 0;
   TYPE_HAS_CONST_INIT_REF (t) = 0;
@@ -3589,8 +3711,14 @@ fixup_anonymous_aggr (tree t)
 
   /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
-    error ("%Jan anonymous union cannot have function members",
-          TYPE_MAIN_DECL (t));
+    {
+      tree decl = TYPE_MAIN_DECL (t);
+
+      if (TREE_CODE (t) != UNION_TYPE)
+       error ("%Jan anonymous struct cannot have function members", decl);
+      else
+       error ("%Jan anonymous union cannot have function members", decl);
+    }
 
   /* Anonymous aggregates cannot have fields with ctors, dtors or complex
      assignment operators (because they cannot have these methods themselves).
@@ -3642,23 +3770,23 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
   else if (declspecs->redefined_builtin_type)
     {
       if (!in_system_header)
-       pedwarn ("redeclaration of C++ built-in type %qT",
-                declspecs->redefined_builtin_type);
+       permerror ("redeclaration of C++ built-in type %qT",
+                  declspecs->redefined_builtin_type);
       return NULL_TREE;
     }
 
   if (declspecs->type
       && TYPE_P (declspecs->type)
       && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
-          && IS_AGGR_TYPE (declspecs->type))
+          && MAYBE_CLASS_TYPE_P (declspecs->type))
          || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
     declared_type = declspecs->type;
   else if (declspecs->type == error_mark_node)
     error_p = true;
   if (declared_type == NULL_TREE && ! saw_friend && !error_p)
-    pedwarn ("declaration does not declare anything");
+    permerror ("declaration does not declare anything");
   /* Check for an anonymous union.  */
-  else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))
+  else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
           && TYPE_ANONYMOUS_P (declared_type))
     {
       /* 7/3 In a simple-declaration, the optional init-declarator-list
@@ -3782,25 +3910,35 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
   attrs = type_specifiers->attributes;
   type_specifiers->attributes = NULL_TREE;
   type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
-  if (attrs)
-    cplus_decl_attributes (&type, attrs, 0);
+  if (attrs && type != error_mark_node)
+    {
+      if (CLASS_TYPE_P (type))
+       warning (OPT_Wattributes, "ignoring attributes applied to class type %qT "
+                "outside of definition", type);
+      else if (MAYBE_CLASS_TYPE_P (type))
+       /* A template type parameter or other dependent type.  */
+       warning (OPT_Wattributes, "ignoring attributes applied to dependent "
+                "type %qT without an associated declaration", type);
+      else
+       cplus_decl_attributes (&type, attrs, 0);
+    }
   return type;
 }
 
-/* Decode a declarator in an ordinary declaration or data definition.
-   This is called as soon as the type information and variable name
-   have been parsed, before parsing the initializer if any.
-   Here we create the ..._DECL node, fill in its type,
-   and put it on the list of decls for the current context.
-   The ..._DECL node is returned as the value.
-
-   Exception: for arrays where the length is not specified,
-   the type is left null, to be filled in by `cp_finish_decl'.
-
-   Function definitions do not come here; they go to start_function
-   instead.  However, external and forward declarations of functions
-   do go through here.  Structure field declarations are done by
-   grokfield and not through here.  */
+/* Process a DECLARATOR for a function-scope variable declaration,
+   namespace-scope variable declaration, or function declaration.
+   (Function definitions go through start_function; class member
+   declarations appearing in the body of the class go through
+   grokfield.)  The DECL corresponding to the DECLARATOR is returned.
+   If an error occurs, the error_mark_node is returned instead.
+   
+   DECLSPECS are the decl-specifiers for the declaration.  INITIALIZED
+   is true if an explicit initializer is present, but false if this is
+   a variable implicitly initialized via a default constructor.
+   ATTRIBUTES and PREFIX_ATTRIBUTES are GNU attributes associated with
+   this declaration.  *PUSHED_SCOPE_P is set to the scope entered in
+   this function, if any; if set, the caller is responsible for
+   calling pop_scope.  */
 
 tree
 start_decl (const cp_declarator *declarator,
@@ -3811,9 +3949,10 @@ start_decl (const cp_declarator *declarator,
            tree *pushed_scope_p)
 {
   tree decl;
-  tree type, tem;
+  tree type;
   tree context;
   bool was_public;
+  int flags;
 
   *pushed_scope_p = NULL_TREE;
 
@@ -3875,8 +4014,17 @@ start_decl (const cp_declarator *declarator,
        TREE_STATIC (decl) = 1;
     }
 
+  /* If this is a typedef that names the class for linkage purposes
+     (7.1.3p8), apply any attributes directly to the type.  */
+  if (TREE_CODE (decl) == TYPE_DECL
+      && TAGGED_TYPE_P (TREE_TYPE (decl))
+      && decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
+    flags = ATTR_FLAG_TYPE_IN_PLACE;
+  else
+    flags = 0;
+
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
-  cplus_decl_attributes (&decl, attributes, 0);
+  cplus_decl_attributes (&decl, attributes, flags);
 
   /* Dllimported symbols cannot be defined.  Static data members (which
      can be initialized in-class and dllimported) go through grokfield,
@@ -3909,10 +4057,10 @@ start_decl (const cp_declarator *declarator,
              if (DECL_CONTEXT (field) != context)
                {
                  if (!same_type_p (DECL_CONTEXT (field), context))
-                   pedwarn ("ISO C++ does not permit %<%T::%D%> "
-                            "to be defined as %<%T::%D%>",
-                            DECL_CONTEXT (field), DECL_NAME (decl),
-                            context, DECL_NAME (decl));
+                   permerror ("ISO C++ does not permit %<%T::%D%> "
+                              "to be defined as %<%T::%D%>",
+                              DECL_CONTEXT (field), DECL_NAME (decl),
+                              context, DECL_NAME (decl));
                  DECL_CONTEXT (decl) = DECL_CONTEXT (field);
                }
              if (processing_specialization
@@ -3965,18 +4113,18 @@ start_decl (const cp_declarator *declarator,
        }
 
       if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
-       pedwarn ("declaration of %q#D outside of class is not definition",
-                decl);
+       permerror ("declaration of %q#D outside of class is not definition",
+                  decl);
     }
 
   was_public = TREE_PUBLIC (decl);
 
   /* Enter this declaration into the symbol table.  */
-  tem = maybe_push_decl (decl);
+  decl = maybe_push_decl (decl);
 
   if (processing_template_decl)
-    tem = push_template_decl (tem);
-  if (tem == error_mark_node)
+    decl = push_template_decl (decl);
+  if (decl == error_mark_node)
     return error_mark_node;
 
   /* Tell the back end to use or not use .common as appropriate.  If we say
@@ -3985,33 +4133,42 @@ start_decl (const cp_declarator *declarator,
      produce errors about redefs; to do this we force variables into the
      data segment.  */
   if (flag_conserve_space
-      && TREE_CODE (tem) == VAR_DECL
-      && TREE_PUBLIC (tem)
-      && !DECL_THREAD_LOCAL_P (tem)
+      && TREE_CODE (decl) == VAR_DECL
+      && TREE_PUBLIC (decl)
+      && !DECL_THREAD_LOCAL_P (decl)
       && !have_global_bss_p ())
-    DECL_COMMON (tem) = 1;
+    DECL_COMMON (decl) = 1;
 
-  if (TREE_CODE (tem) == VAR_DECL
-      && DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
-      && !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
+  if (TREE_CODE (decl) == VAR_DECL
+      && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
+      && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
     {
       /* 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_readonly (TREE_TYPE (tem)));
-      DECL_THIS_STATIC (tem) = 1;
+      gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+      DECL_THIS_STATIC (decl) = 1;
     }
 
-  if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
-    start_decl_1 (tem, initialized);
+  if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+    start_decl_1 (decl, initialized);
 
-  return tem;
+  return decl;
 }
 
+/* Process the declaration of a variable DECL.  INITIALIZED is true
+   iff DECL is explicitly initialized.  (INITIALIZED is false if the
+   variable is initialized via an implicitly-called constructor.)
+   This function must be called for ordinary variables (including, for
+   example, implicit instantiations of templates), but must not be
+   called for template declarations.  */
+
 void
 start_decl_1 (tree decl, bool initialized)
 {
   tree type;
+  bool complete_p;
+  bool aggregate_definition_p;
 
   gcc_assert (!processing_template_decl);
 
@@ -4019,21 +4176,37 @@ start_decl_1 (tree decl, bool initialized)
     return;
 
   gcc_assert (TREE_CODE (decl) == VAR_DECL);
+
   type = TREE_TYPE (decl);
+  complete_p = COMPLETE_TYPE_P (type);
+  aggregate_definition_p = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
+
+  /* If an explicit initializer is present, or if this is a definition
+     of an aggregate, then we need a complete type at this point.
+     (Scalars are always complete types, so there is nothing to
+     check.)  This code just sets COMPLETE_P; errors (if necessary)
+     are issued below.  */
+  if ((initialized || aggregate_definition_p) 
+      && !complete_p
+      && COMPLETE_TYPE_P (complete_type (type)))
+    {
+      complete_p = true;
+      /* We will not yet have set TREE_READONLY on DECL if the type
+        was "const", but incomplete, before this point.  But, now, we
+        have a complete type, so we can try again.  */
+      cp_apply_type_quals_to_decl (cp_type_quals (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
-       tell `cp_finish_decl' to ignore the initializer once it is parsed.  */
+    /* Is it valid for this decl to have an initializer at all?  */
     {
       /* Don't allow initializations for incomplete types except for
         arrays which might be completed by the initialization.  */
-      if (COMPLETE_TYPE_P (complete_type (type)))
+      if (complete_p)
        ;                       /* A complete type is ok.  */
       else if (TREE_CODE (type) != ARRAY_TYPE)
        {
          error ("variable %q#D has initializer but incomplete type", decl);
-         initialized = 0;
          type = TREE_TYPE (decl) = error_mark_node;
        }
       else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
@@ -4041,30 +4214,15 @@ start_decl_1 (tree decl, bool initialized)
          if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
            error ("elements of array %q#D have incomplete type", decl);
          /* else we already gave an error in start_decl.  */
-         initialized = 0;
        }
     }
-  else if (IS_AGGR_TYPE (type)
-          && ! DECL_EXTERNAL (decl))
+  else if (aggregate_definition_p && !complete_p)
     {
-      if (!COMPLETE_TYPE_P (complete_type (type)))
-       {
-         error ("aggregate %q#D has incomplete type and cannot be defined",
-                decl);
-         /* Change the type so that assemble_variable will give
-            DECL an rtl we can live with: (mem (const_int 0)).  */
-         type = TREE_TYPE (decl) = error_mark_node;
-       }
-      else
-       {
-         /* If any base type in the hierarchy of TYPE needs a constructor,
-            then we set initialized to 1.  This way any nodes which are
-            created for the purposes of initializing this aggregate
-            will live as long as it does.  This is necessary for global
-            aggregates which do not have their initializers processed until
-            the end of the file.  */
-         initialized = TYPE_NEEDS_CONSTRUCTING (type);
-       }
+      error ("aggregate %q#D has incomplete type and cannot be defined",
+            decl);
+      /* Change the type so that assemble_variable will give
+        DECL an rtl we can live with: (mem (const_int 0)).  */
+      type = TREE_TYPE (decl) = error_mark_node;
     }
 
   /* Create a new scope to hold this declaration if necessary.
@@ -4140,6 +4298,39 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
   return NULL_TREE;
 }
 
+/* Subroutine of check_initializer.  We're initializing a DECL of
+   std::initializer_list<T> TYPE from a braced-init-list INIT, and need to
+   extend the lifetime of the underlying array to match that of the decl,
+   just like for reference initialization.  CLEANUP is as for
+   grok_reference_init.  */
+
+static tree
+build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+{
+  tree aggr_init, array, arrtype;
+  init = perform_implicit_conversion (type, init, tf_warning_or_error);
+  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);
+  gcc_assert (TREE_CODE (array) == ADDR_EXPR);
+  array = TREE_OPERAND (array, 0);
+  /* If the array is constant, finish_compound_literal already made it a
+     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);
+      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;
+}
+
 /* Designated initializers in arrays are not supported in GNU C++.
    The parser cannot detect this error since it does not know whether
    a given brace-enclosed initializer is for a class type or for an
@@ -4194,7 +4385,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
          HOST_WIDE_INT i;
          for (i = 0; 
               VEC_iterate (constructor_elt, v, i, ce);
-              ++i)
+              ++i) 
            if (!check_array_designated_initializer (ce))
              failure = 1;
        }
@@ -4274,7 +4465,7 @@ layout_var_decl (tree decl)
   /* Keep this code around in case we later want to control debug info
      based on whether a type is "used".  (jason 1999-11-11) */
 
-  else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
+  else if (!DECL_EXTERNAL (decl) && MAYBE_CLASS_TYPE_P (ttype))
     /* Let debugger know it should output info for this type.  */
     note_debug_info_needed (ttype);
 
@@ -4289,7 +4480,10 @@ layout_var_decl (tree decl)
       if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
        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;
+       }
     }
 }
 
@@ -4415,7 +4609,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
   unsigned HOST_WIDE_INT index;
 
   /* The initializer for an array is always a CONSTRUCTOR.  */
-  new_init = build_constructor (NULL_TREE, NULL);
+  new_init = build_constructor (init_list_type_node, NULL);
 
   if (sized_array_p)
     {
@@ -4510,7 +4704,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
   gcc_assert (CLASS_TYPE_P (type));
 
   /* The initializer for a class is always a CONSTRUCTOR.  */
-  new_init = build_constructor (NULL_TREE, NULL);
+  new_init = build_constructor (init_list_type_node, NULL);
   field = next_initializable_field (TYPE_FIELDS (type));
 
   if (!field)
@@ -4736,6 +4930,58 @@ reshape_init (tree type, tree init)
   return new_init;
 }
 
+/* Verify array initializer.  Returns true if errors have been reported.  */
+
+bool
+check_array_initializer (tree decl, tree type, tree init)
+{
+  tree element_type = TREE_TYPE (type);
+
+  /* The array type itself need not be complete, because the
+     initializer may tell us how many elements are in the array.
+     But, the elements of the array must be complete.  */
+  if (!COMPLETE_TYPE_P (complete_type (element_type)))
+    {
+      if (decl)
+       error ("elements of array %q#D have incomplete type", decl);
+      else
+       error ("elements of array %q#T have incomplete type", type);
+      return true;
+    }
+  /* It is not valid to initialize a VLA.  */
+  if (init
+      && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+         || !TREE_CONSTANT (TYPE_SIZE (element_type))))
+    {
+      if (decl)
+       error ("variable-sized object %qD may not be initialized", decl);
+      else
+       error ("variable-sized compound literal");
+      return true;
+    }
+  return false;
+}
+
+/* Subroutine of check_initializer; args are passed down from that function.
+   Set stmts_are_full_exprs_p to 1 across a call to build_aggr_init.  */
+
+static tree
+build_aggr_init_full_exprs (tree decl, tree init, int flags)
+     
+{
+  int saved_stmts_are_full_exprs_p = 0;
+  if (building_stmt_tree ())
+    {
+      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+      current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+    }
+  init = build_aggr_init (decl, init, flags, tf_warning_or_error);
+  if (building_stmt_tree ())
+    current_stmt_tree ()->stmts_are_full_exprs_p =
+      saved_stmts_are_full_exprs_p;
+  return init;
+}
+
 /* Verify INIT (the initializer for DECL), and record the
    initialization in DECL_INITIAL, if appropriate.  CLEANUP is as for
    grok_reference_init.
@@ -4759,24 +5005,8 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      tree element_type = TREE_TYPE (type);
-
-      /* The array type itself need not be complete, because the
-        initializer may tell us how many elements are in the array.
-        But, the elements of the array must be complete.  */
-      if (!COMPLETE_TYPE_P (complete_type (element_type)))
-       {
-         error ("elements of array %q#D have incomplete type", decl);
-         return NULL_TREE;
-       }
-      /* It is not valid to initialize a VLA.  */
-      if (init
-         && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
-             || !TREE_CONSTANT (TYPE_SIZE (element_type))))
-       {
-         error ("variable-sized object %qD may not be initialized", decl);
-         return NULL_TREE;
-       }
+      if (check_array_initializer (decl, type, init))
+       return NULL_TREE;
     }
   else if (!COMPLETE_TYPE_P (type))
     {
@@ -4793,7 +5023,12 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
       int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
       if (SCALAR_TYPE_P (type))
        {
-         if (init_len != 1)
+         if (init_len == 0)
+           {
+             maybe_warn_cpp0x ("extended initializer lists");
+             init = build_zero_init (type, NULL_TREE, false);
+           }
+         else if (init_len != 1)
            {
              error ("scalar object %qD requires one element in initializer",
                     decl);
@@ -4801,15 +5036,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
              return NULL_TREE;
            }
        }
-      else if ((cxx_dialect == cxx98) && !CP_AGGREGATE_TYPE_P (type))
-       {
-         /* A non-aggregate that is not a scalar cannot be initialized
-            via an initializer-list in C++98.  */
-         error ("braces around initializer for non-aggregate type %qT",
-                type);
-         TREE_TYPE (decl) = error_mark_node;
-         return NULL_TREE;
-       }
     }
 
   if (TREE_CODE (decl) == CONST_DECL)
@@ -4827,17 +5053,26 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
     {
       /* Do not reshape constructors of vectors (they don't need to be
         reshaped.  */
-      if (TREE_CODE (init) == CONSTRUCTOR
-         && !COMPOUND_LITERAL_P (init)
-         && !TREE_TYPE (init))  /* ptrmemfunc */
+      if (BRACE_ENCLOSED_INITIALIZER_P (init))
        {
-         init = reshape_init (type, init);
-
-         if ((*targetm.vector_opaque_p) (type))
+         if (is_std_init_list (type))
+           return build_init_list_var_init (decl, type, init, cleanup);
+         else if (TYPE_NON_AGGREGATE_CLASS (type))
+           {
+             /* Don't reshape if the class has constructors.  */
+             if (cxx_dialect == cxx98)
+               error ("in C++98 %qD must be initialized by constructor, "
+                      "not by %<{...}%>",
+                      decl);
+             init = build_tree_list (NULL_TREE, init);
+           }
+         else if ((*targetm.vector_opaque_p) (type))
            {
              error ("opaque vector types cannot be initialized");
              init = error_mark_node;
            }
+         else
+           init = reshape_init (type, init);       
        }
 
       /* If DECL has an array type without a specific bound, deduce the
@@ -4847,61 +5082,27 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
       if (type == error_mark_node)
        return NULL_TREE;
 
-      if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
-       {
-         if (TREE_CODE (type) == ARRAY_TYPE)
-           goto initialize_aggr;
-         else if (TREE_CODE (init) == CONSTRUCTOR)
-           {
-             if (TYPE_NON_AGGREGATE_CLASS (type))
-               {
-                 error ("%qD must be initialized by constructor, "
-                        "not by %<{...}%>",
-                        decl);
-                 init = error_mark_node;
-               }
-             else
-               goto dont_use_constructor;
-           }
-         else
-           {
-             int saved_stmts_are_full_exprs_p;
-
-           initialize_aggr:
-             saved_stmts_are_full_exprs_p = 0;
-             if (building_stmt_tree ())
-               {
-                 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
-                 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-               }
-             init = build_aggr_init (decl, init, flags);
-             if (building_stmt_tree ())
-               current_stmt_tree ()->stmts_are_full_exprs_p =
-                 saved_stmts_are_full_exprs_p;
-             return init;
-           }
-       }
-      else
+      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)
        {
-       dont_use_constructor:
-         if (TREE_CODE (init) != TREE_VEC)
-           {
-             init_code = store_init_value (decl, init);
-             if (pedantic && TREE_CODE (type) == ARRAY_TYPE
-                 && DECL_INITIAL (decl)
-                 && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
-                 && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
-               warning (0, "array %qD initialized by parenthesized string literal %qE",
-                        decl, DECL_INITIAL (decl));
-             init = NULL;
-           }
+         init_code = store_init_value (decl, init);
+         if (pedantic && TREE_CODE (type) == ARRAY_TYPE
+             && DECL_INITIAL (decl)
+             && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+             && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
+           warning (0, "array %qD initialized by parenthesized string literal %qE",
+                    decl, DECL_INITIAL (decl));
+         init = NULL;
        }
     }
   else if (DECL_EXTERNAL (decl))
     ;
   else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
-    goto initialize_aggr;
-  else if (IS_AGGR_TYPE (type))
+    return build_aggr_init_full_exprs (decl, init, flags);
+  else if (MAYBE_CLASS_TYPE_P (type))
     {
       tree core_type = strip_array_types (type);
 
@@ -4965,7 +5166,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
       /* An in-class declaration of a static data member should be
         external; it is only a declaration, and not a definition.  */
       if (init == NULL_TREE)
-       gcc_assert (DECL_EXTERNAL (decl));
+       gcc_assert (DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl));
     }
 
   /* We don't create any RTL for local variables.  */
@@ -5009,6 +5210,55 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
     rest_of_decl_compilation (decl, toplev, at_eof);
 }
 
+/* walk_tree helper for wrap_temporary_cleanups, below.  */
+
+static tree
+wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+  if (TYPE_P (*stmt_p))
+    {
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
+  if (TREE_CODE (*stmt_p) == TARGET_EXPR)
+    {
+      tree guard = (tree)data;
+      tree tcleanup = TARGET_EXPR_CLEANUP (*stmt_p);
+
+      tcleanup = build2 (TRY_CATCH_EXPR, void_type_node, tcleanup, guard);
+      /* Tell honor_protect_cleanup_actions to handle this as a separate
+        cleanup.  */
+      TRY_CATCH_IS_CLEANUP (tcleanup) = 1;
+      TARGET_EXPR_CLEANUP (*stmt_p) = tcleanup;
+    }
+
+  return NULL_TREE;
+}
+
+/* We're initializing a local variable which has a cleanup GUARD.  If there
+   are any temporaries used in the initializer INIT of this variable, we
+   need to wrap their cleanups with TRY_CATCH_EXPR (, GUARD) so that the
+   variable will be cleaned up properly if one of them throws.
+
+   Unfortunately, there's no way to express this properly in terms of
+   nesting, as the regions for the temporaries overlap the region for the
+   variable itself; if there are two temporaries, the variable needs to be
+   the first thing destroyed if either of them throws.  However, we only
+   want to run the variable's cleanup if it actually got constructed.  So
+   we need to guard the temporary cleanups with the variable's cleanup if
+   they are run on the normal path, but not if they are run on the
+   exceptional path.  We implement this by telling
+   honor_protect_cleanup_actions to strip the variable cleanup from the
+   exceptional path.  */
+
+static void
+wrap_temporary_cleanups (tree init, tree guard)
+{
+  cp_walk_tree_without_duplicates (&init, wrap_cleanups_r, (void *)guard);
+}
+
 /* Generate code to initialize DECL (a local variable).  */
 
 static void
@@ -5016,6 +5266,7 @@ initialize_local_var (tree decl, tree init)
 {
   tree type = TREE_TYPE (decl);
   tree cleanup;
+  int already_used;
 
   gcc_assert (TREE_CODE (decl) == VAR_DECL
              || TREE_CODE (decl) == RESULT_DECL);
@@ -5026,46 +5277,53 @@ initialize_local_var (tree decl, tree init)
       /* If we used it already as memory, it must stay in memory.  */
       DECL_INITIAL (decl) = NULL_TREE;
       TREE_ADDRESSABLE (decl) = TREE_USED (decl);
+      return;
     }
 
-  if (DECL_SIZE (decl) && type != error_mark_node)
-    {
-      int already_used;
+  if (type == error_mark_node)
+    return;
 
-      /* Compute and store the initial value.  */
-      already_used = TREE_USED (decl) || TREE_USED (type);
+  /* Compute and store the initial value.  */
+  already_used = TREE_USED (decl) || TREE_USED (type);
 
-      /* Perform the initialization.  */
-      if (init)
-       {
-         int saved_stmts_are_full_exprs_p;
+  /* Generate a cleanup, if necessary.  */
+  cleanup = cxx_maybe_build_cleanup (decl);
 
-         gcc_assert (building_stmt_tree ());
-         saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
-         current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-         finish_expr_stmt (init);
-         current_stmt_tree ()->stmts_are_full_exprs_p =
-           saved_stmts_are_full_exprs_p;
-       }
+  /* Perform the initialization.  */
+  if (init)
+    {
+      int saved_stmts_are_full_exprs_p;
 
-      /* Set this to 0 so we can tell whether an aggregate which was
-        initialized was ever used.  Don't do this if it has a
-        destructor, so we don't complain about the 'resource
-        allocation is initialization' idiom.  Now set
-        attribute((unused)) on types so decls of that type will be
-        marked used. (see TREE_USED, above.)  */
-      if (TYPE_NEEDS_CONSTRUCTING (type)
-         && ! already_used
-         && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
-         && DECL_NAME (decl))
-       TREE_USED (decl) = 0;
-      else if (already_used)
-       TREE_USED (decl) = 1;
-    }
+      /* If we're only initializing a single object, guard the destructors
+        of any temporaries used in its initializer with its destructor.
+        This isn't right for arrays because each element initialization is
+        a full-expression.  */
+      if (cleanup && TREE_CODE (type) != ARRAY_TYPE)
+       wrap_temporary_cleanups (init, cleanup);
 
-  /* Generate a cleanup, if necessary.  */
-  cleanup = cxx_maybe_build_cleanup (decl);
-  if (DECL_SIZE (decl) && cleanup)
+      gcc_assert (building_stmt_tree ());
+      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+      current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+      finish_expr_stmt (init);
+      current_stmt_tree ()->stmts_are_full_exprs_p =
+       saved_stmts_are_full_exprs_p;
+    }
+
+  /* Set this to 0 so we can tell whether an aggregate which was
+     initialized was ever used.  Don't do this if it has a
+     destructor, so we don't complain about the 'resource
+     allocation is initialization' idiom.  Now set
+     attribute((unused)) on types so decls of that type will be
+     marked used. (see TREE_USED, above.)  */
+  if (TYPE_NEEDS_CONSTRUCTING (type)
+      && ! already_used
+      && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+      && DECL_NAME (decl))
+    TREE_USED (decl) = 0;
+  else if (already_used)
+    TREE_USED (decl) = 1;
+
+  if (cleanup)
     finish_decl_cleanup (decl, cleanup);
 }
 
@@ -5080,7 +5338,7 @@ initialize_artificial_var (tree decl, tree init)
 {
   gcc_assert (DECL_ARTIFICIAL (decl));
   if (TREE_CODE (init) == TREE_LIST)
-    init = build_constructor_from_list (NULL_TREE, init);
+    init = build_constructor_from_list (TREE_TYPE (decl), init);
   gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
   DECL_INITIAL (decl) = init;
   DECL_INITIALIZED_P (decl) = 1;
@@ -5185,6 +5443,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 
       type_dependent_p = dependent_type_p (type);
 
+      if (check_for_bare_parameter_packs (init))
+       {
+         init = NULL_TREE;
+         DECL_INITIAL (decl) = NULL_TREE;
+       }
+
       if (init && init_const_expr_p)
        {
          DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
@@ -5212,7 +5476,21 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          goto finish_end;
        }
 
-      init = fold_non_dependent_expr (init);
+      if (TREE_CODE (init) == TREE_LIST)
+       {
+         /* If the parenthesized-initializer form was used (e.g.,
+            "int A<N>::i(X)"), then INIT will be a TREE_LIST of initializer
+            arguments.  (There is generally only one.)  We convert them
+            individually.  */
+         tree list = init;
+         for (; list; list = TREE_CHAIN (list))
+           {
+             tree elt = TREE_VALUE (list);
+             TREE_VALUE (list) = fold_non_dependent_expr (elt);
+           }
+       }
+      else
+       init = fold_non_dependent_expr (init);
       processing_template_decl = 0;
     }
 
@@ -5220,7 +5498,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
   if (TREE_CODE (decl) == TYPE_DECL)
     {
       if (type != error_mark_node
-         && IS_AGGR_TYPE (type) && DECL_NAME (decl))
+         && MAYBE_CLASS_TYPE_P (type) && DECL_NAME (decl))
        {
          if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
            warning (0, "shadowing previous type declaration of %q#D", decl);
@@ -5261,8 +5539,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
         require a guard variable, and since the mangled name of the
         guard variable will depend on the mangled name of this
         variable.  */
-      if (!processing_template_decl
-         && DECL_FUNCTION_SCOPE_P (decl)
+      if (DECL_FUNCTION_SCOPE_P (decl)
          && TREE_STATIC (decl)
          && !DECL_ARTIFICIAL (decl))
        push_local_name (decl);
@@ -5275,6 +5552,20 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
             is *not* defined.  */
          && (!DECL_EXTERNAL (decl) || init))
        {
+         if (TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+           {
+             tree jclass
+               = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+             /* Allow libjava/prims.cc define primitive classes.  */
+             if (init != NULL_TREE
+                 || jclass == NULL_TREE
+                 || TREE_CODE (jclass) != TYPE_DECL
+                 || !POINTER_TYPE_P (TREE_TYPE (jclass))
+                 || !same_type_ignoring_top_level_qualifiers_p
+                                       (type, TREE_TYPE (TREE_TYPE (jclass))))
+               error ("Java object %qD not allocated with %<new%>", decl);
+             init = NULL_TREE;
+           }
          if (init)
            {
              DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
@@ -5345,6 +5636,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       else if (TREE_CODE (type) == ARRAY_TYPE)
        layout_type (type);
     }
+  else if (TREE_CODE (decl) == FIELD_DECL
+          && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+    error ("non-static data member %qD has Java class type", decl);
 
   /* Add this declaration to the statement-tree.  This needs to happen
      after the call to check_initializer so that the DECL_EXPR for a
@@ -5364,6 +5658,24 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          maybe_commonize_var (decl);
        }
 
+      /* This needs to happen after the linkage is set. */
+      determine_visibility (decl);
+
+      if (var_definition_p && TREE_STATIC (decl))
+       {
+         /* If a TREE_READONLY variable needs initialization
+            at runtime, it is no longer readonly and we need to
+            avoid MEM_READONLY_P being set on RTL created for it.  */
+         if (init)
+           {
+             if (TREE_READONLY (decl))
+               TREE_READONLY (decl) = 0;
+             was_readonly = 0;
+           }
+         else if (was_readonly)
+           TREE_READONLY (decl) = 1;
+       }
+
       make_rtl_for_nonlocal_decl (decl, init, asmspec);
 
       /* Check for abstractness of the type. Notice that there is no
@@ -5375,9 +5687,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       else
        abstract_virtuals_error (decl, type);
 
-      /* This needs to happen after the linkage is set. */
-      determine_visibility (decl);
-
       if (TREE_CODE (decl) == FUNCTION_DECL
          || TREE_TYPE (decl) == error_mark_node)
        /* No initialization required.  */
@@ -5389,40 +5698,21 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          if (init)
            DECL_INITIAL (decl) = init;
        }
-      else
-       {
-         /* A variable definition.  */
-         if (DECL_FUNCTION_SCOPE_P (decl))
-           {
-             /* Initialize the local variable.  */
-             if (processing_template_decl)
-               DECL_INITIAL (decl) = init;
-             else if (!TREE_STATIC (decl))
-               initialize_local_var (decl, init);
-           }
+      /* A variable definition.  */
+      else if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
+       /* Initialize the local variable.  */
+       initialize_local_var (decl, init);
 
-         /* 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
-            calling expand_static_init more than once.  For variables
-            that are not static data members, we can call
-            expand_static_init only when we actually process the
-            initializer.  It is not legal to redeclare a static data
-            member, so this issue does not arise in that case.  */
-         if (var_definition_p && TREE_STATIC (decl))
-           {
-             /* If a TREE_READONLY variable needs initialization
-                at runtime, it is no longer readonly and we need to
-                avoid MEM_READONLY_P being set on RTL created for it.  */
-             if (init)
-               {
-                 if (TREE_READONLY (decl))
-                   TREE_READONLY (decl) = 0;
-                 was_readonly = 0;
-               }
-             expand_static_init (decl, init);
-           }
-       }
+      /* 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
+        calling expand_static_init more than once.  For variables
+        that are not static data members, we can call
+        expand_static_init only when we actually process the
+        initializer.  It is not legal to redeclare a static data
+        member, so this issue does not arise in that case.  */
+      else if (var_definition_p && TREE_STATIC (decl))
+       expand_static_init (decl, init);
     }
 
   /* If a CLEANUP_STMT was created to destroy a temporary bound to a
@@ -5736,7 +6026,7 @@ register_dtor_fn (tree decl)
          addr = build_address (decl);
          /* The declared type of the parameter to "__cxa_atexit" is
             "void *".  For plain "T*", we could just let the
-            machinery in build_function_call convert it -- but if the
+            machinery in cp_build_function_call convert it -- but if the
             type is "cv-qualified T *", then we need to convert it
             before passing it in, to avoid spurious errors.  */
          addr = build_nop (ptr_type_node, addr);
@@ -5748,7 +6038,8 @@ register_dtor_fn (tree decl)
           other value.  */
        addr = null_pointer_node;
       args = tree_cons (NULL_TREE,
-                       build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
+                       cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+                                        tf_warning_or_error),
                        NULL_TREE);
       if (targetm.cxx.use_aeabi_atexit ())
        {
@@ -5763,7 +6054,8 @@ register_dtor_fn (tree decl)
     }
   else
     args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
-  return build_function_call (get_atexit_node (), args);
+  return cp_build_function_call (get_atexit_node (), args, 
+                                tf_warning_or_error);
 }
 
 /* DECL is a VAR_DECL with static storage duration.  INIT, if present,
@@ -5921,6 +6213,9 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
   if (initial_value)
     {
+      unsigned HOST_WIDE_INT i;
+      tree value;
+
       /* An array of character type can be initialized from a
         brace-enclosed string constant.
 
@@ -5937,6 +6232,18 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
              && VEC_length (constructor_elt, v) == 1)
            initial_value = value;
        }
+
+      /* If any of the elements are parameter packs, we can't actually
+        complete this type now because the array size is dependent.  */
+      if (TREE_CODE (initial_value) == CONSTRUCTOR)
+       {
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (initial_value), 
+                                     i, value)
+           {
+             if (PACK_EXPANSION_P (value))
+               return 0;
+           }
+       }
     }
 
   failure = complete_array_type (ptype, initial_value, do_default);
@@ -6039,8 +6346,8 @@ check_class_member_definition_namespace (tree decl)
      The definition for a static data member shall appear in a
      namespace scope enclosing the member's class definition.  */
   if (!is_ancestor (current_namespace, DECL_CONTEXT (decl)))
-    pedwarn ("definition of %qD is not in namespace enclosing %qT",
-            decl, DECL_CONTEXT (decl));
+    permerror ("definition of %qD is not in namespace enclosing %qT",
+              decl, DECL_CONTEXT (decl));
 }
 
 /* Build a PARM_DECL for the "this" parameter.  TYPE is the
@@ -6273,16 +6580,16 @@ grokfndecl (tree ctype,
                /* Allow this; it's pretty common in C.  */;
              else
                {
-                 pedwarn ("non-local function %q#D uses anonymous type",
+                 permerror ("non-local function %q#D uses anonymous type",
                              decl);
                  if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
-                   pedwarn ("%q+#D does not refer to the unqualified "
-                            "type, so it is not used for linkage",
-                            TYPE_NAME (t));
+                   permerror ("%q+#D does not refer to the unqualified "
+                              "type, so it is not used for linkage",
+                              TYPE_NAME (t));
                }
            }
          else
-           pedwarn ("non-local function %q#D uses local type %qT", decl, t);
+           permerror ("non-local function %q#D uses local type %qT", decl, t);
        }
     }
 
@@ -6393,7 +6700,10 @@ grokfndecl (tree ctype,
               XXX Isn't this done in start_function, too?  */
            revert_static_member_fn (decl);
          if (DECL_ARTIFICIAL (old_decl))
-           error ("definition of implicitly-declared %qD", old_decl);
+           {
+             error ("definition of implicitly-declared %qD", old_decl);
+             return NULL_TREE;
+           }
 
          /* Since we've smashed OLD_DECL to its
             DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
@@ -6594,13 +6904,13 @@ build_ptrmemfunc_type (tree type)
     unqualified_variant
       = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
 
-  t = make_aggr_type (RECORD_TYPE);
+  t = make_class_type (RECORD_TYPE);
   xref_basetypes (t, NULL_TREE);
 
   /* Let the front end know this is a pointer to member function...  */
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
-  /* ... and not really an aggregate.  */
-  SET_IS_AGGR_TYPE (t, 0);
+  /* ... and not really a class type.  */
+  SET_CLASS_TYPE_P (t, 0);
 
   field = build_decl (FIELD_DECL, pfn_identifier, type);
   fields = field;
@@ -6759,12 +7069,7 @@ compute_array_index_type (tree name, tree size)
     {
       /* Check to see if the array bound overflowed.  Make that an
         error, no matter how generous we're being.  */
-      int old_flag_pedantic_errors = flag_pedantic_errors;
-      int old_pedantic = pedantic;
-      pedantic = flag_pedantic_errors = 1;
-      constant_expression_warning (size);
-      pedantic = old_pedantic;
-      flag_pedantic_errors = old_flag_pedantic_errors;
+      constant_expression_error (size);
 
       /* An array must have a positive number of elements.  */
       if (INT_CST_LT (size, integer_zero_node))
@@ -6827,7 +7132,8 @@ compute_array_index_type (tree name, tree size)
       processing_template_decl = 0;
       itype = cp_build_binary_op (MINUS_EXPR,
                                  cp_convert (ssizetype, size),
-                                 cp_convert (ssizetype, integer_one_node));
+                                 cp_convert (ssizetype, integer_one_node),
+                                 tf_warning_or_error);
       itype = fold (itype);
       processing_template_decl = saved_processing_template_decl;
 
@@ -7355,6 +7661,12 @@ grokdeclarator (const cp_declarator *declarator,
       return error_mark_node;
     }
 
+  if (declspecs->conflicting_specifiers_p)
+    {
+      error ("conflicting specifiers in declaration of %qs", name);
+      return error_mark_node;
+    }
+
   /* Extract the basic type from the decl-specifier-seq.  */
   type = declspecs->type;
   if (type == error_mark_node)
@@ -7371,6 +7683,10 @@ grokdeclarator (const cp_declarator *declarator,
     {
       typedef_decl = type;
       type = TREE_TYPE (typedef_decl);
+      if (TREE_DEPRECATED (type)
+         && DECL_ARTIFICIAL (typedef_decl)
+         && deprecated_state != DEPRECATED_SUPPRESS)
+       warn_deprecated_use (type);
     }
   /* No type at all: default to `int', and set DEFAULTED_INT
      because it was not a user-defined typedef.  */
@@ -7417,7 +7733,9 @@ grokdeclarator (const cp_declarator *declarator,
        /* We've already issued an error, don't complain more.  */;
       else if (in_system_header || flag_ms_extensions)
        /* Allow it, sigh.  */;
-      else if (pedantic || ! is_main)
+      else if (! is_main)
+       permerror ("ISO C++ forbids declaration of %qs with no type", name);
+      else if (pedantic)
        pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
       else
        warning (OPT_Wreturn_type,
@@ -7461,6 +7779,13 @@ grokdeclarator (const cp_declarator *declarator,
        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 if (type == char16_type_node || type == char32_type_node)
+       {
+         if (signed_p || unsigned_p)
+           error ("%<signed%> or %<unsigned%> invalid for %qs", name);
+         else if (short_p || long_p)
+           error ("%<short%> or %<long%> invalid for %qs", name);
+       }
       else
        {
          ok = 1;
@@ -7624,7 +7949,7 @@ grokdeclarator (const cp_declarator *declarator,
   if (virtualp
       && (current_class_name == NULL_TREE || decl_context != FIELD))
     {
-      error ("virtual outside class declaration");
+      error ("%<virtual%> outside class declaration");
       virtualp = 0;
     }
 
@@ -7645,15 +7970,10 @@ grokdeclarator (const cp_declarator *declarator,
       error ("multiple storage classes in declaration of %qs", name);
       thread_p = false;
     }
-  if (declspecs->conflicting_specifiers_p)
-    {
-      error ("conflicting specifiers in declaration of %qs", name);
-      storage_class = sc_none;
-    }
-  else if (decl_context != NORMAL
-          && ((storage_class != sc_none
-               && storage_class != sc_mutable)
-              || thread_p))
+  if (decl_context != NORMAL
+      && ((storage_class != sc_none
+          && storage_class != sc_mutable)
+         || thread_p))
     {
       if ((decl_context == PARM || decl_context == CATCHPARM)
          && (storage_class == sc_register
@@ -7685,19 +8005,6 @@ grokdeclarator (const cp_declarator *declarator,
            storage_class = sc_none;
        }
     }
-  else if (storage_class == sc_extern && initialized
-          && !funcdef_flag)
-    {
-      if (toplevel_bindings_p ())
-       {
-         /* It's common practice (and completely valid) to have a const
-            be initialized and declared extern.  */
-         if (!(type_quals & TYPE_QUAL_CONST))
-           warning (0, "%qs initialized and declared %<extern%>", name);
-       }
-      else
-       error ("%qs has both %<extern%> and initializer", name);
-    }
   else if (storage_class == sc_extern && funcdef_flag
           && ! toplevel_bindings_p ())
     error ("nested function %qs declared %<extern%>", name);
@@ -7716,7 +8023,11 @@ grokdeclarator (const cp_declarator *declarator,
     }
 
   if (storage_class && friendp)
-    error ("storage class specifiers invalid in friend function declarations");
+    {
+      error ("storage class specifiers invalid in friend function declarations");
+      storage_class = sc_none;
+      staticp = 0;
+    }
 
   if (!id_declarator)
     unqualified_id = NULL_TREE;
@@ -7789,7 +8100,7 @@ grokdeclarator (const cp_declarator *declarator,
            if (type_quals != TYPE_UNQUALIFIED)
              {
                if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
-                 warning (OPT_Wreturn_type,
+                 warning (OPT_Wignored_qualifiers,
                           "type qualifiers ignored on function return type");
                /* We now know that the TYPE_QUALS don't apply to the
                   decl, but to its return type.  */
@@ -7797,17 +8108,17 @@ grokdeclarator (const cp_declarator *declarator,
                set_no_warning = true;
              }
 
-           /* Warn about some types functions can't return.  */
+           /* Error about some types functions can't return.  */
 
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
                error ("%qs declared as function returning a function", name);
-               type = integer_type_node;
+               return error_mark_node;
              }
            if (TREE_CODE (type) == ARRAY_TYPE)
              {
                error ("%qs declared as function returning an array", name);
-               type = integer_type_node;
+               return error_mark_node;
              }
 
            /* Pick up type qualifiers which should be applied to `this'.  */
@@ -7866,7 +8177,7 @@ grokdeclarator (const cp_declarator *declarator,
                      explicitp = 2;
                    if (virtualp)
                      {
-                       pedwarn ("constructors cannot be declared virtual");
+                       permerror ("constructors cannot be declared virtual");
                        virtualp = 0;
                      }
                    if (decl_context == FIELD
@@ -7951,7 +8262,8 @@ grokdeclarator (const cp_declarator *declarator,
          type_quals = TYPE_UNQUALIFIED;
 
          if (declarator->kind == cdk_ptrmem
-             && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
+             && (TREE_CODE (type) == FUNCTION_TYPE
+                 || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
            {
              memfn_quals |= cp_type_quals (type);
              type = build_memfn_type (type,
@@ -8088,12 +8400,12 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (friendp)
            {
-             pedwarn ("member functions are implicitly friends of their class");
+             permerror ("member functions are implicitly friends of their class");
              friendp = 0;
            }
          else
-           pedwarn ("extra qualification %<%T::%> on member %qs",
-                    ctype, name);
+           permerror ("extra qualification %<%T::%> on member %qs",
+                      ctype, name);
        }
       else if (/* If the qualifying type is already complete, then we
                  can skip the following checks.  */
@@ -8277,9 +8589,9 @@ grokdeclarator (const cp_declarator *declarator,
            DECL_ABSTRACT (decl) = 1;
        }
       else if (constructor_name_p (unqualified_id, current_class_type))
-       pedwarn ("ISO C++ forbids nested type %qD with same name "
-                "as enclosing class",
-                unqualified_id);
+       permerror ("ISO C++ forbids nested type %qD with same name "
+                  "as enclosing class",
+                  unqualified_id);
 
       /* If the user declares "typedef struct {...} foo" then the
         struct will have an anonymous name.  Fill that name in now.
@@ -8290,8 +8602,6 @@ grokdeclarator (const cp_declarator *declarator,
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && TYPE_ANONYMOUS_P (type)
-         /* Don't do this if there are attributes.  */
-         && (!attrlist || !*attrlist)
          && cp_type_quals (type) == TYPE_UNQUALIFIED)
        {
          tree oldname = TYPE_NAME (type);
@@ -8404,15 +8714,15 @@ grokdeclarator (const cp_declarator *declarator,
            {
              /* Don't allow friend declaration without a class-key.  */
              if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
-               pedwarn ("template parameters cannot be friends");
+               permerror ("template parameters cannot be friends");
              else if (TREE_CODE (type) == TYPENAME_TYPE)
-               pedwarn ("friend declaration requires class-key, "
-                        "i.e. %<friend class %T::%D%>",
-                        TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
+               permerror ("friend declaration requires class-key, "
+                          "i.e. %<friend class %T::%D%>",
+                          TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
              else
-               pedwarn ("friend declaration requires class-key, "
-                        "i.e. %<friend %#T%>",
-                        type);
+               permerror ("friend declaration requires class-key, "
+                          "i.e. %<friend %#T%>",
+                          type);
            }
 
          /* Only try to do this stuff if we didn't already give up.  */
@@ -8588,6 +8898,13 @@ grokdeclarator (const cp_declarator *declarator,
                    return error_mark_node;
                  }
              }
+           else if (sfk == sfk_constructor && friendp)
+             {
+               error ("expected qualified name in friend declaration "
+                      "for constructor %qD",
+                      id_declarator->u.id.unqualified_name);
+               return error_mark_node;
+             }
 
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
            function_context = (ctype != NULL_TREE) ?
@@ -8622,17 +8939,11 @@ grokdeclarator (const cp_declarator *declarator,
              DECL_NONCONVERTING_P (decl) = 1;
            else if (DECL_CONSTRUCTOR_P (decl))
              {
-               /* The constructor can be called with exactly one
-                  parameter if there is at least one parameter, and
-                  any subsequent parameters have default arguments.
+               /* A constructor with no parms is not a conversion.
                   Ignore any compiler-added parms.  */
                tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
 
-               if (arg_types == void_list_node
-                   || (arg_types
-                       && TREE_CHAIN (arg_types)
-                       && TREE_CHAIN (arg_types) != void_list_node
-                       && !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+               if (arg_types == void_list_node)
                  DECL_NONCONVERTING_P (decl) = 1;
              }
          }
@@ -8690,7 +9001,7 @@ grokdeclarator (const cp_declarator *declarator,
          {
            /* Friends are treated specially.  */
            if (ctype == current_class_type)
-             ;  /* We already issued a pedwarn.  */
+             ;  /* We already issued a permerror.  */
            else if (decl && DECL_NAME (decl))
              {
                if (template_class_depth (current_class_type) == 0)
@@ -8731,9 +9042,9 @@ 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.  */
-                   pedwarn ("ISO C++ forbids initialization of member %qD",
-                            unqualified_id);
-                   pedwarn ("making %qD static", unqualified_id);
+                   permerror ("ISO C++ forbids initialization of member %qD",
+                              unqualified_id);
+                   permerror ("making %qD static", unqualified_id);
                    staticp = 1;
                  }
 
@@ -8855,8 +9166,8 @@ grokdeclarator (const cp_declarator *declarator,
               declaring main to be static.  */
            if (TREE_CODE (type) == METHOD_TYPE)
              {
-               pedwarn ("cannot declare member function %qD to have "
-                        "static linkage", decl);
+               permerror ("cannot declare member function %qD to have "
+                          "static linkage", decl);
                invalid_static = 1;
              }
            else if (current_function_decl)
@@ -8892,8 +9203,8 @@ grokdeclarator (const cp_declarator *declarator,
            DECL_CONTEXT (decl) = ctype;
            if (staticp == 1)
              {
-               pedwarn ("%<static%> may not be used when defining "
-                        "(as opposed to declaring) a static data member");
+               permerror ("%<static%> may not be used when defining "
+                          "(as opposed to declaring) a static data member");
                staticp = 0;
                storage_class = sc_none;
              }
@@ -8912,6 +9223,19 @@ grokdeclarator (const cp_declarator *declarator,
          }
       }
 
+    if (storage_class == sc_extern && initialized && !funcdef_flag)
+      {
+       if (toplevel_bindings_p ())
+         {
+           /* It's common practice (and completely valid) to have a const
+              be initialized and declared extern.  */
+           if (!(type_quals & TYPE_QUAL_CONST))
+             warning (0, "%qs initialized and declared %<extern%>", name);
+         }
+       else
+         error ("%qs has both %<extern%> and initializer", name);
+      }
+
     /* Record `register' declaration for warnings on &
        and in case doing stupid register allocation.  */
 
@@ -8922,9 +9246,9 @@ grokdeclarator (const cp_declarator *declarator,
     else if (storage_class == sc_static)
       DECL_THIS_STATIC (decl) = 1;
 
-    /* Record constancy and volatility.  There's no need to do this
-       when processing a template; we'll do this for the instantiated
-       declaration based on the type of DECL.  */
+    /* Record constancy and volatility on the DECL itself .  There's
+       no need to do this when processing a template; we'll do this
+       for the instantiated declaration based on the type of DECL.  */
     if (!processing_template_decl)
       cp_apply_type_quals_to_decl (type_quals, decl);
 
@@ -8976,18 +9300,6 @@ local_variable_p (const_tree t)
   return 0;
 }
 
-/* Returns nonzero if T is an automatic local variable or a label.
-   (These are the declarations that need to be remapped when the code
-   containing them is duplicated.)  */
-
-int
-nonstatic_local_decl_p (const_tree t)
-{
-  return ((local_variable_p (t) && !TREE_STATIC (t))
-         || TREE_CODE (t) == LABEL_DECL
-         || TREE_CODE (t) == RESULT_DECL);
-}
-
 /* Like local_variable_p, but suitable for use as a tree-walking
    function.  */
 
@@ -9061,8 +9373,7 @@ check_default_argument (tree decl, tree arg)
 
      The keyword `this' shall not be used in a default argument of a
      member function.  */
-  var = walk_tree_without_duplicates (&arg, local_variable_p_walkfn,
-                                     NULL);
+  var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
   if (var)
     {
       error ("default argument %qE uses local variable %qD", arg, var);
@@ -9128,6 +9439,16 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
          TREE_TYPE (decl) = error_mark_node;
        }
 
+      if (type != error_mark_node
+         && TYPE_FOR_JAVA (type)
+         && MAYBE_CLASS_TYPE_P (type))
+       {
+         error ("parameter %qD has Java class type", decl);
+         type = error_mark_node;
+         TREE_TYPE (decl) = error_mark_node;
+         init = NULL_TREE;
+       }
+
       if (type != error_mark_node)
        {
          /* Top-level qualifiers on the parameters are
@@ -9217,7 +9538,7 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
    operator.  */
 
 int
-copy_fn_p (tree d)
+copy_fn_p (const_tree d)
 {
   tree args;
   tree arg_type;
@@ -9273,7 +9594,7 @@ copy_fn_p (tree d)
    operator, false otherwise.  */
 
 bool
-move_fn_p (tree d)
+move_fn_p (const_tree d)
 {
   tree args;
   tree arg_type;
@@ -9319,7 +9640,8 @@ move_fn_p (tree d)
 
 /* Remember any special properties of member function DECL.  */
 
-void grok_special_member_properties (tree decl)
+void
+grok_special_member_properties (tree decl)
 {
   tree class_type;
 
@@ -9331,7 +9653,8 @@ void grok_special_member_properties (tree decl)
     {
       int ctor = copy_fn_p (decl);
 
-      TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+      if (!DECL_ARTIFICIAL (decl))
+       TYPE_HAS_USER_CONSTRUCTOR (class_type) = 1;
 
       if (ctor > 0)
        {
@@ -9348,6 +9671,8 @@ void grok_special_member_properties (tree decl)
        }
       else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
        TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
+      else if (is_list_ctor (decl))
+       TYPE_HAS_LIST_CTOR (class_type) = 1;
     }
   else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
     {
@@ -9372,7 +9697,7 @@ void grok_special_member_properties (tree decl)
    if the class has a constructor of the form X(X).  */
 
 int
-grok_ctor_properties (tree ctype, tree decl)
+grok_ctor_properties (const_tree ctype, const_tree decl)
 {
   int ctor_parm = copy_fn_p (decl);
 
@@ -9475,7 +9800,7 @@ grok_op_properties (tree decl, bool complain)
        gcc_unreachable ();
       }
     while (0);
-  gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
+  gcc_assert (operator_code != MAX_TREE_CODES);
   SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
 
   if (class_type)
@@ -9527,7 +9852,10 @@ grok_op_properties (tree decl, bool complain)
     }
 
   if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
-    TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+    {
+      TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+      DECL_IS_OPERATOR_NEW (decl) = 1;
+    }
   else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
     TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
   else
@@ -9563,10 +9891,11 @@ grok_op_properties (tree decl, bool complain)
                  if (arg == error_mark_node)
                    return false;
 
-                 /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
+                 /* MAYBE_CLASS_TYPE_P, rather than CLASS_TYPE_P, is used
                     because these checks are performed even on
                     template functions.  */
-                 if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
+                 if (MAYBE_CLASS_TYPE_P (arg)
+                     || TREE_CODE (arg) == ENUMERAL_TYPE)
                    break;
                }
 
@@ -9607,7 +9936,7 @@ grok_op_properties (tree decl, bool complain)
              if (t == class_type)
                what = "the same type";
              /* Don't force t to be complete here.  */
-             else if (IS_AGGR_TYPE (t)
+             else if (MAYBE_CLASS_TYPE_P (t)
                       && COMPLETE_TYPE_P (t)
                       && DERIVED_FROM_P (t, class_type))
                what = "a base class";
@@ -10081,14 +10410,14 @@ xref_tag (enum tag_types tag_code, tree name,
        }
       else
        {
-         t = make_aggr_type (code);
+         t = make_class_type (code);
          TYPE_CONTEXT (t) = context;
          t = pushtag (name, t, scope);
        }
     }
   else
     {
-      if (template_header_p && IS_AGGR_TYPE (t))
+      if (template_header_p && MAYBE_CLASS_TYPE_P (t))
         {
          if (!redeclare_class_template (t, current_template_parms))
             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
@@ -10551,7 +10880,8 @@ finish_enum (tree enumtype)
       saved_location = input_location;
       input_location = DECL_SOURCE_LOCATION (decl);
       value = perform_implicit_conversion (underlying_type,
-                                          DECL_INITIAL (decl));
+                                          DECL_INITIAL (decl),
+                                          tf_warning_or_error);
       input_location = saved_location;
 
       /* Do not clobber shared ints.  */
@@ -10684,7 +11014,6 @@ build_enumerator (tree name, tree value, tree enumtype)
 
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
   TREE_CONSTANT (decl) = 1;
-  TREE_INVARIANT (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
 
@@ -10714,11 +11043,15 @@ check_function_type (tree decl, tree current_function_parms)
 
   if (dependent_type_p (return_type))
     return;
-  if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+  if (!COMPLETE_OR_VOID_TYPE_P (return_type)
+      || (TYPE_FOR_JAVA (return_type) && MAYBE_CLASS_TYPE_P (return_type)))
     {
       tree args = TYPE_ARG_TYPES (fntype);
 
-      error ("return type %q#T is incomplete", return_type);
+      if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+       error ("return type %q#T is incomplete", return_type);
+      else
+       error ("return type has Java class type %q#T", return_type);
 
       /* Make it return void instead.  */
       if (TREE_CODE (fntype) == METHOD_TYPE)
@@ -10799,6 +11132,15 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       && lookup_attribute ("noinline", attrs))
     warning (0, "inline function %q+D given attribute noinline", decl1);
 
+  /* Handle gnu_inline attribute.  */
+  if (GNU_INLINE_P (decl1))
+    {
+      DECL_EXTERNAL (decl1) = 1;
+      DECL_NOT_REALLY_EXTERN (decl1) = 0;
+      DECL_INTERFACE_KNOWN (decl1) = 1;
+      DECL_DISREGARD_INLINE_LIMITS (decl1) = 1;
+    }
+
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
     /* This is a constructor, we must ensure that any default args
        introduced by this definition are propagated to the clones
@@ -10971,14 +11313,19 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
      CFUN set up, and our per-function variables initialized.
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
-  allocate_struct_function (decl1);
+  allocate_struct_function (decl1, processing_template_decl);
+
+  /* Initialize the language data structures.  Whenever we start
+     a new function, we destroy temporaries in the usual way.  */
+  cfun->language = GGC_CNEW (struct language_function);
+  current_stmt_tree ()->stmts_are_full_exprs_p = 1;
   current_binding_level = bl;
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
-  cfun->x_dont_save_pending_sizes_p = 1;
+  cfun->dont_save_pending_sizes_p = 1;
 
   /* Start the statement-tree, start the tree now.  */
   DECL_SAVED_TREE (decl1) = push_stmt_list ();
@@ -11000,7 +11347,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
 
       cp_function_chain->x_current_class_ref
-       = build_indirect_ref (t, NULL);
+       = cp_build_indirect_ref (t, NULL, tf_warning_or_error);
       cp_function_chain->x_current_class_ptr = t;
 
       /* Constructors and destructors need to know whether they're "in
@@ -11084,8 +11431,9 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   else
     {
       /* This is a definition, not a reference.
-        So clear DECL_EXTERNAL.  */
-      DECL_EXTERNAL (decl1) = 0;
+        So clear DECL_EXTERNAL, unless this is a GNU extern inline.  */
+      if (!GNU_INLINE_P (decl1))
+       DECL_EXTERNAL (decl1) = 0;
 
       if ((DECL_DECLARED_INLINE_P (decl1)
           || DECL_TEMPLATE_INSTANTIATION (decl1))
@@ -11285,7 +11633,8 @@ finish_constructor_body (void)
   tree val;
   tree exprstmt;
 
-  if (targetm.cxx.cdtor_returns_this ())
+  if (targetm.cxx.cdtor_returns_this ()
+      && (! TYPE_FOR_JAVA (current_class_type)))
     {
       /* Any return from a constructor will end up here.  */
       add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
@@ -11440,7 +11789,7 @@ finish_function_body (tree compstmt)
    of curly braces, skipping the artificial block created for constructor
    initializers.  */
 
-static tree
+tree
 outer_curly_brace_block (tree fndecl)
 {
   tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
@@ -11513,11 +11862,10 @@ finish_function (int flags)
          /* Hack.  We don't want the middle-end to warn that this
             return is unreachable, so put the statement on the
             special line 0.  */
-#ifdef USE_MAPPED_LOCATION
-         SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
-#else
-         annotate_with_file_line (stmt, input_filename, 0);
-#endif
+         {
+           location_t linezero = linemap_line_start (line_table, 0, 1);
+           SET_EXPR_LOCATION (stmt, linezero);
+         }
        }
 
       if (use_eh_spec_block (current_function_decl))
@@ -11648,7 +11996,7 @@ finish_function (int flags)
 
   /* We're leaving the context of this function, so zap cfun.  It's still in
      DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation.  */
-  cfun = NULL;
+  set_cfun (NULL);
   current_function_decl = NULL;
 
   /* If this is an in-class inline definition, we may have to pop the
@@ -11917,8 +12265,9 @@ cxx_maybe_build_cleanup (tree decl)
       fn = lookup_name (id);
       arg = build_address (decl);
       mark_used (decl);
-      cleanup = build_function_call (fn, build_tree_list (NULL_TREE,
-                                                         arg));
+      cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
+                                                            arg),
+                                       tf_warning_or_error);
     }
   /* Handle ordinary C++ destructors.  */
   type = TREE_TYPE (decl);
@@ -11933,10 +12282,7 @@ cxx_maybe_build_cleanup (tree decl)
       if (TREE_CODE (type) == ARRAY_TYPE)
        addr = decl;
       else
-       {
-         cxx_mark_addressable (decl);
-         addr = build_unary_op (ADDR_EXPR, decl, 0);
-       }
+       addr = build_address (decl);
 
       /* Optimize for space over speed here.  */
       if (!has_vbases || flag_expensive_optimizations)
@@ -11985,47 +12331,6 @@ revert_static_member_fn (tree decl)
   DECL_STATIC_FUNCTION_P (decl) = 1;
 }
 
-/* Initialize the variables used during compilation of a C++
-   function.  */
-
-void
-cxx_push_function_context (struct function * f)
-{
-  struct language_function *p = GGC_CNEW (struct language_function);
-  f->language = p;
-
-  /* Whenever we start a new function, we destroy temporaries in the
-     usual way.  */
-  current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-
-  if (f->decl)
-    {
-      tree fn = f->decl;
-
-      if (DECL_SAVED_FUNCTION_DATA (fn))
-       {
-         /* If we already parsed this function, and we're just expanding it
-            now, restore saved state.  */
-         *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
-
-         /* We don't need the saved data anymore.  Unless this is an inline
-            function; we need the named return value info for
-            declare_return_variable.  */
-         if (! DECL_INLINE (fn))
-           DECL_SAVED_FUNCTION_DATA (fn) = NULL;
-       }
-    }
-}
-
-/* Free the language-specific parts of F, now that we've finished
-   compiling the function.  */
-
-void
-cxx_pop_function_context (struct function * f)
-{
-  f->language = 0;
-}
-
 /* Return which tree structure is used by T, or TS_CP_GENERIC if T is
    one of the language-independent trees.  */
 
@@ -12038,7 +12343,6 @@ cp_tree_node_structure (union lang_tree_node * t)
     case IDENTIFIER_NODE:      return TS_CP_IDENTIFIER;
     case OVERLOAD:             return TS_CP_OVERLOAD;
     case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
-    case TINST_LEVEL:          return TS_CP_TINST_LEVEL;
     case PTRMEM_CST:           return TS_CP_PTRMEM;
     case BASELINK:             return TS_CP_BASELINK;
     case STATIC_ASSERT:                return TS_CP_STATIC_ASSERT;