OSDN Git Service

/cp
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index a2a650d..b053160 100644 (file)
@@ -1,13 +1,14 @@
 /* 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  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.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* Process declarations and symbol lookup for C++ front end.
@@ -48,9 +48,11 @@ Boston, MA 02110-1301, USA.  */
 #include "c-common.h"
 #include "c-pragma.h"
 #include "diagnostic.h"
+#include "intl.h"
 #include "debug.h"
 #include "timevar.h"
 #include "tree-flow.h"
+#include "pointer-set.h"
 
 static tree grokparms (cp_parameter_declarator *, tree *);
 static const char *redeclaration_error_message (tree, tree);
@@ -64,10 +66,7 @@ static tree grok_reference_init (tree, tree, tree, tree *);
 static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
                         int, int, tree);
 static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (const char *, tree, tree,
-                               enum built_in_function code,
-                               enum built_in_class cl, const char *,
-                               tree);
+static tree builtin_function_1 (tree, tree);
 static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static void bad_specifiers (tree, const char *, int, int, int, int,
@@ -316,7 +315,7 @@ current_tmpl_spec_kind (int n_class_scopes)
 
         template <class T> void S<T>::f(int);
 
-       The `class T' maches the `S<T>', leaving no template headers
+       The `class T' matches the `S<T>', leaving no template headers
        corresponding to the `f'.  */
     return tsk_none;
   else if (n_template_parm_scopes > n_class_scopes + 1)
@@ -358,17 +357,12 @@ 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));
        }
-      else if (!TREE_USED (label))
-       warning (OPT_Wunused_label, "label %q+D defined but not used", label);
+      else 
+       warn_for_unused_label (label);
     }
 
   SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
@@ -589,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
@@ -715,7 +709,7 @@ poplevel (int keep, int reverse, int functionbody)
 
   /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
      list if a `using' declaration put them there.  The debugging
-     back-ends won't understand OVERLOAD, so we remove them here.
+     back ends won't understand OVERLOAD, so we remove them here.
      Because the BLOCK_VARS are (temporarily) shared with
      CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
      popped all the bindings.  */
@@ -758,7 +752,12 @@ poplevel (int keep, int reverse, int functionbody)
 
   leave_scope ();
   if (functionbody)
-    DECL_INITIAL (current_function_decl) = block;
+    {
+      /* The current function is being defined, so its DECL_INITIAL
+        should be error_mark_node.  */
+      gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node);
+      DECL_INITIAL (current_function_decl) = block;
+    }
   else if (block)
     current_binding_level->blocks
       = chainon (current_binding_level->blocks, block);
@@ -801,12 +800,12 @@ insert_block (tree block)
    itself, calling F for each.  The DATA is passed to F as well.  */
 
 static int
-walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
+walk_namespaces_r (tree name_space, walk_namespaces_fn f, void* data)
 {
   int result = 0;
-  tree current = NAMESPACE_LEVEL (namespace)->namespaces;
+  tree current = NAMESPACE_LEVEL (name_space)->namespaces;
 
-  result |= (*f) (namespace, data);
+  result |= (*f) (name_space, data);
 
   for (; current; current = TREE_CHAIN (current))
     result |= walk_namespaces_r (current, f, data);
@@ -828,9 +827,9 @@ walk_namespaces (walk_namespaces_fn f, void* data)
    wrapup_global_declarations for this NAMESPACE.  */
 
 int
-wrapup_globals_for_namespace (tree namespace, void* data)
+wrapup_globals_for_namespace (tree name_space, void* data)
 {
-  struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+  struct cp_binding_level *level = NAMESPACE_LEVEL (name_space);
   VEC(tree,gc) *statics = level->static_decls;
   tree *vec = VEC_address (tree, statics);
   int len = VEC_length (tree, statics);
@@ -1056,13 +1055,13 @@ 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
    function templates.  If their exception specifications do not
-   match, issue an a diagnostic.  */
+   match, issue a diagnostic.  */
 
 static void
 check_redeclaration_exception_specification (tree new_decl,
@@ -1095,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.
@@ -1273,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;
@@ -1293,30 +1307,36 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
     }
   else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
-      if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
-          && TREE_CODE (newdecl) != TYPE_DECL
-          && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
-                && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
-         || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
-             && TREE_CODE (olddecl) != TYPE_DECL
-             && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
-                   && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
-                       == TYPE_DECL))))
-       {
-         /* We do nothing special here, because C++ does such nasty
-            things with TYPE_DECLs.  Instead, just let the TYPE_DECL
-            get shadowed, and know that if we need to find a TYPE_DECL
-            for a given name, we can look in the IDENTIFIER_TYPE_VALUE
-            slot of the identifier.  */
-         return NULL_TREE;
+      /* C++ Standard, 3.3, clause 4:
+        "[Note: a namespace name or a class template name must be unique
+        in its declarative region (7.3.2, clause 14). ]"  */
+      if (TREE_CODE (olddecl) != NAMESPACE_DECL
+         && TREE_CODE (newdecl) != NAMESPACE_DECL
+         && (TREE_CODE (olddecl) != TEMPLATE_DECL
+             || TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) != TYPE_DECL)
+         && (TREE_CODE (newdecl) != TEMPLATE_DECL
+             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != TYPE_DECL))
+       {
+         if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
+              && TREE_CODE (newdecl) != TYPE_DECL)
+             || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
+                 && TREE_CODE (olddecl) != TYPE_DECL))
+           {
+             /* We do nothing special here, because C++ does such nasty
+                things with TYPE_DECLs.  Instead, just let the TYPE_DECL
+                get shadowed, and know that if we need to find a TYPE_DECL
+                for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+                slot of the identifier.  */
+             return NULL_TREE;
+           }
+           
+           if ((TREE_CODE (newdecl) == FUNCTION_DECL
+                && DECL_FUNCTION_TEMPLATE_P (olddecl))
+               || (TREE_CODE (olddecl) == FUNCTION_DECL
+                   && DECL_FUNCTION_TEMPLATE_P (newdecl)))
+             return NULL_TREE;
        }
 
-      if ((TREE_CODE (newdecl) == FUNCTION_DECL
-          && DECL_FUNCTION_TEMPLATE_P (olddecl))
-         || (TREE_CODE (olddecl) == FUNCTION_DECL
-             && DECL_FUNCTION_TEMPLATE_P (newdecl)))
-       return NULL_TREE;
-
       error ("%q#D redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
        olddecl = TREE_VALUE (olddecl);
@@ -1519,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
                  {
@@ -1531,14 +1551,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
                                 olddecl);
                  }
              }
-
-         if (DECL_DECLARED_INLINE_P (newdecl)
-             && ! DECL_DECLARED_INLINE_P (olddecl)
-             && TREE_ADDRESSABLE (olddecl) && warn_inline)
-           {
-             warning (0, "%q#D was used before it was declared inline", newdecl);
-             warning (0, "%Jprevious non-inline declaration here", olddecl);
-           }
        }
     }
 
@@ -1573,6 +1585,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
       DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
       DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
+      DECL_INVALID_OVERRIDER_P (newdecl) |= DECL_INVALID_OVERRIDER_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
       if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
        SET_OVERLOADED_OPERATOR_CODE
@@ -1592,6 +1605,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
          warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
        }
+
+      if (DECL_DELETED_FN (newdecl))
+       {
+         error ("deleted definition of %qD", newdecl);
+         error ("after previous declaration %q+D", olddecl);
+       }
     }
 
   /* Deal with C++: must preserve virtual function table size.  */
@@ -1624,23 +1643,48 @@ 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_UNINLINABLE (old_result) = 1;
+             else
+               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_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.  */
-      if (DECL_INITIAL (old_result) == NULL_TREE
-         && DECL_INITIAL (new_result) != NULL_TREE)
+        line information on the declaration, and also make
+        the old declaration the same definition.  */
+      if (DECL_INITIAL (new_result) != NULL_TREE)
        {
          DECL_SOURCE_LOCATION (olddecl)
            = DECL_SOURCE_LOCATION (old_result)
            = DECL_SOURCE_LOCATION (newdecl);
+         DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
          if (DECL_FUNCTION_TEMPLATE_P (newdecl))
            DECL_ARGUMENTS (old_result)
              = DECL_ARGUMENTS (new_result);
@@ -1748,10 +1792,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);
        }
@@ -1793,9 +1840,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);
 
@@ -1869,6 +1936,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))
+       {
+         /* Never inline re-defined extern inline functions.
+            FIXME: this could be better handled by keeping both
+            function as separate declarations.  */
+         DECL_UNINLINABLE (newdecl) = 1;
+       }
       else
        {
          if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
@@ -1876,14 +1950,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
          DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
 
-         /* If either decl says `inline', this fn is inline, unless
-            its definition was passed already.  */
-         if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
-           DECL_INLINE (olddecl) = 1;
-         DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
          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.  */
@@ -1968,6 +2041,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       ggc_free (DECL_LANG_SPECIFIC (olddecl));
     }
 
+   /* Merge the USED information.  */
+   if (TREE_USED (olddecl))
+     TREE_USED (newdecl) = 1;
+   else if (TREE_USED (newdecl))
+     TREE_USED (olddecl) = 1;
+
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
       int function_size;
@@ -2111,9 +2190,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)
@@ -2139,9 +2234,37 @@ 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
+           default template-argument, that declaration shall be a
+           definition and shall be the only declaration of the
+           function template in the translation unit.  */
+      if ((cxx_dialect != cxx98) 
+          && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
+          && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl), 
+                                       /*is_primary=*/1, /*is_partial=*/0,
+                                       /*is_friend_decl=*/2))
+        return "redeclaration of friend %q#D may not have default template arguments";
+
       return NULL;
     }
   else if (TREE_CODE (newdecl) == VAR_DECL
@@ -2161,8 +2284,24 @@ redeclaration_error_message (tree newdecl, tree olddecl)
     }
   else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
     {
-      /* Objects declared at top level:  */
-      /* If at least one is a reference, it's ok.  */
+      /* The objects have been declared at namespace scope.  If either
+        is a member of an anonymous union, then this is an invalid
+        redeclaration.  For example:
+
+          int i;
+          union { int i; };
+
+          is invalid.  */
+      if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl))
+         || (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl)))
+       return "redeclaration of %q#D";
+      /* If at least one declaration is a reference, there is no
+        conflict.  For example:
+
+          int i = 3;
+          extern int i;
+
+        is valid.  */
       if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
        return NULL;
       /* Reject two definitions.  */
@@ -2309,11 +2448,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
@@ -2355,7 +2494,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)
@@ -2451,8 +2590,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;
     }
 
