OSDN Git Service

/cp
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 271b8e6..b053160 100644 (file)
@@ -1,6 +1,7 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -314,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)
@@ -356,12 +357,7 @@ pop_label (tree label, tree old_value)
          location_t location;
 
          error ("label %q+D used but not defined", label);
-#ifdef USE_MAPPED_LOCATION
          location = input_location; /* FIXME want (input_filename, (line)0) */
-#else
-         location.file = input_filename;
-         location.line = 0;
-#endif
          /* Avoid crashing later.  */
          define_label (location, DECL_NAME (label));
        }
@@ -587,7 +583,7 @@ poplevel (int keep, int reverse, int functionbody)
 
   /* In each subblock, record that this is its superior.  */
   if (keep >= 0)
-    for (link = subblocks; link; link = TREE_CHAIN (link))
+    for (link = subblocks; link; link = BLOCK_CHAIN (link))
       BLOCK_SUPERCONTEXT (link) = block;
 
   /* We still support the old for-scope rules, whereby the variables
@@ -804,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);
@@ -831,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);
@@ -1059,8 +1055,8 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
     return;
 
   name = DECL_ASSEMBLER_NAME (newdecl);
-  pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
-  pedwarn ("previous declaration of %q+D", olddecl);
+  permerror ("%qD was declared %<extern%> and later %<static%>", newdecl);
+  permerror ("previous declaration of %q+D", olddecl);
 }
 
 /* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
@@ -1543,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
                  {
@@ -1555,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);
-           }
        }
     }
 
@@ -1617,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.  */
@@ -1658,15 +1652,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
              && DECL_INITIAL (new_result))
            {
              if (DECL_INITIAL (old_result))
-               {
-                 DECL_INLINE (old_result) = 0;
-                 DECL_UNINLINABLE (old_result) = 1;
-               }
+               DECL_UNINLINABLE (old_result) = 1;
              else
-               {
-                 DECL_INLINE (old_result) = DECL_INLINE (new_result);
-                 DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
-               }
+               DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
              DECL_EXTERNAL (old_result) = DECL_EXTERNAL (new_result);
              DECL_NOT_REALLY_EXTERN (old_result)
                = DECL_NOT_REALLY_EXTERN (new_result);
@@ -1674,13 +1662,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
                = DECL_INTERFACE_KNOWN (new_result);
              DECL_DECLARED_INLINE_P (old_result)
                = DECL_DECLARED_INLINE_P (new_result);
+             DECL_DISREGARD_INLINE_LIMITS (old_result)
+               |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+
            }
          else
            {
-             DECL_INLINE (old_result)
-               |= DECL_INLINE (new_result);
              DECL_DECLARED_INLINE_P (old_result)
                |= DECL_DECLARED_INLINE_P (new_result);
+             DECL_DISREGARD_INLINE_LIMITS (old_result)
+               |= DECL_DISREGARD_INLINE_LIMITS (new_result);
              check_redeclaration_exception_specification (newdecl, olddecl);
            }
        }
@@ -1801,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);
        }
@@ -1846,24 +1840,24 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   new_template = NULL_TREE;
   if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
     {
-      bool old_decl_gnu_inline;
+      bool new_redefines_gnu_inline = false;
 
-      if ((DECL_INTERFACE_KNOWN (olddecl)
-          && TREE_CODE (olddecl) == FUNCTION_DECL)
-         || (TREE_CODE (olddecl) == TEMPLATE_DECL
-             && TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL))
+      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);
 
-         old_decl_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
+         new_redefines_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
        }
-      else
-       old_decl_gnu_inline = false;
 
-      if (!old_decl_gnu_inline)
+      if (!new_redefines_gnu_inline)
        {
          DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
          DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
@@ -1944,9 +1938,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        }
       else if (new_defines_function && DECL_INITIAL (olddecl))
        {
-         /* C++ is always in in unit-at-a-time mode, so we never
-            inline re-defined extern inline functions.  */
-         DECL_INLINE (newdecl) = 0;
+         /* 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
@@ -1956,12 +1950,6 @@ 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));
 
@@ -2053,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;
@@ -2454,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
@@ -2500,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)
@@ -2596,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;
     }
 
@@ -2615,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)
@@ -2636,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");
@@ -2689,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)
     {
@@ -2889,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;
@@ -2977,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);
@@ -3054,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))
@@ -3082,7 +3076,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
     }
 
   /* Build the UNBOUND_CLASS_TEMPLATE.  */
-  t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+  t = cxx_make_type (UNBOUND_CLASS_TEMPLATE);
   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
   TREE_TYPE (t) = NULL_TREE;
   SET_TYPE_STRUCTURAL_EQUALITY (t);
@@ -3340,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.) */
@@ -3380,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);
@@ -3584,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);
@@ -3623,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;
 }