@@ -2470,7 +2609,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)
@@ -2491,8 +2630,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");
@@ -2544,7 +2683,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)
     {
@@ -2674,7 +2813,7 @@ static hashval_t
 typename_hash (const void* k)
 {
   hashval_t hash;
-  tree t = (tree) k;
+  const_tree const t = (const_tree) k;
 
   hash = (htab_hash_pointer (TYPE_CONTEXT (t))
          ^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
@@ -2690,16 +2829,14 @@ typedef struct typename_info {
   bool class_p;
 } typename_info;
 
-/* Compare two TYPENAME_TYPEs.  K1 and K2 are really of type `tree'.  */
+/* Compare two TYPENAME_TYPEs.  K1 is really of type `tree', K2 is
+   really of type `typename_info*'  */
 
 static int
 typename_compare (const void * k1, const void * k2)
 {
-  tree t1;
-  const typename_info *t2;
-
-  t1 = (tree) k1;
-  t2 = (const typename_info *) k2;
+  const_tree const t1 = (const_tree) k1;
+  const typename_info *const t2 = (const typename_info *) k2;
 
   return (DECL_NAME (TYPE_NAME (t1)) == t2->name
          && TYPE_CONTEXT (t1) == t2->scope
@@ -2746,7 +2883,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;
@@ -2761,6 +2898,11 @@ build_typename_type (tree context, tree name, tree fullname,
 
       /* Store it in the hash table.  */
       *e = t;
+
+      /* TYPENAME_TYPEs must always be compared structurally, because
+        they may or may not resolve down to another type depending on
+        the currently open classes. */
+      SET_TYPE_STRUCTURAL_EQUALITY (t);
     }
 
   return t;
@@ -2809,6 +2951,11 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
       name = TREE_OPERAND (name, 0);
       if (TREE_CODE (name) == TEMPLATE_DECL)
        name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
+      else if (TREE_CODE (name) == OVERLOAD)
+       {
+         error ("%qD is not a type", name);
+         return error_mark_node;
+       }
     }
   if (TREE_CODE (name) == TEMPLATE_DECL)
     {
@@ -2824,7 +2971,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);
@@ -2860,7 +3007,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
     }
   
   if (complain & tf_error)
-    perform_or_defer_access_check (TYPE_BINFO (context), t);
+    perform_or_defer_access_check (TYPE_BINFO (context), t, t);
 
   if (want_template)
     return lookup_template_class (t, TREE_OPERAND (fullname, 1),
@@ -2901,7 +3048,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))
@@ -2923,15 +3070,16 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
        }
 
       if (complain & tf_error)
-       perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
+       perform_or_defer_access_check (TYPE_BINFO (context), tmpl, tmpl);
 
       return tmpl;
     }
 
   /* 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);
 
   /* Build the corresponding TEMPLATE_DECL.  */
   d = build_decl (TEMPLATE_DECL, name, t);
@@ -3026,7 +3174,7 @@ record_builtin_java_type (const char* name, int size)
   return type;
 }
 
-/* Push a type into the namespace so that the back-ends ignore it.  */
+/* Push a type into the namespace so that the back ends ignore it.  */
 
 static void
 record_unknown_type (tree type, const char* name)
@@ -3125,22 +3273,8 @@ cxx_init_decl_processing (void)
 
   current_lang_name = NULL_TREE;
 
-  /* Adjust various flags based on command-line settings.  */
-  if (!flag_permissive)
-    flag_pedantic_errors = 1;
-  if (!flag_no_inline)
-    {
-      flag_inline_trees = 1;
-      flag_no_inline = 1;
-    }
-  if (flag_inline_functions)
-    flag_inline_trees = 2;
-
-  /* Force minimum function alignment if using the least significant
-     bit of function pointers to store the virtual bit.  */
-  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
-      && force_align_functions_log < 1)
-    force_align_functions_log = 1;
+  if (flag_visibility_ms_compat)
+    default_visibility = VISIBILITY_HIDDEN;
 
   /* Initially, C.  */
   current_lang_name = lang_name_c;
@@ -3200,6 +3334,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.) */
@@ -3240,7 +3377,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);
@@ -3332,7 +3469,7 @@ cp_make_fname_decl (tree id, int type_dep)
   tree decl = build_decl (VAR_DECL, id, type);
 
   if (name)
-    free ((char *) name);
+    free (CONST_CAST (char *, name));
 
   /* As we're using pushdecl_with_scope, we must set the context.  */
   DECL_CONTEXT (decl) = current_function_decl;
@@ -3359,90 +3496,66 @@ cp_make_fname_decl (tree id, int type_dep)
   return decl;
 }
 
-/* Make a definition for a builtin function named NAME in the current
-   namespace, whose data type is TYPE and whose context is CONTEXT.
-   TYPE should be a function type with argument types.
+static tree
+builtin_function_1 (tree decl, tree context)
+{
+  tree          id = DECL_NAME (decl);
+  const char *name = IDENTIFIER_POINTER (id);
 
-   CLASS and CODE tell later passes how to compile calls to this function.
-   See tree.h for possible values.
+  retrofit_lang_decl (decl);
 
-   If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
-   the name to be called if we can't opencode the function.
-   If ATTRS is nonzero, use that for the function's attribute
-   list.  */
+  /* All nesting of C++ functions is lexical; there is never a "static
+     chain" in the sense of GNU C nested functions.  */
+  DECL_NO_STATIC_CHAIN (decl) = 1;
+
+  DECL_ARTIFICIAL (decl) = 1;
+  SET_OVERLOADED_OPERATOR_CODE (decl, ERROR_MARK);
+  SET_DECL_LANGUAGE (decl, lang_c);
+  /* Runtime library routines are, by definition, available in an
+     external shared object.  */
+  DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+  DECL_VISIBILITY_SPECIFIED (decl) = 1;
 
-static tree
-builtin_function_1 (const char* name,
-                   tree type,
-                   tree context,
-                   enum built_in_function code,
-                   enum built_in_class class,
-                   const char* libname,
-                   tree attrs)
-{
-  tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
-  DECL_BUILT_IN_CLASS (decl) = class;
-  DECL_FUNCTION_CODE (decl) = code;
   DECL_CONTEXT (decl) = context;
 
   pushdecl (decl);
 
-  /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
-     we cannot change DECL_ASSEMBLER_NAME until we have installed this
-     function in the namespace.  */
-  if (libname)
-    SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
-
   /* A function in the user's namespace should have an explicit
      declaration before it is used.  Mark the built-in function as
      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);
 
-  /* Possibly apply some default attributes to this built-in function.  */
-  if (attrs)
-    decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
-  else
-    decl_attributes (&decl, NULL_TREE, 0);
+      /* 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;
 }
 
-/* Entry point for the benefit of c_common_nodes_and_builtins.
-
-   Make a definition for a builtin function named NAME and whose data type
-   is TYPE.  TYPE should be a function type with argument types.  This
-   function places the anticipated declaration in the global namespace
-   and additionally in the std namespace if appropriate.
-
-   CLASS and CODE tell later passes how to compile calls to this function.
-   See tree.h for possible values.
-
-   If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
-   the name to be called if we can't opencode the function.
-
-   If ATTRS is nonzero, use that for the function's attribute
-   list.  */
-
 tree
-builtin_function (const char* name,
-                 tree type,
-                 int code,
-                 enum built_in_class cl,
-                 const char* libname,
-                 tree attrs)
+cxx_builtin_function (tree decl)
 {
+  tree          id = DECL_NAME (decl);
+  const char *name = IDENTIFIER_POINTER (id);
   /* All builtins that don't begin with an '_' should additionally
      go in the 'std' namespace.  */
   if (name[0] != '_')
     {
+      tree decl2 = copy_node(decl);
       push_namespace (std_identifier);
-      builtin_function_1 (name, type, std_node, code, cl, libname, attrs);
+      builtin_function_1 (decl2, std_node);
       pop_namespace ();
     }
 
-  return builtin_function_1 (name, type, NULL_TREE, code,
-                            cl, libname, attrs);
+  return builtin_function_1 (decl, NULL_TREE);
 }
 
 /* Generate a FUNCTION_DECL with the typical flags for a runtime library
@@ -3468,7 +3581,7 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
    We assume that such functions never throw; if this is incorrect,
    callers should unset TREE_NOTHROW.  */
 
-tree
+static tree
 build_library_fn (tree name, tree type)
 {
   tree fn = build_library_fn_1 (name, ERROR_MARK, type);
@@ -3507,12 +3620,18 @@ build_cp_library_fn_ptr (const char* name, tree type)
 }
 
 /* Like build_library_fn, but also pushes the function so that we will
-   be able to find it via IDENTIFIER_GLOBAL_VALUE.  */
+   be able to find it via IDENTIFIER_GLOBAL_VALUE.  Also, the function
+   may throw exceptions listed in RAISES.  */
 
 tree
-push_library_fn (tree name, tree type)
+push_library_fn (tree name, tree type, tree raises)
 {
-  tree fn = build_library_fn (name, type);
+  tree fn;
+
+  if (raises)
+    type = build_exception_variant (type, raises);
+
+  fn = build_library_fn (name, type);
   pushdecl_top_level (fn);
   return fn;
 }
@@ -3537,7 +3656,7 @@ tree
 push_void_library_fn (tree name, tree parmtypes)
 {
   tree type = build_function_type (void_type_node, parmtypes);
-  return push_library_fn (name, type);
+  return push_library_fn (name, type, NULL_TREE);
 }
 
 /* Like push_library_fn, but also note that this function throws
@@ -3546,7 +3665,7 @@ push_void_library_fn (tree name, tree parmtypes)
 tree
 push_throw_library_fn (tree name, tree type)
 {
-  tree fn = push_library_fn (name, type);
+  tree fn = push_library_fn (name, type, NULL_TREE);
   TREE_THIS_VOLATILE (fn) = 1;
   TREE_NOTHROW (fn) = 0;
   return fn;
@@ -3568,7 +3687,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;
@@ -3588,8 +3707,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).
@@ -3641,23 +3766,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
@@ -3684,9 +3809,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
       /* Anonymous unions are objects, so they can have specifiers.  */;
       SET_ANON_AGGR_TYPE_P (declared_type);
 
-      if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
-         && !in_system_header)
-       pedwarn ("ISO C++ prohibits anonymous structs");
+      if (TREE_CODE (declared_type) != UNION_TYPE && !in_system_header)
+       pedwarn (OPT_pedantic, "ISO C++ prohibits anonymous structs");
     }
 
   else
@@ -3711,6 +3835,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
               || declspecs->specs[(int)ds_thread])
        error ("qualifiers can only be specified for objects "
               "and functions");
+      else if (saw_typedef)
+       warning (0, "%<typedef%> was ignored in this declaration");
     }
 
   return declared_type;
@@ -3779,25 +3905,36 @@ 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 1
+   if an explicit initializer is present, or 2 for an explicitly defaulted
+   function, or 3 for an explicitly deleted function, but 0 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,
@@ -3808,8 +3945,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;
 
@@ -3849,12 +3988,15 @@ start_decl (const cp_declarator *declarator,
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+       error ("typedef %qD is initialized (use decltype instead)", decl);
        return error_mark_node;
 
       case FUNCTION_DECL:
-       error ("function %q#D is initialized like a variable", decl);
-       return error_mark_node;
+       if (initialized == 3)
+         /* We'll handle the rest of the semantics later, but we need to
+            set this now so it's visible to duplicate_decls.  */
+         DECL_DELETED_FN (decl) = 1;
+       break;
 
       default:
        break;
@@ -3871,8 +4013,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,
@@ -3905,10 +4056,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
@@ -3934,8 +4085,9 @@ start_decl (const cp_declarator *declarator,
                                       > template_class_depth (context))
                                      ? current_template_parms
                                      : NULL_TREE);
-         if (field && duplicate_decls (decl, field,
-                                       /*newdecl_is_friend=*/false))
+         if (field && field != error_mark_node
+             && duplicate_decls (decl, field,
+                                /*newdecl_is_friend=*/false))
            decl = field;
        }
 
@@ -3960,40 +4112,62 @@ 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
+  /* Tell the back end to use or not use .common as appropriate.  If we say
      -fconserve-space, we want this to save .data space, at the expense of
      wrong semantics.  If we say -fno-conserve-space, we want this to
      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 (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 (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);
 
@@ -4001,21 +4175,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))))
@@ -4023,30 +4213,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.
@@ -4122,6 +4297,63 @@ 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
+   array.  This function checks that CE does not use a designated
+   initializer.  If it does, an error is issued.  Returns true if CE
+   is valid, i.e., does not have a designated initializer.  */
+
+static bool
+check_array_designated_initializer (const constructor_elt *ce)
+{
+  /* Designated initializers for array elements are not supported.  */
+  if (ce->index)
+    {
+      /* The parser only allows identifiers as designated
+        initializers.  */
+      gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+      error ("name %qD used in a GNU-style designated "
+            "initializer for an array", ce->index);
+      return false;
+    }
+
+  return true;
+}
+
 /* When parsing `int a[] = {1, 2};' we don't know the size of the
    array until we finish parsing the initializer.  If that's the
    situation we're in, update DECL accordingly.  */
@@ -4139,32 +4371,52 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
         But let's leave it here to ease the eventual merge.  */
       int do_default = !DECL_EXTERNAL (decl);
       tree initializer = init ? init : DECL_INITIAL (decl);
-      int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
-                                           do_default);
+      int failure = 0;
 
-      if (failure == 1)
+      /* Check that there are no designated initializers in INIT, as
+        those are not supported in GNU C++, and as the middle-end
+        will crash if presented with a non-numeric designated
+        initializer.  */
+      if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
        {
-         error ("initializer fails to determine size of %qD", decl);
-         TREE_TYPE (decl) = error_mark_node;
+         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
+         constructor_elt *ce;
+         HOST_WIDE_INT i;
+         for (i = 0; 
+              VEC_iterate (constructor_elt, v, i, ce);
+              ++i) 
+           if (!check_array_designated_initializer (ce))
+             failure = 1;
        }
-      else if (failure == 2)
+
+      if (!failure)
        {
-         if (do_default)
+         failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
+                                           do_default);
+         if (failure == 1)
            {
-             error ("array size missing in %qD", decl);
+             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);
+                 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
+                will give it a default size and it will get allocated.  */
+             else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+               DECL_EXTERNAL (decl) = 1;
+           }
+         else if (failure == 3)
+           {
+             error ("zero-size array %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
-            will give it a default size and it will get allocated.  */
-         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
-           DECL_EXTERNAL (decl) = 1;
-       }
-      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);
@@ -4212,7 +4464,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);
 
@@ -4227,7 +4479,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;
+       }
     }
 }
 
@@ -4353,7 +4608,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)
     {
@@ -4376,18 +4631,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
     {
       tree elt_init;
 
-      if (d->cur->index)
-       {
-         /* Handle array designated initializers (GNU extension).  */
-         if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
-           {
-             error ("name %qD used in a GNU-style designated "
-                    "initializer for an array", d->cur->index);
-           }
-         else
-           gcc_unreachable ();
-       }
-
+      check_array_designated_initializer (d->cur);
       elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
       if (elt_init == error_mark_node)
        return error_mark_node;
@@ -4459,7 +4703,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)
@@ -4533,15 +4777,20 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
   if (!CP_AGGREGATE_TYPE_P (type))
     {
       /* It is invalid to initialize a non-aggregate type with a
-        brace-enclosed initializer.
+        brace-enclosed initializer before C++0x.
         We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
         of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
         a CONSTRUCTOR (with a record type).  */
       if (TREE_CODE (init) == CONSTRUCTOR
          && BRACE_ENCLOSED_INITIALIZER_P (init))  /* p7626.C */
        {
-         error ("braces around scalar initializer for type %qT", type);
-         init = error_mark_node;
+         if (SCALAR_TYPE_P (type))
+           {
+             error ("braces around scalar initializer for type %qT", type);
+             init = error_mark_node;
+           }
+         else
+           maybe_warn_cpp0x ("extended initializer lists");
        }
 
       d->cur++;
@@ -4603,19 +4852,24 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
     {
       if (TREE_CODE (init) == CONSTRUCTOR)
        {
+         if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
+           /* There is no need to reshape pointer-to-member function
+              initializers, as they are always constructed correctly
+              by the front end.  */
+           ;
+         else if (COMPOUND_LITERAL_P (init))
          /* For a nested compound literal, there is no need to reshape since
             brace elision is not allowed. Even if we decided to allow it,
             we should add a call to reshape_init in finish_compound_literal,
             before calling digest_init, so changing this code would still
             not be necessary.  */
-         if (!COMPOUND_LITERAL_P (init))
+           gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
+         else
            {
              ++d->cur;
              gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
              return reshape_init (type, init);
            }
-         else
-           gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
        }
 
       warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
@@ -4680,6 +4934,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.
@@ -4703,24 +5009,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 an 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))
     {
@@ -4731,14 +5021,25 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   else
     /* There is no way to make a variable-sized class type in GNU C++.  */
     gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
-  
-  if (!CP_AGGREGATE_TYPE_P (type)
-      && init && BRACE_ENCLOSED_INITIALIZER_P (init)
-      && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
+
+  if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
     {
-      error ("scalar object %qD requires one element in initializer", decl);
-      TREE_TYPE (decl) = error_mark_node;
-      return NULL_TREE;
+      int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+      if (SCALAR_TYPE_P (type))
+       {
+         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);
+             TREE_TYPE (decl) = error_mark_node;
+             return NULL_TREE;
+           }
+       }
     }
 
   if (TREE_CODE (decl) == CONST_DECL)
@@ -4756,17 +5057,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
@@ -4776,61 +5086,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);
 
@@ -4894,7 +5170,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.  */
@@ -4938,6 +5214,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
@@ -4945,6 +5270,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);
@@ -4955,46 +5281,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);
 }
 
@@ -5009,7 +5342,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;
@@ -5019,6 +5352,36 @@ initialize_artificial_var (tree decl, tree init)
   make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
 }
 
+/* INIT is the initializer for a variable, as represented by the
+   parser.  Returns true iff INIT is value-dependent.  */
+
+static bool
+value_dependent_init_p (tree init)
+{
+  if (TREE_CODE (init) == TREE_LIST)
+    /* A parenthesized initializer, e.g.: int i (3, 2); ? */
+    return any_value_dependent_elements_p (init);
+  else if (TREE_CODE (init) == CONSTRUCTOR)
+  /* A brace-enclosed initializer, e.g.: int i = { 3 }; ? */
+    {
+      VEC(constructor_elt, gc) *elts;
+      size_t nelts;
+      size_t i;
+
+      elts = CONSTRUCTOR_ELTS (init);
+      nelts = VEC_length (constructor_elt, elts);
+      for (i = 0; i < nelts; ++i)
+       if (value_dependent_init_p (VEC_index (constructor_elt,
+                                              elts, i)->value))
+         return true;
+    }
+  else
+    /* It must be a simple expression, e.g., int i = 3;  */
+    return value_dependent_expression_p (init);
+  
+  return false;
+}
+
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
@@ -5084,6 +5447,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;
@@ -5091,11 +5460,16 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            TREE_CONSTANT (decl) = 1;
        }
 
-      if (!init
-         || !DECL_CLASS_SCOPE_P (decl)
-         || !DECL_INTEGRAL_CONSTANT_VAR_P (decl)
-         || type_dependent_p
-         || value_dependent_expression_p (init))
+      /* Generally, initializers in templates are expanded when the
+        template is instantiated.  But, if DECL is an integral
+        constant static data member, then it can be used in future
+        integral constant expressions, and its value must be
+        available. */
+      if (!(init
+           && DECL_CLASS_SCOPE_P (decl)
+           && DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+           && !type_dependent_p
+           && !value_dependent_init_p (init)))
        {
          if (init)
            DECL_INITIAL (decl) = init;
@@ -5106,7 +5480,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;
     }
 
@@ -5114,7 +5502,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);
@@ -5155,8 +5543,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);
@@ -5169,6 +5556,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;
@@ -5239,6 +5640,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
@@ -5256,14 +5660,24 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
        {
          layout_var_decl (decl);
          maybe_commonize_var (decl);
-         if (DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl)
-             && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (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)
            {
-             /* 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.  */
-             DECL_THIS_STATIC (decl) = 1;
+             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);
@@ -5277,13 +5691,38 @@ 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)
+      if (TREE_TYPE (decl) == error_mark_node)
        /* No initialization required.  */
        ;