@@ -3653,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
@@ -3662,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;
@@ -3684,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;
@@ -3704,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).
@@ -3757,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
@@ -3800,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
@@ -3897,31 +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)
+  if (attrs && type != error_mark_node)
     {
       if (CLASS_TYPE_P (type))
-       warning (OPT_Wattributes, "ignoring attributes applied to class type "
-                "outside of definition");
+       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,
@@ -3932,9 +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;
 
@@ -3974,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;
@@ -3996,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,
@@ -4030,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
@@ -4086,18 +4112,18 @@ start_decl (const cp_declarator *declarator,
        }
 
       if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
-       pedwarn ("declaration of %q#D outside of class is not definition",
-                decl);
+       permerror ("declaration of %q#D outside of class is not definition",
+                  decl);
     }
 
   was_public = TREE_PUBLIC (decl);
 
   /* Enter this declaration into the symbol table.  */
-  tem = maybe_push_decl (decl);
+  decl = maybe_push_decl (decl);
 
   if (processing_template_decl)
-    tem = push_template_decl (tem);
-  if (tem == error_mark_node)
+    decl = push_template_decl (decl);
+  if (decl == error_mark_node)
     return error_mark_node;
 
   /* Tell the back end to use or not use .common as appropriate.  If we say
@@ -4106,33 +4132,42 @@ start_decl (const cp_declarator *declarator,
      produce errors about redefs; to do this we force variables into the
      data segment.  */
   if (flag_conserve_space
-      && TREE_CODE (tem) == VAR_DECL
-      && TREE_PUBLIC (tem)
-      && !DECL_THREAD_LOCAL_P (tem)
+      && TREE_CODE (decl) == VAR_DECL
+      && TREE_PUBLIC (decl)
+      && !DECL_THREAD_LOCAL_P (decl)
       && !have_global_bss_p ())
-    DECL_COMMON (tem) = 1;
+    DECL_COMMON (decl) = 1;
 
-  if (TREE_CODE (tem) == VAR_DECL
-      && DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
-      && !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
+  if (TREE_CODE (decl) == VAR_DECL
+      && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
+      && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
     {
       /* This is a const variable with implicit 'static'.  Set
         DECL_THIS_STATIC so we can tell it from variables that are
         !TREE_PUBLIC because of the anonymous namespace.  */
-      gcc_assert (cp_type_readonly (TREE_TYPE (tem)));
-      DECL_THIS_STATIC (tem) = 1;
+      gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+      DECL_THIS_STATIC (decl) = 1;
     }
 
-  if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
-    start_decl_1 (tem, initialized);
+  if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+    start_decl_1 (decl, initialized);
 
-  return tem;
+  return decl;
 }
 
+/* Process the declaration of a variable DECL.  INITIALIZED is true
+   iff DECL is explicitly initialized.  (INITIALIZED is false if the
+   variable is initialized via an implicitly-called constructor.)
+   This function must be called for ordinary variables (including, for
+   example, implicit instantiations of templates), but must not be
+   called for template declarations.  */
+
 void
 start_decl_1 (tree decl, bool initialized)
 {
   tree type;
+  bool complete_p;
+  bool aggregate_definition_p;
 
   gcc_assert (!processing_template_decl);
 
@@ -4140,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))))
@@ -4162,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.
@@ -4261,6 +4297,39 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
   return NULL_TREE;
 }
 
+/* Subroutine of check_initializer.  We're initializing a DECL of
+   std::initializer_list<T> TYPE from a braced-init-list INIT, and need to
+   extend the lifetime of the underlying array to match that of the decl,
+   just like for reference initialization.  CLEANUP is as for
+   grok_reference_init.  */
+
+static tree
+build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+{
+  tree aggr_init, array, arrtype;
+  init = perform_implicit_conversion (type, init, tf_warning_or_error);
+  aggr_init = TARGET_EXPR_INITIAL (init);
+  init = build2 (INIT_EXPR, type, decl, init);
+
+  array = AGGR_INIT_EXPR_ARG (aggr_init, 1);
+  arrtype = TREE_TYPE (array);
+  STRIP_NOPS (array);
+  gcc_assert (TREE_CODE (array) == ADDR_EXPR);
+  array = TREE_OPERAND (array, 0);
+  /* If the array is constant, finish_compound_literal already made it a
+     static variable and we don't need to do anything here.  */
+  if (decl && TREE_CODE (array) == TARGET_EXPR)
+    {
+      tree subinit;
+      tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit);
+      var = build_address (var);
+      var = convert (arrtype, var);
+      AGGR_INIT_EXPR_ARG (aggr_init, 1) = var;
+      init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
+    }
+  return init;
+}
+
 /* Designated initializers in arrays are not supported in GNU C++.
    The parser cannot detect this error since it does not know whether
    a given brace-enclosed initializer is for a class type or for an
@@ -4275,7 +4344,7 @@ check_array_designated_initializer (const constructor_elt *ce)
   if (ce->index)
     {
       /* The parser only allows identifiers as designated
-        intializers.  */
+        initializers.  */
       gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
       error ("name %qD used in a GNU-style designated "
             "initializer for an array", ce->index);