+      else if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         if (init)
+           {
+             if (init == ridpointers[(int)RID_DELETE])
+               {
+                 /* fixme check this is 1st decl */
+                 DECL_DELETED_FN (decl) = 1;
+                 DECL_DECLARED_INLINE_P (decl) = 1;
+                 DECL_INITIAL (decl) = error_mark_node;
+               }
+             else if (init == ridpointers[(int)RID_DEFAULT])
+               {
+                 if (!defaultable_fn_p (decl))
+                   error ("%qD cannot be defaulted", decl);
+                 else
+                   {
+                     /* An out-of-class default definition is defined at
+                        the point where it is explicitly defaulted.  */
+                     DECL_DEFAULTED_FN (decl) = 1;
+                     if (DECL_INITIAL (decl) == error_mark_node)
+                       synthesize_method (decl);
+                   }
+               }
+             else
+               error ("function %q#D is initialized like a variable", decl);
+           }
+         /* else no initialization required.  */
+       }
       else if (DECL_EXTERNAL (decl)
               && ! (DECL_LANG_SPECIFIC (decl)
                     && DECL_NOT_REALLY_EXTERN (decl)))
@@ -5291,29 +5730,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))
-           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
@@ -5368,6 +5799,33 @@ declare_global_var (tree name, tree type)
   return decl;
 }
 
+/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
+   if "__cxa_atexit" is not being used) corresponding to the function
+   to be called when the program exits.  */
+
+static tree
+get_atexit_fn_ptr_type (void)
+{
+  tree arg_types;
+  tree fn_type;
+
+  if (!atexit_fn_ptr_type_node)
+    {
+      if (flag_use_cxa_atexit 
+         && !targetm.cxx.use_atexit_for_cxa_atexit ())
+       /* The parameter to "__cxa_atexit" is "void (*)(void *)".  */
+       arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+      else
+       /* The parameter to "atexit" is "void (*)(void)".  */
+       arg_types = void_list_node;
+      
+      fn_type = build_function_type (void_type_node, arg_types);
+      atexit_fn_ptr_type_node = build_pointer_type (fn_type);
+    }
+
+  return atexit_fn_ptr_type_node;
+}
+
 /* Returns a pointer to the `atexit' function.  Note that if
    FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
    `__cxa_atexit' function specified in the IA64 C++ ABI.  */
@@ -5385,7 +5843,7 @@ get_atexit_node (void)
   if (atexit_node)
     return atexit_node;
 
-  if (flag_use_cxa_atexit)
+  if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
     {
       /* The declaration for `__cxa_atexit' is:
 
@@ -5397,9 +5855,7 @@ get_atexit_node (void)
       use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
       /* First, build the pointer-to-function type for the first
         argument.  */
-      arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
-      fn_type = build_function_type (void_type_node, arg_types);
-      fn_ptr_type = build_pointer_type (fn_type);
+      fn_ptr_type = get_atexit_fn_ptr_type ();
       /* Then, build the rest of the argument types.  */
       arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
       if (use_aeabi_atexit)
@@ -5428,8 +5884,7 @@ get_atexit_node (void)
 
         We build up the argument types and then then function type
         itself.  */
-      fn_type = build_function_type (void_type_node, void_list_node);
-      fn_ptr_type = build_pointer_type (fn_type);
+      fn_ptr_type = get_atexit_fn_ptr_type ();
       arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
       /* Build the final atexit type.  */
       fn_type = build_function_type (integer_type_node, arg_types);
@@ -5470,28 +5925,20 @@ static tree
 start_cleanup_fn (void)
 {
   char name[32];
-  tree parmtypes;
   tree fntype;
   tree fndecl;
+  bool use_cxa_atexit = flag_use_cxa_atexit
+                       && !targetm.cxx.use_atexit_for_cxa_atexit ();
 
   push_to_top_level ();
 
   /* No need to mangle this.  */
   push_lang_context (lang_name_c);
 
-  /* Build the parameter-types.  */
-  parmtypes = void_list_node;
-  /* Functions passed to __cxa_atexit take an additional parameter.
-     We'll just ignore it.  After we implement the new calling
-     convention for destructors, we can eliminate the use of
-     additional cleanup functions entirely in the -fnew-abi case.  */
-  if (flag_use_cxa_atexit)
-    parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
-  /* Build the function type itself.  */
-  fntype = build_function_type (void_type_node, parmtypes);
   /* Build the name of the function.  */
   sprintf (name, "__tcf_%d", start_cleanup_cnt++);
   /* Build the function declaration.  */
+  fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
   fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
   /* It's a function with internal linkage, generated by the
      compiler.  */
@@ -5501,11 +5948,9 @@ start_cleanup_fn (void)
      actually needed.  It is unlikely that it will be inlined, since
      it is only called via a function pointer, but we avoid unnecessary
      emissions this way.  */
-  DECL_INLINE (fndecl) = 1;
-  DECL_DECLARED_INLINE_P (fndecl) = 1;
   DECL_INTERFACE_KNOWN (fndecl) = 1;
   /* Build the parameter.  */
-  if (flag_use_cxa_atexit)
+  if (use_cxa_atexit)
     {
       tree parmdecl;
 
@@ -5543,56 +5988,104 @@ register_dtor_fn (tree decl)
   tree compound_stmt;
   tree args;
   tree fcall;
+  tree type;
+  bool use_dtor;
 
-  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+  type = TREE_TYPE (decl);
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     return void_zero_node;
 
-  /* Call build_cleanup before we enter the anonymous function so that
-     any access checks will be done relative to the current scope,
-     rather than the scope of the anonymous function.  */
-  build_cleanup (decl);
-
-  /* Now start the function.  */
-  cleanup = start_cleanup_fn ();
-
-  /* Now, recompute the cleanup.  It may contain SAVE_EXPRs that refer
-     to the original function, rather than the anonymous one.  That
-     will make the back-end think that nested functions are in use,
-     which causes confusion.  */
-
-  push_deferring_access_checks (dk_no_check);
-  fcall = build_cleanup (decl);
-  pop_deferring_access_checks ();
+  /* If we're using "__cxa_atexit" (or "__aeabi_atexit"), and DECL is
+     a class object, we can just pass the destructor to
+     "__cxa_atexit"; we don't have to build a temporary function to do
+     the cleanup.  */
+  use_dtor = (flag_use_cxa_atexit 
+             && !targetm.cxx.use_atexit_for_cxa_atexit ()
+             && CLASS_TYPE_P (type));
+  if (use_dtor)
+    {
+      int idx;
 
-  /* Create the body of the anonymous function.  */
-  compound_stmt = begin_compound_stmt (BCS_FN_BODY);
-  finish_expr_stmt (fcall);
-  finish_compound_stmt (compound_stmt);
-  end_cleanup_fn ();
+      /* Find the destructor.  */
+      idx = lookup_fnfields_1 (type, complete_dtor_identifier);
+      gcc_assert (idx >= 0);
+      cleanup = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
+      /* Make sure it is accessible.  */
+      perform_or_defer_access_check (TYPE_BINFO (type), cleanup, cleanup);
+    }
+  else
+    {
+      /* Call build_cleanup before we enter the anonymous function so
+        that any access checks will be done relative to the current
+        scope, rather than the scope of the anonymous function.  */
+      build_cleanup (decl);
+  
+      /* Now start the function.  */
+      cleanup = start_cleanup_fn ();
+      
+      /* Now, recompute the cleanup.  It may contain SAVE_EXPRs that refer
+        to the original function, rather than the anonymous one.  That
+        will make the back end think that nested functions are in use,
+        which causes confusion.  */
+      push_deferring_access_checks (dk_no_check);
+      fcall = build_cleanup (decl);
+      pop_deferring_access_checks ();
+      
+      /* Create the body of the anonymous function.  */
+      compound_stmt = begin_compound_stmt (BCS_FN_BODY);
+      finish_expr_stmt (fcall);
+      finish_compound_stmt (compound_stmt);
+      end_cleanup_fn ();
+    }
 
   /* Call atexit with the cleanup function.  */
-  cxx_mark_addressable (cleanup);
   mark_used (cleanup);
-  cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
-  if (flag_use_cxa_atexit)
-    {
+  cleanup = build_address (cleanup);
+  if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
+    {
+      tree addr;
+
+      if (use_dtor)
+       {
+         /* We must convert CLEANUP to the type that "__cxa_atexit"
+            expects.  */
+         cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
+         /* "__cxa_atexit" will pass the address of DECL to the
+            cleanup function.  */
+         mark_used (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 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);
+       }
+      else
+       /* Since the cleanup functions we build ignore the address
+          they're given, there's no reason to pass the actual address
+          in, and, in general, it's cheaper to pass NULL than any
+          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 ())
        {
          args = tree_cons (NULL_TREE, cleanup, args);
-         args = tree_cons (NULL_TREE, null_pointer_node, args);
+         args = tree_cons (NULL_TREE, addr, args);
        }
       else
        {
-         args = tree_cons (NULL_TREE, null_pointer_node, args);
+         args = tree_cons (NULL_TREE, addr, args);
          args = tree_cons (NULL_TREE, cleanup, args);
        }
     }
   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,
@@ -5616,7 +6109,7 @@ expand_static_init (tree decl, tree init)
       /* Emit code to perform this initialization but once.  */
       tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
       tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
-      tree guard, guard_addr, guard_addr_list;
+      tree guard, guard_addr;
       tree acquire_fn, release_fn, abort_fn;
       tree flag, begin;
 
@@ -5668,7 +6161,6 @@ expand_static_init (tree decl, tree init)
       if (flag_threadsafe_statics)
        {
          guard_addr = build_address (guard);
-         guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
 
          acquire_fn = get_identifier ("__cxa_guard_acquire");
          release_fn = get_identifier ("__cxa_guard_release");
@@ -5679,9 +6171,10 @@ expand_static_init (tree decl, tree init)
                                         void_list_node);
              tree vfntype = build_function_type (void_type_node, argtypes);
              acquire_fn = push_library_fn
-               (acquire_fn, build_function_type (integer_type_node, argtypes));
-             release_fn = push_library_fn (release_fn, vfntype);
-             abort_fn = push_library_fn (abort_fn, vfntype);
+               (acquire_fn, build_function_type (integer_type_node, argtypes),
+                NULL_TREE);
+             release_fn = push_library_fn (release_fn, vfntype, NULL_TREE);
+             abort_fn = push_library_fn (abort_fn, vfntype, NULL_TREE);
            }
          else
            {
@@ -5690,7 +6183,7 @@ expand_static_init (tree decl, tree init)
            }
 
          inner_if_stmt = begin_if_stmt ();
-         finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+         finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
                               inner_if_stmt);
 
          inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
@@ -5700,7 +6193,7 @@ expand_static_init (tree decl, tree init)
          TARGET_EXPR_CLEANUP (begin)
            = build3 (COND_EXPR, void_type_node, flag,
                      void_zero_node,
-                     build_call (abort_fn, guard_addr_list));
+                     build_call_n (abort_fn, 1, guard_addr));
          CLEANUP_EH_ONLY (begin) = 1;
 
          /* Do the initialization itself.  */
@@ -5708,7 +6201,7 @@ expand_static_init (tree decl, tree init)
          init = add_stmt_to_compound
            (init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
          init = add_stmt_to_compound
-           (init, build_call (release_fn, guard_addr_list));
+           (init, build_call_n (release_fn, 1, guard_addr));
        }
       else
        init = add_stmt_to_compound (init, set_guard (guard));
@@ -5751,6 +6244,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.
 
@@ -5767,6 +6263,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);
@@ -5869,8 +6377,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
@@ -5953,6 +6461,28 @@ grokfndecl (tree ctype,
   if (TYPE_VOLATILE (type))
     TREE_THIS_VOLATILE (decl) = 1;
 
+  /* Setup decl according to sfk.  */
+  switch (sfk)
+    {
+    case sfk_constructor:
+    case sfk_copy_constructor:
+      DECL_CONSTRUCTOR_P (decl) = 1;
+      break;
+    case sfk_destructor:
+      DECL_DESTRUCTOR_P (decl) = 1;
+      break;
+    default:
+      break;
+    }
+
+  /* If pointers to member functions use the least significant bit to
+     indicate whether a function is virtual, ensure a pointer
+     to this function will have that bit clear.  */
+  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
+      && TREE_CODE (type) == METHOD_TYPE
+      && DECL_ALIGN (decl) < 2 * BITS_PER_UNIT)
+    DECL_ALIGN (decl) = 2 * BITS_PER_UNIT;
+
   if (friendp
       && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
     {
@@ -6054,16 +6584,6 @@ grokfndecl (tree ctype,
        error ("cannot declare %<::main%> to be inline");
       if (!publicp)
        error ("cannot declare %<::main%> to be static");
-      if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
-                       integer_type_node))
-       {
-         tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
-         tree newtype;
-         error ("%<::main%> must return %<int%>");
-         newtype =  build_function_type (integer_type_node,
-                                         oldtypeargs);
-         TREE_TYPE (decl) = newtype;
-       }
       inlinep = 0;
       publicp = 1;
     }
@@ -6091,16 +6611,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);
        }
     }
 
@@ -6114,17 +6634,14 @@ grokfndecl (tree ctype,
   /* If the declaration was declared inline, mark it as such.  */
   if (inlinep)
     DECL_DECLARED_INLINE_P (decl) = 1;
-  /* We inline functions that are explicitly declared inline, or, when
-     the user explicitly asks us to, all functions.  */
-  if (DECL_DECLARED_INLINE_P (decl)
-      || (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
-    DECL_INLINE (decl) = 1;
 
   DECL_EXTERNAL (decl) = 1;
   if (quals && TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error ("%smember function %qD cannot have cv-qualifier",
-            (ctype ? "static " : "non-"), decl);
+      error (ctype
+             ? G_("static member function %qD cannot have cv-qualifier")
+             : G_("non-member function %qD cannot have cv-qualifier"),
+            decl);
       quals = TYPE_UNQUALIFIED;
     }
 
@@ -6148,12 +6665,7 @@ grokfndecl (tree ctype,
     return decl;
 
   if (ctype != NULL_TREE)
-    {
-      if (sfk == sfk_constructor)
-       DECL_CONSTRUCTOR_P (decl) = 1;
-
-      grokclassfn (ctype, decl, flags);
-    }
+    grokclassfn (ctype, decl, flags);
 
   decl = check_explicit_specialization (orig_declarator, decl,
                                        template_count,
@@ -6168,17 +6680,35 @@ grokfndecl (tree ctype,
       *attrlist = NULL_TREE;
     }
 
+  /* Check main's type after attributes have been applied.  */
+  if (ctype == NULL_TREE && DECL_MAIN_P (decl))
+    {
+      if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+                       integer_type_node))
+       {
+         tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
+         tree newtype;
+         error ("%<::main%> must return %<int%>");
+         newtype = build_function_type (integer_type_node, oldtypeargs);
+         TREE_TYPE (decl) = newtype;
+       }
+      if (warn_main)
+       check_main_parameter_types (decl);
+    }
+
   if (ctype != NULL_TREE
       && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
       && check)
     {
-      tree old_decl;
+      tree old_decl = check_classfn (ctype, decl,
+                                    (processing_template_decl
+                                     > template_class_depth (ctype))
+                                    ? current_template_parms
+                                    : NULL_TREE);
+
+      if (old_decl == error_mark_node)
+       return NULL_TREE;
 
-      old_decl = check_classfn (ctype, decl,
-                               (processing_template_decl
-                                > template_class_depth (ctype))
-                               ? current_template_parms
-                               : NULL_TREE);
       if (old_decl)
        {
          tree ok;
@@ -6197,7 +6727,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.  */
@@ -6331,14 +6864,7 @@ grokvardecl (tree type,
     }
 
   if (declspecs->specs[(int)ds_thread])
-    {
-      if (targetm.have_tls)
-       DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
-      else
-       /* A mere warning is sure to result in improper semantics
-          at runtime.  Don't bother to allow this to compile.  */
-       error ("thread-local storage not supported for this target");
-    }
+    DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
 
   if (TREE_PUBLIC (decl))
     {
@@ -6405,13 +6931,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...  */
+  /* 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;
@@ -6422,7 +6948,7 @@ build_ptrmemfunc_type (tree type)
 
   finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
 
-  /* Zap out the name so that the back-end will give us the debugging
+  /* Zap out the name so that the back end will give us the debugging
      information for this anonymous RECORD_TYPE.  */
   TYPE_NAME (t) = NULL_TREE;
 
@@ -6436,12 +6962,18 @@ build_ptrmemfunc_type (tree type)
       TYPE_MAIN_VARIANT (t) = unqualified_variant;
       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
       TYPE_NEXT_VARIANT (unqualified_variant) = t;
+      TREE_TYPE (TYPE_BINFO (t)) = t;
     }
 
   /* Cache this pointer-to-member type so that we can find it again
      later.  */
   TYPE_SET_PTRMEMFUNC_TYPE (type, t);
 
+  if (TYPE_STRUCTURAL_EQUALITY_P (type))
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (TYPE_CANONICAL (type) != type)
+    TYPE_CANONICAL (t) = build_ptrmemfunc_type (TYPE_CANONICAL (type));
+
   return t;
 }
 
@@ -6500,8 +7032,8 @@ check_static_variable_definition (tree decl, tree type)
     error ("ISO C++ forbids in-class initialization of non-const "
           "static member %qD",
           decl);
-  else if (pedantic && !INTEGRAL_TYPE_P (type))
-    pedwarn ("ISO C++ forbids initialization of member constant "
+  else if (!INTEGRAL_TYPE_P (type))
+    pedwarn (OPT_pedantic, "ISO C++ forbids initialization of member constant "
             "%qD of non-integral type %qT", decl, type);
 
   return 0;
@@ -6516,6 +7048,7 @@ compute_array_index_type (tree name, tree size)
 {
   tree type;
   tree itype;
+  tree abi_1_itype = NULL_TREE;
 
   if (error_operand_p (size))
     return error_mark_node;
@@ -6532,14 +7065,26 @@ compute_array_index_type (tree name, tree size)
       type = TREE_TYPE (size);
     }
 
-  if (abi_version_at_least (2)
-      /* We should only handle value dependent expressions specially.  */
-      ? value_dependent_expression_p (size)
-      /* But for abi-1, we handled all instances in templates. This
-        effects the manglings produced.  */
-      : processing_template_decl)
-    return build_index_type (build_min (MINUS_EXPR, sizetype,
-                                       size, integer_one_node));
+  if (value_dependent_expression_p (size))
+    {
+      /* We cannot do any checking for a value-dependent SIZE. Just
+        build the index type and mark that it requires structural
+        equality checks.  */
+      itype = build_index_type (build_min (MINUS_EXPR, sizetype,
+                                          size, integer_one_node));
+      SET_TYPE_STRUCTURAL_EQUALITY (itype);
+      return itype;
+    }
+  
+  if (!abi_version_at_least (2) && processing_template_decl)
+    /* For abi-1, we handled all instances in templates the same way,
+       even when they were non-dependent. This affects the manglings
+       produced.  So, we do the normal checking for non-dependent
+       sizes, but at the end we'll return the same type that abi-1
+       would have, but with TYPE_CANONICAL set to the "right"
+       value that the current ABI would provide. */
+    abi_1_itype = build_index_type (build_min (MINUS_EXPR, sizetype,
+                                              size, integer_one_node));
 
   /* The size might be the result of a cast.  */
   STRIP_TYPE_NOPS (size);
@@ -6552,12 +7097,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))
@@ -6570,12 +7110,12 @@ compute_array_index_type (tree name, tree size)
        }
       /* As an extension we allow zero-sized arrays.  We always allow
         them in system headers because glibc uses them.  */
-      else if (integer_zerop (size) && pedantic && !in_system_header)
+      else if (integer_zerop (size) && !in_system_header)
        {
          if (name)
-           pedwarn ("ISO C++ forbids zero-size array %qD", name);
+           pedwarn (OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
          else
-           pedwarn ("ISO C++ forbids zero-size array");
+           pedwarn (OPT_pedantic, "ISO C++ forbids zero-size array");
        }
     }
   else if (TREE_CONSTANT (size))
@@ -6588,12 +7128,21 @@ compute_array_index_type (tree name, tree size)
        error ("size of array is not an integral constant-expression");
       size = integer_one_node;
     }
-  else if (pedantic)
+  else if (pedantic && warn_vla != 0)
+    {
+      if (name)
+       pedwarn (OPT_Wvla, "ISO C++ forbids variable length array %qD", name);
+      else
+       pedwarn (OPT_Wvla, "ISO C++ forbids variable length array");
+    }
+  else if (warn_vla > 0)
     {
       if (name)
-       pedwarn ("ISO C++ forbids variable-size array %qD", name);
+       warning (OPT_Wvla, 
+                 "variable length array %qD is used", name);
       else
-       pedwarn ("ISO C++ forbids variable-size array");
+       warning (OPT_Wvla, 
+                 "variable length array is used");
     }
 
   if (processing_template_decl && !TREE_CONSTANT (size))
@@ -6611,7 +7160,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;
 
@@ -6630,7 +7180,14 @@ compute_array_index_type (tree name, tree size)
     }
 
   /* Create and return the appropriate index type.  */