@@ -4315,7 +4384,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
          HOST_WIDE_INT i;
          for (i = 0; 
               VEC_iterate (constructor_elt, v, i, ce);
-              ++i)
+              ++i) 
            if (!check_array_designated_initializer (ce))
              failure = 1;
        }
@@ -4395,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);
 
@@ -4410,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;
+       }
     }
 }
 
@@ -4536,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)
     {
@@ -4631,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)
@@ -4705,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++;
@@ -4857,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.
@@ -4880,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 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))
     {
@@ -4914,7 +5027,12 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
       int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
       if (SCALAR_TYPE_P (type))
        {
-         if (init_len != 1)
+         if (init_len == 0)
+           {
+             maybe_warn_cpp0x ("extended initializer lists");
+             init = build_zero_init (type, NULL_TREE, false);
+           }
+         else if (init_len != 1)
            {
              error ("scalar object %qD requires one element in initializer",
                     decl);
@@ -4922,15 +5040,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
              return NULL_TREE;
            }
        }
-      else if ((cxx_dialect == cxx98) && !CP_AGGREGATE_TYPE_P (type))
-       {
-         /* A non-aggregate that is not a scalar cannot be initialized
-            via an initializer-list in C++98.  */
-         error ("braces around initializer for non-aggregate type %qT",
-                type);
-         TREE_TYPE (decl) = error_mark_node;
-         return NULL_TREE;
-       }
     }
 
   if (TREE_CODE (decl) == CONST_DECL)
@@ -4948,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
@@ -4968,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 (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)
        {
-         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
-       {
-       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);
 
@@ -5086,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.  */
@@ -5130,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
@@ -5137,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);
@@ -5147,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);
 }
 
@@ -5201,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;
@@ -5306,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;
@@ -5355,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);
@@ -5396,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);
@@ -5410,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;
@@ -5480,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
@@ -5502,6 +5665,21 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       /* This needs to happen after the linkage is set. */
       determine_visibility (decl);
 
+      if (var_definition_p && TREE_STATIC (decl))
+       {
+         /* If a TREE_READONLY variable needs initialization
+            at runtime, it is no longer readonly and we need to
+            avoid MEM_READONLY_P being set on RTL created for it.  */
+         if (init)
+           {
+             if (TREE_READONLY (decl))
+               TREE_READONLY (decl) = 0;
+             was_readonly = 0;
+           }
+         else if (was_readonly)
+           TREE_READONLY (decl) = 1;
+       }
+
       make_rtl_for_nonlocal_decl (decl, init, asmspec);
 
       /* Check for abstractness of the type. Notice that there is no
@@ -5513,10 +5691,38 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       else
        abstract_virtuals_error (decl, type);
 
-      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)))
@@ -5524,40 +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))
-           {
-             /* If a TREE_READONLY variable needs initialization
-                at runtime, it is no longer readonly and we need to
-                avoid MEM_READONLY_P being set on RTL created for it.  */
-             if (init)
-               {
-                 if (TREE_READONLY (decl))
-                   TREE_READONLY (decl) = 0;
-                 was_readonly = 0;
-               }
-             expand_static_init (decl, init);
-           }
-       }
+      /* If a variable is defined, and then a subsequent
+        definition with external linkage is encountered, we will
+        get here twice for the same variable.  We want to avoid
+        calling expand_static_init more than once.  For variables
+        that are not static data members, we can call
+        expand_static_init only when we actually process the
+        initializer.  It is not legal to redeclare a static data
+        member, so this issue does not arise in that case.  */
+      else if (var_definition_p && TREE_STATIC (decl))
+       expand_static_init (decl, init);
     }
 
   /* If a CLEANUP_STMT was created to destroy a temporary bound to a
@@ -5761,8 +5948,6 @@ 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 (use_cxa_atexit)
@@ -5871,7 +6056,7 @@ register_dtor_fn (tree decl)
          addr = build_address (decl);
          /* The declared type of the parameter to "__cxa_atexit" is
             "void *".  For plain "T*", we could just let the
-            machinery in build_function_call convert it -- but if the
+            machinery in cp_build_function_call convert it -- but if the
             type is "cv-qualified T *", then we need to convert it
             before passing it in, to avoid spurious errors.  */
          addr = build_nop (ptr_type_node, addr);