-  return build_index_type (itype);
+  if (abi_1_itype)
+    {
+      tree t = build_index_type (itype);
+      TYPE_CANONICAL (abi_1_itype) = TYPE_CANONICAL (t);
+      return abi_1_itype;
+    }
+  else
+    return build_index_type (itype);
 }
 
 /* Returns the scope (if any) in which the entity declared by
@@ -6773,10 +7330,8 @@ check_special_function_return_type (special_function_kind sfk,
       break;
 
     case sfk_conversion:
-      if (type && !same_type_p (type, optype))
-       error ("operator %qT declared to return %qT", optype, type);
-      else if (type)
-       pedwarn ("return type specified for %<operator %T%>",  optype);
+      if (type)
+       error ("return type specified for %<operator %T%>",  optype);
       type = optype;
       break;
 
@@ -6816,8 +7371,8 @@ check_var_type (tree identifier, tree type)
    the name and type of the object declared and construct a DECL node
    for it.
 
-   DECLSPECS is a chain of tree_list nodes whose value fields
-    are the storage classes and type specifiers.
+   DECLSPECS points to the representation of declaration-specifier
+   sequence that precedes declarator.
 
    DECL_CONTEXT says which syntactic context this declaration is in:
      NORMAL for most contexts.  Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
@@ -6835,7 +7390,7 @@ check_var_type (tree identifier, tree type)
       Don't make a DECL node; just return the ..._TYPE node.
      FIELD for a struct or union field; make a FIELD_DECL.
      BITFIELD for a field with specified width.
-   INITIALIZED is 1 if the decl has an initializer.
+   INITIALIZED is as for start_decl.
 
    ATTRLIST is a pointer to the list of attributes, which may be NULL
    if there are none; *ATTRLIST may be modified if attributes from inside
@@ -6916,6 +7471,8 @@ grokdeclarator (const cp_declarator *declarator,
   cp_storage_class storage_class;
   bool unsigned_p, signed_p, short_p, long_p, thread_p;
   bool type_was_error_mark_node = false;
+  bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
+  bool set_no_warning = false;
 
   signed_p = declspecs->specs[(int)ds_signed];
   unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -6931,6 +7488,9 @@ grokdeclarator (const cp_declarator *declarator,
   else if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
 
+  if (initialized > 1)
+    funcdef_flag = true;
+
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -7062,19 +7622,19 @@ grokdeclarator (const cp_declarator *declarator,
                gcc_unreachable ();
              }
            break;
+         }
 
-         case cdk_array:
-         case cdk_pointer:
-         case cdk_reference:
-         case cdk_ptrmem:
-           break;
+       case cdk_array:
+       case cdk_pointer:
+       case cdk_reference:
+       case cdk_ptrmem:
+         break;
 
-         case cdk_error:
-           return error_mark_node;
+       case cdk_error:
+         return error_mark_node;
 
-         default:
-           gcc_unreachable ();
-         }
+       default:
+         gcc_unreachable ();
        }
       if (id_declarator->kind == cdk_id)
        break;
@@ -7132,6 +7692,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)
@@ -7148,6 +7714,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.  */
@@ -7194,10 +7764,14 @@ 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)
-       pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
-      else if (warn_return_type)
-       warning (0, "ISO C++ forbids declaration of %qs with no type", name);
+      else if (! is_main)
+       permerror ("ISO C++ forbids declaration of %qs with no type", name);
+      else if (pedantic)
+       pedwarn (OPT_pedantic,
+                "ISO C++ forbids declaration of %qs with no type", name);
+      else
+       warning (OPT_Wreturn_type,
+                 "ISO C++ forbids declaration of %qs with no type", name);
 
       type = integer_type_node;
     }
@@ -7237,12 +7811,20 @@ 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;
          if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
            {
-             pedwarn ("long, short, signed or unsigned used invalidly for %qs",
+             pedwarn (OPT_pedantic, 
+                      "long, short, signed or unsigned used invalidly for %qs",
                       name);
              if (flag_pedantic_errors)
                ok = 0;
@@ -7290,7 +7872,7 @@ grokdeclarator (const cp_declarator *declarator,
       else if (type == char_type_node)
        type = unsigned_char_type_node;
       else if (typedef_decl)
-       type = c_common_unsigned_type (type);
+       type = unsigned_type_for (type);
       else
        type = unsigned_type_node;
     }
@@ -7347,7 +7929,8 @@ grokdeclarator (const cp_declarator *declarator,
       if (pedantic)
        {
          tree bad_type = build_qualified_type (type, type_quals);
-         pedwarn ("ignoring %qV qualifiers added to function type %qT",
+         pedwarn (OPT_pedantic, 
+                  "ignoring %qV qualifiers added to function type %qT",
                   bad_type, type);
        }
       type_quals = TYPE_UNQUALIFIED;
@@ -7400,7 +7983,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;
     }
 
@@ -7412,24 +7995,19 @@ grokdeclarator (const cp_declarator *declarator,
 
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
-  if (declspecs->conflicting_specifiers_p)
-    {
-      error ("conflicting specifiers in declaration of %qs", name);
-      storage_class = sc_none;
-    }
-  else if (thread_p
-          && ((storage_class
-               && storage_class != sc_extern
-               && storage_class != sc_static)
-              || declspecs->specs[(int)ds_typedef]))
+  if (thread_p
+      && ((storage_class
+          && storage_class != sc_extern
+          && storage_class != sc_static)
+         || declspecs->specs[(int)ds_typedef]))
     {
       error ("multiple storage classes in declaration of %qs", name);
       thread_p = false;
     }
-  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
@@ -7461,19 +8039,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);
@@ -7492,7 +8057,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;
@@ -7562,21 +8131,28 @@ grokdeclarator (const cp_declarator *declarator,
            /* Declaring a function type.
               Make sure we have a valid type for the function to return.  */
 
-           /* We now know that the TYPE_QUALS don't apply to the
-              decl, but to its return type.  */
-           type_quals = TYPE_UNQUALIFIED;
+           if (type_quals != TYPE_UNQUALIFIED)
+             {
+               if (SCALAR_TYPE_P (type) || VOID_TYPE_P (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.  */
+               type_quals = TYPE_UNQUALIFIED;
+               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'.  */
@@ -7635,7 +8211,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
@@ -7688,10 +8264,24 @@ grokdeclarator (const cp_declarator *declarator,
 
          if (TREE_CODE (type) == REFERENCE_TYPE)
            {
-             error (declarator->kind == cdk_reference
-                    ? "cannot declare reference to %q#T"
-                    : "cannot declare pointer to %q#T", type);
-             type = TREE_TYPE (type);
+             if (declarator->kind != cdk_reference)
+               {
+                 error ("cannot declare pointer to %q#T", type);
+                 type = TREE_TYPE (type);
+               }
+
+             /* In C++0x, we allow reference to reference declarations
+                that occur indirectly through typedefs [7.1.3/8 dcl.typedef]
+                and template type arguments [14.3.1/4 temp.arg.type]. The
+                check for direct reference to reference declarations, which
+                are still forbidden, occurs below. Reasoning behind the change
+                can be found in DR106, DR540, and the rvalue reference
+                proposals. */
+             else if (cxx_dialect == cxx98)
+               {
+                 error ("cannot declare reference to %q#T", type);
+                 type = TREE_TYPE (type);
+               }
            }
          else if (VOID_TYPE_P (type))
            {
@@ -7706,7 +8296,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,
@@ -7717,8 +8308,39 @@ grokdeclarator (const cp_declarator *declarator,
 
          if (declarator->kind == cdk_reference)
            {
+             /* In C++0x, the type we are creating a reference to might be
+                a typedef which is itself a reference type. In that case,
+                we follow the reference collapsing rules in
+                [7.1.3/8 dcl.typedef] to create the final reference type:
+
+                "If a typedef TD names a type that is a reference to a type
+                T, an attempt to create the type 'lvalue reference to cv TD'
+                creates the type 'lvalue reference to T,' while an attempt
+                to create the type "rvalue reference to cv TD' creates the
+                type TD."
+              */
              if (!VOID_TYPE_P (type))
-               type = build_reference_type (type);
+               type = cp_build_reference_type
+                      ((TREE_CODE (type) == REFERENCE_TYPE
+                        ? TREE_TYPE (type) : type),
+                       (declarator->u.reference.rvalue_ref
+                        && (TREE_CODE(type) != REFERENCE_TYPE
+                            || TYPE_REF_IS_RVALUE (type))));
+
+             /* In C++0x, we need this check for direct reference to
+                reference declarations, which are forbidden by
+                [8.3.2/5 dcl.ref]. Reference to reference declarations
+                are only allowed indirectly through typedefs and template
+                type arguments. Example:
+
+                  void foo(int & &);      // invalid ref-to-ref decl
+
+                  typedef int & int_ref;
+                  void foo(int_ref &);    // valid ref-to-ref decl
+             */
+             if (inner_declarator && inner_declarator->kind == cdk_reference)
+               error ("cannot declare reference to %q#T, which is not "
+                      "a typedef or a template type argument", type);
            }
          else if (TREE_CODE (type) == METHOD_TYPE)
            type = build_ptrmemfunc_type (build_pointer_type (type));
@@ -7811,10 +8433,14 @@ grokdeclarator (const cp_declarator *declarator,
       if (ctype == current_class_type)
        {
          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_at (declarator->id_loc, 
+                         "extra qualification %<%T::%> on member %qs",
+                         ctype, name);
        }
       else if (/* If the qualifying type is already complete, then we
                  can skip the following checks.  */
@@ -7878,6 +8504,16 @@ grokdeclarator (const cp_declarator *declarator,
        attrlist = &returned_attrs;
     }
 
+  /* Handle parameter packs. */
+  if (parameter_pack_p)
+    {
+      if (decl_context == PARM)
+        /* Turn the type into a pack expansion.*/
+        type = make_pack_expansion (type);
+      else
+        error ("non-parameter %qs cannot be a parameter pack", name);
+    }
+
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -7960,7 +8596,12 @@ grokdeclarator (const cp_declarator *declarator,
         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);
+        {
+          type = cp_build_qualified_type (type, memfn_quals);
+          
+          /* We have now dealt with these qualifiers.  */
+          memfn_quals = TYPE_UNQUALIFIED;
+        }
 
       if (decl_context == FIELD)
        decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
@@ -7983,9 +8624,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.
@@ -7996,8 +8637,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);
@@ -8022,11 +8661,6 @@ grokdeclarator (const cp_declarator *declarator,
             type with external linkage have external linkage.  */
        }
 
-       /* 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;
@@ -8073,8 +8707,11 @@ grokdeclarator (const cp_declarator *declarator,
          if (cp_type_quals (type) != TYPE_UNQUALIFIED
              && (current_class_type == NULL_TREE || staticp) )
            {
-             error ("qualified function types cannot be used to declare %s functions",
-                    (staticp? "static member" : "free"));
+             error (staticp
+                     ? G_("qualified function types cannot be used to "
+                          "declare static member functions")
+                     : G_("qualified function types cannot be used to "
+                          "declare free functions"));
              type = TYPE_MAIN_VARIANT (type);
            }
 
@@ -8112,15 +8749,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.  */
@@ -8296,6 +8933,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) ?
@@ -8330,17 +8974,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;
              }
          }
@@ -8398,7 +9036,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)
@@ -8439,9 +9077,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;
                  }
 
@@ -8470,20 +9108,15 @@ grokdeclarator (const cp_declarator *declarator,
                DECL_EXTERNAL (decl) = 1;
 
                if (thread_p)
-                 {
-                   if (targetm.have_tls)
-                     DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
-                   else
-                     /* A mere warning is sure to result in improper
-                        semantics at runtime.  Don't bother to allow this to
-                        compile.  */
-                     error ("thread-local storage not supported for this target");
-                 }
+                 DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
              }
            else
              {
                decl = build_decl (FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
+               if (bitfield && !unqualified_id)
+                 TREE_NO_WARNING (decl) = 1;
+
                if (storage_class == sc_mutable)
                  {
                    DECL_MUTABLE_P (decl) = 1;
@@ -8526,10 +9159,12 @@ grokdeclarator (const cp_declarator *declarator,
            && pedantic)
          {
            if (storage_class == sc_static)
-             pedwarn ("%<static%> specified invalid for function %qs "
+             pedwarn (OPT_pedantic, 
+                      "%<static%> specified invalid for function %qs "
                       "declared out of global scope", name);
            else
-             pedwarn ("%<inline%> specifier invalid for function %qs "
+             pedwarn (OPT_pedantic, 
+                      "%<inline%> specifier invalid for function %qs "
                       "declared out of global scope", name);
          }
 
@@ -8568,8 +9203,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)
@@ -8605,8 +9240,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;
              }
@@ -8617,14 +9252,30 @@ grokdeclarator (const cp_declarator *declarator,
              }
            if (storage_class == sc_extern && pedantic)
              {
-               pedwarn ("cannot explicitly declare member %q#D to have "
-                        "extern linkage",
-                        decl);
+               pedwarn (OPT_pedantic, 
+                        "cannot explicitly declare member %q#D to have "
+                        "extern linkage", decl);
                storage_class = sc_none;
              }
          }
       }
 
+    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);
+           return error_mark_node;
+         }
+      }
+
     /* Record `register' declaration for warnings on &
        and in case doing stupid register allocation.  */
 
@@ -8635,12 +9286,15 @@ 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);
 
+    if (set_no_warning)
+        TREE_NO_WARNING (decl) = 1;
+
     return decl;
   }
 }
@@ -8672,7 +9326,7 @@ require_complete_types_for_parms (tree parms)
 /* Returns nonzero if T is a local variable.  */
 
 int
-local_variable_p (tree t)
+local_variable_p (const_tree t)
 {
   if ((TREE_CODE (t) == VAR_DECL
        /* A VAR_DECL with a context that is a _TYPE is a static data
@@ -8686,18 +9340,6 @@ local_variable_p (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 (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.  */
 
@@ -8771,8 +9413,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);
@@ -8800,6 +9441,7 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
   int ellipsis = !first_parm || first_parm->ellipsis_p;
   cp_parameter_declarator *parm;
   int any_error = 0;
+  struct pointer_set_t *unique_decls = pointer_set_create ();
 
   for (parm = first_parm; parm != NULL; parm = parm->next)
     {
@@ -8837,6 +9479,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
@@ -8879,6 +9531,19 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
            init = check_default_argument (decl, init);
        }
 
+      if (TREE_CODE (decl) == PARM_DECL
+          && FUNCTION_PARAMETER_PACK_P (decl)
+          && parm->next)
+        error ("parameter packs must be at the end of the parameter list");
+
+      if (DECL_NAME (decl))
+        {
+          if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
+            error ("multiple parameters named %qE", DECL_NAME (decl));
+          else
+            pointer_set_insert (unique_decls, DECL_NAME (decl));
+        }
+
       TREE_CHAIN (decl) = decls;
       decls = decl;
       result = tree_cons (init, type, result);
@@ -8889,6 +9554,7 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
     result = chainon (result, void_list_node);
   *parms = decls;
 
+  pointer_set_destroy (unique_decls);
   return result;
 }
 
@@ -8912,7 +9578,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;
@@ -8943,6 +9609,7 @@ copy_fn_p (tree d)
       result = -1;
     }
   else if (TREE_CODE (arg_type) == REFERENCE_TYPE
+          && !TYPE_REF_IS_RVALUE (arg_type)
           && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
     {
       if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
@@ -8960,9 +9627,61 @@ copy_fn_p (tree d)
   return result;
 }
 
+/* D is a constructor or overloaded `operator='.
+
+   Let T be the class in which D is declared. Then, this function
+   returns true when D is a move constructor or move assignment
+   operator, false otherwise.  */
+
+bool
+move_fn_p (const_tree d)
+{
+  tree args;
+  tree arg_type;
+  bool result = false;
+
+  gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+
+  if (cxx_dialect == cxx98)
+    /* There are no move constructors if we are in C++98 mode.  */
+    return false;
+
+  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
+       accept those as copy functions.  */
+    return 0;
+
+  args = FUNCTION_FIRST_USER_PARMTYPE (d);
+  if (!args)
+    return 0;
+
+  arg_type = TREE_VALUE (args);
+  if (arg_type == error_mark_node)
+    return 0;
+
+  if (TREE_CODE (arg_type) == REFERENCE_TYPE
+      && TYPE_REF_IS_RVALUE (arg_type)
+      && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)),
+                      DECL_CONTEXT (d)))
+    result = true;
+
+  args = TREE_CHAIN (args);
+
+  if (args && args != void_list_node && !TREE_PURPOSE (args))
+    /* There are more non-optional args.  */
+    return false;
+
+  return result;
+}
+
 /* 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;
 
@@ -8974,7 +9693,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)
        {
@@ -8986,11 +9706,15 @@ void grok_special_member_properties (tree decl)
             are no other parameters or else all other parameters have
             default arguments.  */
          TYPE_HAS_INIT_REF (class_type) = 1;
+         if (!DECL_DEFAULTED_FN (decl))
+           TYPE_HAS_COMPLEX_INIT_REF (class_type) = 1;
          if (ctor > 1)
            TYPE_HAS_CONST_INIT_REF (class_type) = 1;
        }
       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)
     {
@@ -9005,6 +9729,8 @@ void grok_special_member_properties (tree decl)
       if (assop)
        {
          TYPE_HAS_ASSIGN_REF (class_type) = 1;
+         if (!DECL_DEFAULTED_FN (decl))
+           TYPE_HAS_COMPLEX_ASSIGN_REF (class_type) = 1;
          if (assop != 1)
            TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
        }
@@ -9015,7 +9741,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);
 
@@ -9118,7 +9844,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)
@@ -9170,7 +9896,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
@@ -9206,10 +9935,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;
                }
 
@@ -9250,7 +9980,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";
@@ -9418,8 +10148,8 @@ grok_op_properties (tree decl, bool complain)
            if (operator_code == POSTINCREMENT_EXPR
                || operator_code == POSTDECREMENT_EXPR)
              {
-               if (pedantic)
-                 pedwarn ("%qD cannot have default arguments", decl);
+               pedwarn (OPT_pedantic, "%qD cannot have default arguments", 
+                        decl);
              }
            else
              {
@@ -9603,6 +10333,12 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
                                           | DECL_SELF_REFERENCE_P (decl));
       return t;
     }
+  else if (decl && TREE_CODE (decl) == TREE_LIST)
+    {
+      error ("reference to %qD is ambiguous", name);
+      print_candidates (decl);
+      return error_mark_node;
+    }
   else
     return NULL_TREE;
 }
@@ -9718,14 +10454,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);
@@ -9778,7 +10514,7 @@ xref_tag_from_type (tree old, tree id, tag_scope scope)
    access_* node, and the TREE_VALUE is the type of the base-class.
    Non-NULL TREE_TYPE indicates virtual inheritance.  
  
-   Returns true if the binfo heirarchy was successfully created,
+   Returns true if the binfo hierarchy was successfully created,
    false if an error was detected. */
 
 bool
@@ -9880,12 +10616,11 @@ xref_basetypes (tree ref, tree base_list)
       if (access == access_default_node)
        access = default_access;
 
+      if (PACK_EXPANSION_P (basetype))
+        basetype = PACK_EXPANSION_PATTERN (basetype);
       if (TREE_CODE (basetype) == TYPE_DECL)
        basetype = TREE_TYPE (basetype);
-      if (TREE_CODE (basetype) != RECORD_TYPE
-         && TREE_CODE (basetype) != TYPENAME_TYPE
-         && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
-         && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
+      if (!MAYBE_CLASS_TYPE_P (basetype) || TREE_CODE (basetype) == UNION_TYPE)
        {
          error ("base type %qT fails to be a struct or class type",
                 basetype);
@@ -9925,6 +10660,11 @@ xref_basetypes (tree ref, tree base_list)
            error ("duplicate base type %qT invalid", basetype);
          return false;
        }
+
+      if (PACK_EXPANSION_P (TREE_VALUE (base_list)))
+        /* Regenerate the pack expansion for the bases. */
+        basetype = make_pack_expansion (basetype);
+
       TYPE_MARKED_P (basetype) = 1;
 
       base_binfo = copy_binfo (base_binfo, basetype, ref,
@@ -10140,7 +10880,7 @@ finish_enum (tree enumtype)
       underlying_type = integer_types[itk_unsigned_long_long];
     }
 
-  /* Compute the minium and maximum values for the type.
+  /* Compute the minimum and maximum values for the type.
 
      [dcl.enum]
 
@@ -10181,7 +10921,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.  */
@@ -10245,7 +10986,7 @@ build_enumerator (tree name, tree value, tree enumtype)
            }
          else
            {
-             error ("enumerator value for %qD not integer constant", name);
+             error ("enumerator value for %qD is not an integer constant", name);
              value = NULL_TREE;
            }
        }
@@ -10314,7 +11055,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;
 
@@ -10344,11 +11084,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)
@@ -10381,7 +11125,13 @@ check_function_type (tree decl, tree current_function_parms)
    For C++, we must first check whether that datum makes any sense.
    For example, "class A local_a(1,2);" means that variable local_a
    is an aggregate of type A, which should have a constructor