@@ -5883,7 +6068,8 @@ register_dtor_fn (tree decl)
           other value.  */
        addr = null_pointer_node;
       args = tree_cons (NULL_TREE,
-                       build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
+                       cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+                                        tf_warning_or_error),
                        NULL_TREE);
       if (targetm.cxx.use_aeabi_atexit ())
        {
@@ -5898,7 +6084,8 @@ register_dtor_fn (tree decl)
     }
   else
     args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
-  return build_function_call (get_atexit_node (), args);
+  return cp_build_function_call (get_atexit_node (), args, 
+                                tf_warning_or_error);
 }
 
 /* DECL is a VAR_DECL with static storage duration.  INIT, if present,
@@ -5984,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
            {
@@ -6056,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.
 
@@ -6072,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);
@@ -6174,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
@@ -6408,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);
        }
     }
 
@@ -6431,11 +6634,6 @@ 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)
@@ -6494,7 +6692,8 @@ grokfndecl (tree ctype,
          newtype = build_function_type (integer_type_node, oldtypeargs);
          TREE_TYPE (decl) = newtype;
        }
-      check_main_parameter_types (decl);
+      if (warn_main)
+       check_main_parameter_types (decl);
     }
 
   if (ctype != NULL_TREE
@@ -6528,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.  */
@@ -6729,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...  */
   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;
@@ -6760,16 +6962,17 @@ 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);
 
-  /* Managing canonical types for the RECORD_TYPE behind a
-     pointer-to-member function is a nightmare, so use structural
-     equality for now.  */
-  SET_TYPE_STRUCTURAL_EQUALITY (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;
 }
@@ -6829,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;
@@ -6875,7 +7078,7 @@ compute_array_index_type (tree name, tree size)
   
   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 effects the manglings
+       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"
@@ -6894,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))
@@ -6912,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))
@@ -6933,9 +7131,9 @@ compute_array_index_type (tree name, tree size)
   else if (pedantic && warn_vla != 0)
     {
       if (name)
-       pedwarn ("ISO C++ forbids variable length array %qD", name);
+       pedwarn (OPT_Wvla, "ISO C++ forbids variable length array %qD", name);
       else
-       pedwarn ("ISO C++ forbids variable length array");
+       pedwarn (OPT_Wvla, "ISO C++ forbids variable length array");
     }
   else if (warn_vla > 0)
     {
@@ -6962,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;
 
@@ -7191,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
@@ -7289,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;
@@ -7490,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)
@@ -7506,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.  */
@@ -7552,8 +7764,11 @@ 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 (! 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);
@@ -7596,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;
@@ -7706,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;
@@ -7759,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;
     }
 
@@ -7780,15 +8004,10 @@ grokdeclarator (const cp_declarator *declarator,
       error ("multiple storage classes in declaration of %qs", name);
       thread_p = false;
     }
-  if (declspecs->conflicting_specifiers_p)
-    {
-      error ("conflicting specifiers in declaration of %qs", name);
-      storage_class = sc_none;
-    }
-  else if (decl_context != NORMAL
-          && ((storage_class != sc_none
-               && storage_class != sc_mutable)
-              || thread_p))
+  if (decl_context != NORMAL
+      && ((storage_class != sc_none
+          && storage_class != sc_mutable)
+         || thread_p))
     {
       if ((decl_context == PARM || decl_context == CATCHPARM)
          && (storage_class == sc_register
@@ -7820,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);
@@ -7851,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;
@@ -7924,7 +8134,7 @@ grokdeclarator (const cp_declarator *declarator,
            if (type_quals != TYPE_UNQUALIFIED)
              {
                if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
-                 warning (OPT_Wreturn_type,
+                 warning (OPT_Wignored_qualifiers,
                           "type qualifiers ignored on function return type");
                /* We now know that the TYPE_QUALS don't apply to the
                   decl, but to its return type.  */
@@ -7932,17 +8142,17 @@ grokdeclarator (const cp_declarator *declarator,
                set_no_warning = true;
              }
 
-           /* Warn about some types functions can't return.  */
+           /* Error about some types functions can't return.  */
 
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
                error ("%qs declared as function returning a function", name);
-               type = integer_type_node;
+               return error_mark_node;
              }
            if (TREE_CODE (type) == ARRAY_TYPE)
              {
                error ("%qs declared as function returning an array", name);
-               type = integer_type_node;
+               return error_mark_node;
              }
 
            /* Pick up type qualifiers which should be applied to `this'.  */
@@ -8001,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
@@ -8086,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,
@@ -8223,12 +8434,13 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (friendp)
            {
-             pedwarn ("member functions are implicitly friends of their class");
+             permerror ("member functions are implicitly friends of their class");
              friendp = 0;
            }
          else
-           pedwarn ("extra qualification %<%T::%> on member %qs",
-                    ctype, name);
+           permerror_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.  */
@@ -8412,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.
@@ -8425,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);
@@ -8539,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.  */
@@ -8723,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) ?
@@ -8757,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;
              }
          }