-   applied to it with the argument list [1, 2].  */
+   applied to it with the argument list [1, 2].
+
+   On entry, DECL_INITIAL (decl1) should be NULL_TREE or error_mark_node,
+   or may be a BLOCK if the function has been defined previously
+   in this translation unit.  On exit, DECL_INITIAL (decl1) will be
+   error_mark_node if the function has never been defined, or
+   a BLOCK if the function has been defined somewhere.  */
 
 void
 start_preparsed_function (tree decl1, tree attrs, int flags)
@@ -10423,6 +11173,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
@@ -10495,9 +11254,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   /* Build the return declaration for the function.  */
   restype = TREE_TYPE (fntype);
-  /* Promote the value to int before returning it.  */
-  if (c_promoting_integer_type_p (restype))
-    restype = type_promotes_to (restype);
   if (DECL_RESULT (decl1) == NULL_TREE)
     {
       tree resdecl;
@@ -10510,24 +11266,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
     }
 
-  /* Initialize RTL machinery.  We cannot do this until
-     CURRENT_FUNCTION_DECL and DECL_RESULT are set up.  We do this
-     even when processing a template; this is how we get
-     CFUN set up, and our per-function variables initialized.
-     FIXME factor out the non-RTL stuff.  */
-  bl = current_binding_level;
-  allocate_struct_function (decl1);
-  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;
-
-  /* Start the statement-tree, start the tree now.  */
-  DECL_SAVED_TREE (decl1) = push_stmt_list ();
-
   /* Let the user know we're compiling this function.  */
   announce_function (decl1);
 
@@ -10549,9 +11287,36 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
               parsing the body of the function.  */
            ;
          else
-           /* Otherwise, OLDDECL is either a previous declaration of
-              the same function or DECL1 itself.  */
-           decl1 = olddecl;
+           {
+             /* Otherwise, OLDDECL is either a previous declaration
+                of the same function or DECL1 itself.  */
+
+             if (warn_missing_declarations
+                 && olddecl == decl1
+                 && !DECL_MAIN_P (decl1)
+                 && TREE_PUBLIC (decl1)
+                 && !DECL_DECLARED_INLINE_P (decl1))
+               {
+                 tree context;
+
+                 /* Check whether DECL1 is in an anonymous
+                    namespace.  */
+                 for (context = DECL_CONTEXT (decl1);
+                      context;
+                      context = DECL_CONTEXT (context))
+                   {
+                     if (TREE_CODE (context) == NAMESPACE_DECL
+                         && DECL_NAME (context) == NULL_TREE)
+                       break;
+                   }
+
+                 if (context == NULL)
+                   warning (OPT_Wmissing_declarations,
+                            "no previous declaration for %q+D", decl1);
+               }
+
+             decl1 = olddecl;
+           }
        }
       else
        {
@@ -10573,9 +11338,38 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        maybe_apply_pragma_weak (decl1);
     }
 
-  /* Reset these in case the call to pushdecl changed them.  */
+  /* Reset this in case the call to pushdecl changed it.  */
   current_function_decl = decl1;
-  cfun->decl = decl1;
+
+  gcc_assert (DECL_INITIAL (decl1));
+
+  /* This function may already have been parsed, in which case just
+     return; our caller will skip over the body without parsing.  */
+  if (DECL_INITIAL (decl1) != error_mark_node)
+    return;
+
+  /* Initialize RTL machinery.  We cannot do this until
+     CURRENT_FUNCTION_DECL and DECL_RESULT are set up.  We do this
+     even when processing a template; this is how we get
+     CFUN set up, and our per-function variables initialized.
+     FIXME factor out the non-RTL stuff.  */
+  bl = current_binding_level;
+  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->dont_save_pending_sizes_p = 1;
+
+  /* Start the statement-tree, start the tree now.  */
+  DECL_SAVED_TREE (decl1) = push_stmt_list ();
 
   /* If we are (erroneously) defining a function that we have already
      defined before, wipe out what we knew before.  */
@@ -10594,7 +11388,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
@@ -10656,7 +11450,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        DECL_EXTERNAL (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
       /* If this function is in an interface implemented in this file,
-        make sure that the backend knows to emit this function
+        make sure that the back end knows to emit this function
         here.  */
       if (!DECL_EXTERNAL (decl1))
        mark_needed (decl1);
@@ -10678,8 +11472,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))
@@ -10879,7 +11674,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));
@@ -11034,7 +11830,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));
@@ -11084,6 +11880,10 @@ finish_function (int flags)
       which then got a warning when stored in a ptr-to-function variable.  */
 
   gcc_assert (building_stmt_tree ());
+  /* The current function is being defined, so its DECL_INITIAL should
+     be set, and unless there's a multiple definition, it should be
+     error_mark_node.  */
+  gcc_assert (DECL_INITIAL (fndecl) == error_mark_node);
 
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
@@ -11103,11 +11903,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))
@@ -11125,7 +11924,7 @@ finish_function (int flags)
   if (!processing_template_decl
       && !cp_function_chain->can_throw
       && !flag_non_call_exceptions
-      && targetm.binds_local_p (fndecl))
+      && !DECL_REPLACEABLE_P (fndecl))
     TREE_NOTHROW (fndecl) = 1;
 
   /* This must come after expand_function_end because cleanups might
@@ -11159,7 +11958,7 @@ finish_function (int flags)
   gcc_assert (stmts_are_full_exprs_p ());
 
   /* Set up the named return value optimization, if we can.  Candidate
-     variables are selected in check_return_value.  */
+     variables are selected in check_return_expr.  */
   if (current_function_return_value)
     {
       tree r = current_function_return_value;
@@ -11203,13 +12002,15 @@ finish_function (int flags)
       /* Don't complain if we abort or throw.  */
       && !current_function_returns_abnormally
       && !DECL_NAME (DECL_RESULT (fndecl))
-      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
-        inline function, as we might never be compiled separately.  */
-      && (DECL_INLINE (fndecl) || processing_template_decl)
+      && !TREE_NO_WARNING (fndecl)
       /* Structor return values (if any) are set by the compiler.  */
       && !DECL_CONSTRUCTOR_P (fndecl)
       && !DECL_DESTRUCTOR_P (fndecl))
-    warning (OPT_Wreturn_type, "no return statement in function returning non-void");
+    {
+      warning (OPT_Wreturn_type,
+              "no return statement in function returning non-void");
+      TREE_NO_WARNING (fndecl) = 1;
+    }
 
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
@@ -11231,14 +12032,14 @@ finish_function (int flags)
       f->extern_decl_map = NULL;
 
       /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
-      c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+      c_warn_unused_result (gimple_body (fndecl));
     }
   /* Clear out the bits we don't need.  */
   local_names = NULL;
 
   /* 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
@@ -11320,8 +12121,6 @@ start_method (cp_decl_specifier_seq *declspecs,
   check_template_shadow (fndecl);
 
   DECL_DECLARED_INLINE_P (fndecl) = 1;
-  if (flag_default_inline)
-    DECL_INLINE (fndecl) = 1;
 
   /* We process method specializations in finish_struct_1.  */
   if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
@@ -11437,7 +12236,7 @@ maybe_register_incomplete_var (tree var)
 }
 
 /* Called when a class type (given by TYPE) is defined.  If there are
-   any existing VAR_DECLs whose type hsa been completed by this
+   any existing VAR_DECLs whose type has been completed by this
    declaration, update them now.  */
 
 void
@@ -11467,39 +12266,78 @@ complete_vars (tree type)
   complete_type_check_abstract (type);
 }
 
-/* If DECL is of a type which needs a cleanup, build that cleanup
-   here.  */
+/* If DECL is of a type which needs a cleanup, build and return an
+   expression to perform that cleanup here.  Return NULL_TREE if no
+   cleanup need be done.  */
 
 tree
 cxx_maybe_build_cleanup (tree decl)
 {
-  tree type = TREE_TYPE (decl);
+  tree type;
+  tree attr;
+  tree cleanup;
+
+  /* Assume no cleanup is required.  */
+  cleanup = NULL_TREE;
 
-  if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (error_operand_p (decl))
+    return cleanup;
+
+  /* Handle "__attribute__((cleanup))".  We run the cleanup function
+     before the destructor since the destructor is what actually
+     terminates the lifetime of the object.  */
+  attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+  if (attr)
+    {
+      tree id;
+      tree fn;
+      tree arg;
+
+      /* Get the name specified by the user for the cleanup function.  */
+      id = TREE_VALUE (TREE_VALUE (attr));
+      /* Look up the name to find the cleanup function to call.  It is
+        important to use lookup_name here because that is what is
+        used in c-common.c:handle_cleanup_attribute when performing
+        initial checks on the attribute.  Note that those checks
+        include ensuring that the function found is not an overloaded
+        function, or an object with an overloaded call operator,
+        etc.; we can rely on the fact that the function found is an
+        ordinary FUNCTION_DECL.  */
+      fn = lookup_name (id);
+      arg = build_address (decl);
+      mark_used (decl);
+      cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
+                                                            arg),
+                                       tf_warning_or_error);
+    }
+  /* Handle ordinary C++ destructors.  */
+  type = TREE_TYPE (decl);
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
-      tree rval;
       bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
                         && CLASSTYPE_VBASECLASSES (type));
+      tree addr;
+      tree call;
 
       if (TREE_CODE (type) == ARRAY_TYPE)
-       rval = decl;
+       addr = decl;
       else
-       {
-         cxx_mark_addressable (decl);
-         rval = build_unary_op (ADDR_EXPR, decl, 0);
-       }
+       addr = build_address (decl);
 
       /* Optimize for space over speed here.  */
       if (!has_vbases || flag_expensive_optimizations)
        flags |= LOOKUP_NONVIRTUAL;
 
-      rval = build_delete (TREE_TYPE (rval), rval,
+      call = build_delete (TREE_TYPE (addr), addr,
                           sfk_complete_destructor, flags, 0);
-
-      return rval;
+      if (cleanup)
+       cleanup = build_compound_expr (cleanup, call);
+      else
+       cleanup = call;
     }
-  return NULL_TREE;
+
+  return cleanup;
 }
 \f
 /* When a stmt has been parsed, this function is called.  */
@@ -11534,47 +12372,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.  */
 
@@ -11587,9 +12384,11 @@ 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;
+    case ARGUMENT_PACK_SELECT:  return TS_CP_ARGUMENT_PACK_SELECT;
+    case TRAIT_EXPR:           return TS_CP_TRAIT_EXPR;
     default:                   return TS_CP_GENERIC;
     }
 }