@@ -8825,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)
@@ -8866,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;
                  }
 
@@ -8948,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);
          }
 
@@ -8990,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)
@@ -9027,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;
              }
@@ -9039,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.  */
 
@@ -9057,9 +9286,9 @@ grokdeclarator (const cp_declarator *declarator,
     else if (storage_class == sc_static)
       DECL_THIS_STATIC (decl) = 1;
 
-    /* Record constancy and volatility.  There's no need to do this
-       when processing a template; we'll do this for the instantiated
-       declaration based on the type of DECL.  */
+    /* Record constancy and volatility on the DECL itself .  There's
+       no need to do this when processing a template; we'll do this
+       for the instantiated declaration based on the type of DECL.  */
     if (!processing_template_decl)
       cp_apply_type_quals_to_decl (type_quals, decl);
 
@@ -9250,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
@@ -9441,7 +9680,8 @@ move_fn_p (const_tree d)
 
 /* Remember any special properties of member function DECL.  */
 
-void grok_special_member_properties (tree decl)
+void
+grok_special_member_properties (tree decl)
 {
   tree class_type;
 
@@ -9453,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)
        {
@@ -9465,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)
     {
@@ -9484,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;
        }
@@ -9597,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)
@@ -9649,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
@@ -9685,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;
                }
 
@@ -9729,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";
@@ -9897,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
              {
@@ -10203,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);
@@ -10369,10 +10620,7 @@ xref_basetypes (tree ref, tree base_list)
         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);
@@ -10632,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]
 
@@ -10673,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.  */
@@ -10806,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;
 
@@ -10836,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)
@@ -11102,14 +11354,19 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
      CFUN set up, and our per-function variables initialized.
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
-  allocate_struct_function (decl1);
+  allocate_struct_function (decl1, processing_template_decl);
+
+  /* Initialize the language data structures.  Whenever we start
+     a new function, we destroy temporaries in the usual way.  */
+  cfun->language = GGC_CNEW (struct language_function);
+  current_stmt_tree ()->stmts_are_full_exprs_p = 1;
   current_binding_level = bl;
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
-  cfun->x_dont_save_pending_sizes_p = 1;
+  cfun->dont_save_pending_sizes_p = 1;
 
   /* Start the statement-tree, start the tree now.  */
   DECL_SAVED_TREE (decl1) = push_stmt_list ();
@@ -11131,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
@@ -11417,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));
@@ -11572,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));
@@ -11645,14 +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
          {
            location_t linezero = linemap_line_start (line_table, 0, 1);
            SET_EXPR_LOCATION (stmt, linezero);
          }
-#else
-         annotate_with_file_line (stmt, input_filename, 0);
-#endif
        }
 
       if (use_eh_spec_block (current_function_decl))
@@ -11748,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.  */
@@ -11776,7 +12032,7 @@ 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;
@@ -11865,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))
@@ -11982,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
@@ -12047,13 +12301,14 @@ cxx_maybe_build_cleanup (tree decl)
         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 functionfound is an
+        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 = build_function_call (fn, build_tree_list (NULL_TREE,
-                                                         arg));
+      cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
+                                                            arg),
+                                       tf_warning_or_error);
     }
   /* Handle ordinary C++ destructors.  */
   type = TREE_TYPE (decl);
@@ -12068,10 +12323,7 @@ cxx_maybe_build_cleanup (tree decl)
       if (TREE_CODE (type) == ARRAY_TYPE)
        addr = decl;
       else
-       {
-         cxx_mark_addressable (decl);
-         addr = build_unary_op (ADDR_EXPR, decl, 0);
-       }
+       addr = build_address (decl);
 
       /* Optimize for space over speed here.  */
       if (!has_vbases || flag_expensive_optimizations)
@@ -12120,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.  */