OSDN Git Service

2010-08-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index c2c2a89..10600c8 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -34,36 +34,31 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "tree.h"
 #include "tree-inline.h"
-#include "rtl.h"
 #include "flags.h"
 #include "function.h"
 #include "output.h"
-#include "expr.h"
 #include "c-tree.h"
 #include "toplev.h"
-#include "ggc.h"
 #include "tm_p.h"
 #include "cpplib.h"
 #include "target.h"
 #include "debug.h"
 #include "opts.h"
 #include "timevar.h"
-#include "c-common.h"
-#include "c-pragma.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
 #include "langhooks.h"
 #include "tree-mudflap.h"
-#include "gimple.h"
 #include "tree-iterator.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
 #include "tree-dump.h"
 #include "cgraph.h"
 #include "hashtab.h"
-#include "libfuncs.h"
-#include "except.h"
 #include "langhooks-def.h"
 #include "pointer-set.h"
-#include "gimple.h"
 #include "plugin.h"
+#include "c-family/c-ada-spec.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -91,9 +86,6 @@ tree pending_invalid_xref;
 /* File and line to appear in the eventual error message.  */
 location_t pending_invalid_xref_location;
 
-/* True means we've initialized exception handling.  */
-bool c_eh_initialized_p;
-
 /* The file and line that the prototype came from if this is an
    old-style definition; used for diagnostics in
    store_parm_decls_oldstyle.  */
@@ -126,15 +118,6 @@ static GTY(()) struct stmt_tree_s c_stmt_tree;
 tree c_break_label;
 tree c_cont_label;
 
-/* True if we are currently parsing the fields of a struct or
-   union.  */
-
-static bool in_struct;
-
-/* A list of types defined in the current struct or union.  */
-
-static VEC(tree,heap) *struct_types;
-
 /* Linked list of TRANSLATION_UNIT_DECLS for the translation units
    included in this invocation.  Note that the current translation
    unit is not included in this list.  */
@@ -223,7 +206,7 @@ struct GTY((chain_next ("%h.prev"))) c_binding {
   BOOL_BITFIELD invisible : 1;  /* normal lookup should ignore this binding */
   BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
   BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
-  /* one free bit */
+  BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */
   location_t locus;            /* location for nested bindings */
 };
 #define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
@@ -513,6 +496,34 @@ static bool keep_next_level_flag;
 
 static bool next_is_function_body;
 
+/* A VEC of pointers to c_binding structures.  */
+
+typedef struct c_binding *c_binding_ptr;
+DEF_VEC_P(c_binding_ptr);
+DEF_VEC_ALLOC_P(c_binding_ptr,heap);
+
+/* Information that we keep for a struct or union while it is being
+   parsed.  */
+
+struct c_struct_parse_info
+{
+  /* If warn_cxx_compat, a list of types defined within this
+     struct.  */
+  VEC(tree,heap) *struct_types;
+  /* If warn_cxx_compat, a list of field names which have bindings,
+     and which are defined in this struct, but which are not defined
+     in any enclosing struct.  This is used to clear the in_struct
+     field of the c_bindings structure.  */
+  VEC(c_binding_ptr,heap) *fields;
+  /* If warn_cxx_compat, a list of typedef names used when defining
+     fields in this struct.  */
+  VEC(tree,heap) *typedefs_seen;
+};
+
+/* Information for the struct or union currently being parsed, or
+   NULL if not parsing a struct or union.  */
+static struct c_struct_parse_info *struct_parse_info;
+
 /* Forward declarations.  */
 static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (location_t, tree, int);
@@ -559,7 +570,7 @@ c_print_identifier (FILE *file, tree node, int indent)
     {
       tree rid = ridpointers[C_RID_CODE (node)];
       indent_to (file, indent + 4);
-      fprintf (file, "rid %p \"%s\"",
+      fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
               (void *) rid, IDENTIFIER_POINTER (rid));
     }
 }
@@ -579,7 +590,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
       binding_freelist = b->prev;
     }
   else
-    b = GGC_NEW (struct c_binding);
+    b = ggc_alloc_c_binding ();
 
   b->shadowed = 0;
   b->decl = decl;
@@ -588,6 +599,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
   b->invisible = invisible;
   b->nested = nested;
   b->inner_comp = 0;
+  b->in_struct = 0;
   b->locus = locus;
 
   b->u.type = NULL;
@@ -692,7 +704,7 @@ void
 record_inline_static (location_t loc, tree func, tree decl,
                      enum c_inline_static_type type)
 {
-  struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
+  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
   csi->location = loc;
   csi->function = func;
   csi->static_decl = decl;
@@ -916,7 +928,7 @@ push_scope (void)
          scope_freelist = scope->outer;
        }
       else
-       scope = GGC_CNEW (struct c_scope);
+       scope = ggc_alloc_cleared_c_scope ();
 
       /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
       if (current_scope)
@@ -987,9 +999,7 @@ update_label_decls (struct c_scope *scope)
 
              /* Update the bindings of any goto statements associated
                 with this label.  */
-             for (ix = 0;
-                  VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
-                  ++ix)
+             FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
                update_spot_bindings (scope, &g->goto_bindings);
            }
        }
@@ -1064,7 +1074,7 @@ pop_scope (void)
     {
       tree file_decl = build_decl (UNKNOWN_LOCATION,
                                   TRANSLATION_UNIT_DECL, 0, 0);
-      TREE_CHAIN (file_decl) = all_translation_units;
+      DECL_CHAIN (file_decl) = all_translation_units;
       all_translation_units = file_decl;
       context = file_decl;
     }
@@ -1084,11 +1094,11 @@ pop_scope (void)
              error ("label %q+D used but not defined", p);
              DECL_INITIAL (p) = error_mark_node;
            }
-         else 
+         else
            warn_for_unused_label (p);
 
          /* Labels go in BLOCK_VARS.  */
-         TREE_CHAIN (p) = BLOCK_VARS (block);
+         DECL_CHAIN (p) = BLOCK_VARS (block);
          BLOCK_VARS (block) = p;
          gcc_assert (I_LABEL_BINDING (b->id) == b);
          I_LABEL_BINDING (b->id) = b->shadowed;
@@ -1146,14 +1156,21 @@ pop_scope (void)
 
        case VAR_DECL:
          /* Warnings for unused variables.  */
-         if (!TREE_USED (p)
+         if ((!TREE_USED (p) || !DECL_READ_P (p))
              && !TREE_NO_WARNING (p)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
              && !DECL_ARTIFICIAL (p)
              && scope != file_scope
              && scope != external_scope)
-           warning (OPT_Wunused_variable, "unused variable %q+D", p);
+           {
+             if (!TREE_USED (p))
+               warning (OPT_Wunused_variable, "unused variable %q+D", p);
+             else if (DECL_CONTEXT (p) == current_function_decl)
+               warning_at (DECL_SOURCE_LOCATION (p),
+                           OPT_Wunused_but_set_variable,
+                           "variable %qD set but not used", p);
+           }
 
          if (b->inner_comp)
            {
@@ -1169,7 +1186,7 @@ pop_scope (void)
             binding in the home scope.  */
          if (!b->nested)
            {
-             TREE_CHAIN (p) = BLOCK_VARS (block);
+             DECL_CHAIN (p) = BLOCK_VARS (block);
              BLOCK_VARS (block) = p;
            }
          else if (VAR_OR_FUNCTION_DECL_P (p))
@@ -1192,7 +1209,7 @@ pop_scope (void)
                }
              if (b->locus != UNKNOWN_LOCATION)
                DECL_SOURCE_LOCATION (extp) = b->locus;
-             TREE_CHAIN (extp) = BLOCK_VARS (block);
+             DECL_CHAIN (extp) = BLOCK_VARS (block);
              BLOCK_VARS (block) = extp;
            }
          /* If this is the file scope, and we are processing more
@@ -1274,7 +1291,7 @@ push_file_scope (void)
 
   start_fname_decls ();
 
-  for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+  for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl))
     bind (DECL_NAME (decl), decl, file_scope,
          /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
 }
@@ -1307,7 +1324,6 @@ pop_file_scope (void)
   file_scope = 0;
 
   maybe_apply_pending_pragma_weaks ();
-  cgraph_finalize_compilation_unit ();
 }
 \f
 /* Adjust the bindings for the start of a statement expression.  */
@@ -1334,9 +1350,7 @@ c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
            continue;
          label_vars = b->u.label;
          ++label_vars->label_bindings.stmt_exprs;
-         for (ix = 0;
-              VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
-              ++ix)
+         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
            ++g->goto_bindings.stmt_exprs;
        }
     }
@@ -1374,9 +1388,7 @@ c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
              label_vars->label_bindings.left_stmt_expr = true;
              label_vars->label_bindings.stmt_exprs = 0;
            }
-         for (ix = 0;
-              VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
-              ++ix)
+         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
            {
              --g->goto_bindings.stmt_exprs;
              if (g->goto_bindings.stmt_exprs < 0)
@@ -1729,8 +1741,35 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        }
       else
        {
-         if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
-           error ("conflicting type qualifiers for %q+D", newdecl);
+         int new_quals = TYPE_QUALS (newtype);
+         int old_quals = TYPE_QUALS (oldtype);
+
+         if (new_quals != old_quals)
+           {
+             addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
+             addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
+             if (new_addr != old_addr)
+               {
+                 if (ADDR_SPACE_GENERIC_P (new_addr))
+                   error ("conflicting named address spaces (generic vs %s) "
+                          "for %q+D",
+                          c_addr_space_name (old_addr), newdecl);
+                 else if (ADDR_SPACE_GENERIC_P (old_addr))
+                   error ("conflicting named address spaces (%s vs generic) "
+                          "for %q+D",
+                          c_addr_space_name (new_addr), newdecl);
+                 else
+                   error ("conflicting named address spaces (%s vs %s) "
+                          "for %q+D",
+                          c_addr_space_name (new_addr),
+                          c_addr_space_name (old_addr),
+                          newdecl);
+               }
+
+             if (CLEAR_QUAL_ADDR_SPACE (new_quals)
+                 != CLEAR_QUAL_ADDR_SPACE (old_quals))
+               error ("conflicting type qualifiers for %q+D", newdecl);
+           }
          else
            error ("conflicting types for %q+D", newdecl);
          diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
@@ -1741,18 +1780,48 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
      but silently ignore the redeclaration if either is in a system
-     header.  (Conflicting redeclarations were handled above.)  */
+     header.  (Conflicting redeclarations were handled above.)  This
+     is allowed for C1X if the types are the same, not just
+     compatible.  */
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
+      bool types_different = false;
+      int comptypes_result;
+
+      comptypes_result
+       = comptypes_check_different_types (oldtype, newtype, &types_different);
+
+      if (comptypes_result != 1 || types_different)
+       {
+         error ("redefinition of typedef %q+D with different type", newdecl);
+         locate_old_decl (olddecl);
+         return false;
+       }
+
       if (DECL_IN_SYSTEM_HEADER (newdecl)
          || DECL_IN_SYSTEM_HEADER (olddecl)
          || TREE_NO_WARNING (newdecl)
          || TREE_NO_WARNING (olddecl))
        return true;  /* Allow OLDDECL to continue in use.  */
 
-      error ("redefinition of typedef %q+D", newdecl);
-      locate_old_decl (olddecl);
-      return false;
+      if (pedantic && !flag_isoc1x)
+       {
+         pedwarn (input_location, OPT_pedantic,
+                  "redefinition of typedef %q+D", newdecl);
+         locate_old_decl (olddecl);
+       }
+      else if (variably_modified_type_p (newtype, NULL))
+       {
+         /* Whether there is a constraint violation for the types not
+            being the same cannot be determined at compile time; a
+            warning that there may be one at runtime is considered
+            appropriate (WG14 reflector message 11743, 8 May 2009).  */
+         warning (0, "redefinition of typedef %q+D may be a constraint "
+                  "violation at runtime", newdecl);
+         locate_old_decl (olddecl);
+       }
+
+      return true;
     }
 
   /* Function declarations can either be 'static' or 'extern' (no
@@ -1853,7 +1922,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
            }
          else if (warn_traditional)
            {
-             warned |= warning (OPT_Wtraditional, 
+             warned |= warning (OPT_Wtraditional,
                                 "non-static declaration of %q+D "
                                 "follows static declaration", newdecl);
            }
@@ -1870,9 +1939,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
                                        DECL_ATTRIBUTES (olddecl)) != NULL;
          if (newa != olda)
            {
-             error ("%<gnu_inline%> attribute present on %q+D",
-                    newa ? newdecl : olddecl);
-             error ("%Jbut not here", newa ? olddecl : newdecl);
+             error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
+                       newa ? newdecl : olddecl);
+             error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
+                       "but not here");
            }
        }
     }
@@ -1930,7 +2000,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
                }
              else if (warn_traditional)
                {
-                 warned |= warning (OPT_Wtraditional, 
+                 warned |= warning (OPT_Wtraditional,
                                     "non-static declaration of %q+D "
                                     "follows static declaration", newdecl);
                }
@@ -1971,6 +2041,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
          return false;
        }
+
+      /* C++ does not permit a decl to appear multiple times at file
+        scope.  */
+      if (warn_cxx_compat
+         && DECL_FILE_SCOPE_P (newdecl)
+         && !DECL_EXTERNAL (newdecl)
+         && !DECL_EXTERNAL (olddecl))
+       warned |= warning_at (DECL_SOURCE_LOCATION (newdecl),
+                             OPT_Wc___compat,
+                             ("duplicate declaration of %qD is "
+                              "invalid in C++"),
+                             newdecl);
     }
 
   /* warnings */
@@ -1989,14 +2071,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       if (DECL_DECLARED_INLINE_P (newdecl)
          && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         warned |= warning (OPT_Wattributes, 
+         warned |= warning (OPT_Wattributes,
                             "inline declaration of %qD follows "
                             "declaration with attribute noinline", newdecl);
        }
       else if (DECL_DECLARED_INLINE_P (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         warned |= warning (OPT_Wattributes, 
+         warned |= warning (OPT_Wattributes,
                             "declaration of %q+D with attribute "
                             "noinline follows inline declaration ", newdecl);
        }
@@ -2311,9 +2393,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
          DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
-         gimple_set_body (newdecl, gimple_body (olddecl));
          DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
-         for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
+         for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
            DECL_CONTEXT (t) = newdecl;
 
          /* See if we've got a function to instantiate from.  */
@@ -2323,16 +2404,23 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
        }
     }
 
-   extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
+  extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
 
-   /* Merge the USED information.  */
-   if (TREE_USED (olddecl))
-     TREE_USED (newdecl) = 1;
-   else if (TREE_USED (newdecl))
-     TREE_USED (olddecl) = 1;
+  /* Merge the USED information.  */
+  if (TREE_USED (olddecl))
+    TREE_USED (newdecl) = 1;
+  else if (TREE_USED (newdecl))
+    TREE_USED (olddecl) = 1;
+  if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+    DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
+  if (DECL_PRESERVE_P (olddecl))
+    DECL_PRESERVE_P (newdecl) = 1;
+  else if (DECL_PRESERVE_P (newdecl))
+    DECL_PRESERVE_P (olddecl) = 1;
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
+     But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
+     DECL_ARGUMENTS (if appropriate).  */
   {
     unsigned olddecl_uid = DECL_UID (olddecl);
     tree olddecl_context = DECL_CONTEXT (olddecl);
@@ -2346,9 +2434,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
     switch (TREE_CODE (olddecl))
       {
       case FUNCTION_DECL:
-       gimple_set_body (olddecl, gimple_body (newdecl));
-       /* fall through */
-
       case FIELD_DECL:
       case VAR_DECL:
       case PARM_DECL:
@@ -2457,7 +2542,8 @@ warn_if_shadowing (tree new_decl)
          warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
                   new_decl);
 
-       warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl);
+       warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
+                   "shadowed declaration is here");
 
        break;
       }
@@ -2753,8 +2839,8 @@ implicit_decl_warning (tree id, tree olddecl)
       if (flag_isoc99)
        warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
                          "implicit declaration of function %qE", id);
-      else 
-       warned = warning (OPT_Wimplicit_function_declaration, 
+      else
+       warned = warning (OPT_Wimplicit_function_declaration,
                          G_("implicit declaration of function %qE"), id);
       if (olddecl && warned)
        locate_old_decl (olddecl);
@@ -2880,17 +2966,16 @@ undeclared_variable (location_t loc, tree id)
 
   if (current_function_decl == 0)
     {
-      error ("%H%qE undeclared here (not in a function)", &loc, id);
+      error_at (loc, "%qE undeclared here (not in a function)", id);
       scope = current_scope;
     }
   else
     {
-      error ("%H%qE undeclared (first use in this function)", &loc, id);
-
+      error_at (loc, "%qE undeclared (first use in this function)", id);
       if (!already)
        {
-         error ("%H(Each undeclared identifier is reported only once", &loc);
-         error ("%Hfor each function it appears in.)", &loc);
+          inform (loc, "each undeclared identifier is reported only"
+                  " once for each function it appears in");
          already = true;
        }
 
@@ -2916,7 +3001,7 @@ make_label (location_t location, tree name, bool defining,
   DECL_CONTEXT (label) = current_function_decl;
   DECL_MODE (label) = VOIDmode;
 
-  label_vars = GGC_NEW (struct c_label_vars);
+  label_vars = ggc_alloc_c_label_vars ();
   label_vars->shadowed = NULL;
   set_spot_bindings (&label_vars->label_bindings, defining);
   label_vars->decls_in_scope = make_tree_vector ();
@@ -3014,7 +3099,7 @@ lookup_label_for_goto (location_t loc, tree name)
     {
       struct c_goto_bindings *g;
 
-      g = GGC_NEW (struct c_goto_bindings);
+      g = ggc_alloc_c_goto_bindings ();
       g->loc = loc;
       set_spot_bindings (&g->goto_bindings, true);
       VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g);
@@ -3029,7 +3114,7 @@ lookup_label_for_goto (location_t loc, tree name)
        ...
        goto lab;
      Issue a warning or error.  */
-  for (ix = 0; VEC_iterate (tree, label_vars->decls_in_scope, ix, decl); ++ix)
+  FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl)
     warn_about_goto (loc, label, decl);
 
   if (label_vars->label_bindings.left_stmt_expr)
@@ -3081,9 +3166,7 @@ check_earlier_gotos (tree label, struct c_label_vars* label_vars)
   unsigned int ix;
   struct c_goto_bindings *g;
 
-  for (ix = 0;
-       VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
-       ++ix)
+  FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
     {
       struct c_binding *b;
       struct c_scope *scope;
@@ -3324,8 +3407,8 @@ void
 pending_xref_error (void)
 {
   if (pending_invalid_xref != 0)
-    error ("%H%qE defined as wrong kind of tag",
-          &pending_invalid_xref_location, pending_invalid_xref);
+    error_at (pending_invalid_xref_location, "%qE defined as wrong kind of tag",
+             pending_invalid_xref);
   pending_invalid_xref = 0;
 }
 
@@ -3383,7 +3466,7 @@ c_init_decl_processing (void)
      using preprocessed headers.  */
   input_location = BUILTINS_LOCATION;
 
-  build_common_tree_nodes (flag_signed_char, false);
+  build_common_tree_nodes (flag_signed_char);
 
   c_common_nodes_and_builtins ();
 
@@ -3438,14 +3521,14 @@ c_make_fname_decl (location_t loc, tree id, int type_dep)
 
   if (current_function_decl
       /* For invalid programs like this:
-        
+
          void foo()
          const char* p = __FUNCTION__;
-        
+
         the __FUNCTION__ is believed to appear in K&R style function
         parameter declarator.  In that case we still don't have
         function_scope.  */
-      && (!errorcount || current_function_scope))
+      && (!seen_error () || current_function_scope))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       bind (id, decl, current_function_scope,
@@ -3476,7 +3559,7 @@ c_builtin_function (tree decl)
      needing to be explicitly declared.  See push_file_scope.  */
   if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
     {
-      TREE_CHAIN (decl) = visible_builtins;
+      DECL_CHAIN (decl) = visible_builtins;
       visible_builtins = decl;
     }
 
@@ -3502,7 +3585,7 @@ c_builtin_function_ext_scope (tree decl)
      needing to be explicitly declared.  See push_file_scope.  */
   if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
     {
-      TREE_CHAIN (decl) = visible_builtins;
+      DECL_CHAIN (decl) = visible_builtins;
       visible_builtins = decl;
     }
 
@@ -3573,7 +3656,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
          else if (!declspecs->tag_defined_p
                   && (declspecs->const_p
                       || declspecs->volatile_p
-                      || declspecs->restrict_p))
+                      || declspecs->restrict_p
+                      || declspecs->address_space))
            {
              if (warned != 1)
                pedwarn (input_location, 0,
@@ -3644,7 +3728,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 
   if (!warned && !in_system_header && (declspecs->const_p
                                       || declspecs->volatile_p
-                                      || declspecs->restrict_p))
+                                      || declspecs->restrict_p
+                                      || declspecs->address_space))
     {
       warning (0, "useless type qualifier in empty declaration");
       warned = 2;
@@ -3667,7 +3752,8 @@ quals_from_declspecs (const struct c_declspecs *specs)
 {
   int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
               | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
-              | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+              | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+              | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
   gcc_assert (!specs->type
              && !specs->decl_attr
              && specs->typespec_word == cts_none
@@ -3967,7 +4053,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
       if (ce->kind == cdk_function)
        {
          tree args = ce->u.arg_info->parms;
-         for (; args; args = TREE_CHAIN (args))
+         for (; args; args = DECL_CHAIN (args))
            {
              tree type = TREE_TYPE (args);
              if (type && INTEGRAL_TYPE_P (type)
@@ -4009,21 +4095,33 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
   return tem;
 }
 
-/* Initialize EH if not initialized yet and exceptions are enabled.  */
+/* Subroutine of finish_decl. TYPE is the type of an uninitialized object
+   DECL or the non-array element type if DECL is an uninitialized array.
+   If that type has a const member, diagnose this. */
 
-void
-c_maybe_initialize_eh (void)
+static void
+diagnose_uninitialized_cst_member (tree decl, tree type)
 {
-  if (!flag_exceptions || c_eh_initialized_p)
-    return;
+  tree field;
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    {
+      tree field_type;
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+      field_type = strip_array_types (TREE_TYPE (field));
+
+      if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST)
+       {
+         warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                     "uninitialized const member in %qT is invalid in C++",
+                     strip_array_types (TREE_TYPE (decl)));
+         inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
+       }
 
-  c_eh_initialized_p = true;
-  eh_personality_libfunc
-    = init_one_libfunc (USING_SJLJ_EXCEPTIONS
-                       ? "__gcc_personality_sj0"
-                       : "__gcc_personality_v0");
-  default_init_unwind_resume_libfunc ();
-  using_eh_for_cleanups ();
+      if (TREE_CODE (field_type) == RECORD_TYPE
+         || TREE_CODE (field_type) == UNION_TYPE)
+       diagnose_uninitialized_cst_member (decl, field_type);
+    }
 }
 
 /* Finish processing of a declaration;
@@ -4049,6 +4147,13 @@ finish_decl (tree decl, location_t init_loc, tree init,
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
+  if (TREE_CODE (decl) == VAR_DECL
+      && TREE_STATIC (decl)
+      && global_bindings_p ())
+    /* So decl is a global variable. Record the types it uses
+       so that we can decide later to emit debug info for them.  */
+    record_types_used_by_current_var_decl (decl);
+
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
@@ -4177,7 +4282,10 @@ finish_decl (tree decl, location_t init_loc, tree init,
        }
 
       if (TREE_USED (type))
-       TREE_USED (decl) = 1;
+       {
+         TREE_USED (decl) = 1;
+         DECL_READ_P (decl) = 1;
+       }
     }
 
   /* If this is a function and an assembler name is specified, reset DECL_RTL
@@ -4325,13 +4433,26 @@ finish_decl (tree decl, location_t init_loc, tree init,
          /* Don't warn about decl unused; the cleanup uses it.  */
          TREE_USED (decl) = 1;
          TREE_USED (cleanup_decl) = 1;
-
-         /* Initialize EH, if we've been told to do so.  */
-         c_maybe_initialize_eh ();
+         DECL_READ_P (decl) = 1;
 
          push_cleanup (decl, cleanup, false);
        }
     }
+
+  if (warn_cxx_compat
+      && TREE_CODE (decl) == VAR_DECL
+      && !DECL_EXTERNAL (decl)
+      && DECL_INITIAL (decl) == NULL_TREE)
+    {
+      type = strip_array_types (type);
+      if (TREE_READONLY (decl))
+       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                   "uninitialized const %qD is invalid in C++", decl);
+      else if ((TREE_CODE (type) == RECORD_TYPE
+               || TREE_CODE (type) == UNION_TYPE)
+              && C_TYPE_FIELDS_READONLY (type))
+       diagnose_uninitialized_cst_member (decl, type);
+    }
 }
 
 /* Given a parsed parameter declaration, decode it into a PARM_DECL.  */
@@ -4402,7 +4523,8 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
   tree complit;
   tree stmt;
 
-  if (type == error_mark_node)
+  if (type == error_mark_node
+      || init == error_mark_node)
     return error_mark_node;
 
   decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
@@ -4411,6 +4533,7 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
   TREE_STATIC (decl) = (current_scope == file_scope);
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
+  DECL_READ_P (decl) = 1;
   TREE_TYPE (decl) = type;
   TREE_READONLY (decl) = TYPE_READONLY (type);
   store_init_value (loc, decl, init, NULL_TREE);
@@ -4479,8 +4602,8 @@ flexible_array_type_p (tree type)
       x = TYPE_FIELDS (type);
       if (x == NULL_TREE)
        return false;
-      while (TREE_CHAIN (x) != NULL_TREE)
-       x = TREE_CHAIN (x);
+      while (DECL_CHAIN (x) != NULL_TREE)
+       x = DECL_CHAIN (x);
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
          && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
@@ -4488,7 +4611,7 @@ flexible_array_type_p (tree type)
        return true;
       return false;
     case UNION_TYPE:
-      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
        {
          if (flexible_array_type_p (TREE_TYPE (x)))
            return true;
@@ -4513,14 +4636,26 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
 
   /* Detect and ignore out of range field width and process valid
      field widths.  */
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
-      || TREE_CODE (*width) != INTEGER_CST)
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
     {
       error ("bit-field %qs width not an integer constant", name);
       *width = integer_one_node;
     }
   else
     {
+      if (TREE_CODE (*width) != INTEGER_CST)
+       {
+         *width = c_fully_fold (*width, false, NULL);
+         if (TREE_CODE (*width) == INTEGER_CST)
+           pedwarn (input_location, OPT_pedantic,
+                    "bit-field %qs width not an integer constant expression",
+                    name);
+       }
+      if (TREE_CODE (*width) != INTEGER_CST)
+       {
+         error ("bit-field %qs width not an integer constant", name);
+         *width = integer_one_node;
+       }
       constant_expression_warning (*width);
       if (tree_int_cst_sgn (*width) < 0)
        {
@@ -4596,7 +4731,7 @@ warn_variable_length_array (tree name, tree size)
        }
       else
        {
-         if (name) 
+         if (name)
            pedwarn (input_location, OPT_Wvla,
                     "ISO C90 forbids variable length array %qE",
                     name);
@@ -4713,7 +4848,7 @@ grokdeclarator (const struct c_declarator *declarator,
   tree name = NULL_TREE;
   bool funcdef_flag = false;
   bool funcdef_syntax = false;
-  int size_varies = 0;
+  bool size_varies = false;
   tree decl_attr = declspecs->decl_attr;
   int array_ptr_quals = TYPE_UNQUALIFIED;
   tree array_ptr_attrs = NULL_TREE;
@@ -4723,6 +4858,7 @@ grokdeclarator (const struct c_declarator *declarator,
   bool bitfield = width != NULL;
   tree element_type;
   struct c_arg_info *arg_info = 0;
+  addr_space_t as1, as2, address_space;
   location_t loc = UNKNOWN_LOCATION;
   const char *errmsg;
   tree expr_dummy;
@@ -4807,7 +4943,7 @@ grokdeclarator (const struct c_declarator *declarator,
       type = integer_type_node;
     }
 
-  size_varies = C_TYPE_VARIABLE_SIZE (type);
+  size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
 
   /* Diagnose defaulting to "int".  */
 
@@ -4822,11 +4958,11 @@ grokdeclarator (const struct c_declarator *declarator,
       else
        {
          if (name)
-           pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int, 
+           pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
                         "type defaults to %<int%> in declaration of %qE",
                         name);
          else
-           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int, 
+           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
                         "type defaults to %<int%> in type name");
        }
     }
@@ -4853,6 +4989,10 @@ grokdeclarator (const struct c_declarator *declarator,
   constp = declspecs->const_p + TYPE_READONLY (element_type);
   restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
   volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+  as1 = declspecs->address_space;
+  as2 = TYPE_ADDR_SPACE (element_type);
+  address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
+
   if (pedantic && !flag_isoc99)
     {
       if (constp > 1)
@@ -4862,11 +5002,17 @@ grokdeclarator (const struct c_declarator *declarator,
       if (volatilep > 1)
        pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
     }
+
+  if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
+    error_at (loc, "conflicting named address spaces (%s vs %s)",
+             c_addr_space_name (as1), c_addr_space_name (as2));
+
   if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
     type = TYPE_MAIN_VARIANT (type);
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
                | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-               | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+               | (volatilep ? TYPE_QUAL_VOLATILE : 0)
+               | ENCODE_QUAL_ADDR_SPACE (address_space));
 
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
@@ -4878,8 +5024,8 @@ grokdeclarator (const struct c_declarator *declarator,
          || storage_class == csc_typedef))
     {
       if (storage_class == csc_auto)
-       pedwarn (loc, 
-                (current_scope == file_scope) ? 0 : OPT_pedantic, 
+       pedwarn (loc,
+                (current_scope == file_scope) ? 0 : OPT_pedantic,
                 "function definition declared %<auto%>");
       if (storage_class == csc_register)
        error_at (loc, "function definition declared %<register%>");
@@ -5140,7 +5286,7 @@ grokdeclarator (const struct c_declarator *declarator,
                                   "variably modified %qE at file scope",
                                   name);
                        else
-                         this_size_varies = size_varies = 1;
+                         this_size_varies = size_varies = true;
                        warn_variable_length_array (name, size);
                      }
                  }
@@ -5155,7 +5301,7 @@ grokdeclarator (const struct c_declarator *declarator,
                    /* Make sure the array size remains visibly
                       nonconstant even if it is (eg) a const variable
                       with known value.  */
-                   this_size_varies = size_varies = 1;
+                   this_size_varies = size_varies = true;
                    warn_variable_length_array (name, size);
                  }
 
@@ -5182,10 +5328,10 @@ grokdeclarator (const struct c_declarator *declarator,
                       - 1.  Do the calculation in index_type, so that
                       if it is a variable the computations will be
                       done in the proper mode.  */
-                   itype = fold_build2 (MINUS_EXPR, index_type,
-                                        convert (index_type, size),
-                                        convert (index_type,
-                                                 size_one_node));
+                   itype = fold_build2_loc (loc, MINUS_EXPR, index_type,
+                                            convert (index_type, size),
+                                            convert (index_type,
+                                                     size_one_node));
 
                    /* If that overflowed, the array is too big.  ???
                       While a size of INT_MAX+1 technically shouldn't
@@ -5227,7 +5373,7 @@ grokdeclarator (const struct c_declarator *declarator,
                     the field variably modified, not through being
                     something other than a declaration with function
                     prototype scope.  */
-                 size_varies = 1;
+                 size_varies = true;
                else
                  {
                    const struct c_declarator *t = declarator;
@@ -5251,7 +5397,7 @@ grokdeclarator (const struct c_declarator *declarator,
                if (array_parm_vla_unspec_p)
                  {
                    itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
-                   size_varies = 1;
+                   size_varies = true;
                  }
              }
            else if (decl_context == TYPENAME)
@@ -5265,7 +5411,7 @@ grokdeclarator (const struct c_declarator *declarator,
                       otherwise be modified below.  */
                    itype = build_range_type (sizetype, size_zero_node,
                                              NULL_TREE);
-                   size_varies = 1;
+                   size_varies = true;
                  }
              }
 
@@ -5282,7 +5428,14 @@ grokdeclarator (const struct c_declarator *declarator,
               it, but here we want to make sure we don't ever
               modify the shared type, so we gcc_assert (itype)
               below.  */
-             type = build_array_type (type, itype);
+             {
+               addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
+               if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
+                 type = build_qualified_type (type,
+                                              ENCODE_QUAL_ADDR_SPACE (as));
+
+               type = build_array_type (type, itype);
+             }
 
            if (type != error_mark_node)
              {
@@ -5307,6 +5460,7 @@ grokdeclarator (const struct c_declarator *declarator,
                    gcc_assert (itype);
                    TYPE_SIZE (type) = bitsize_zero_node;
                    TYPE_SIZE_UNIT (type) = size_zero_node;
+                   SET_TYPE_STRUCTURAL_EQUALITY (type);
                  }
                if (array_parm_vla_unspec_p)
                  {
@@ -5314,6 +5468,7 @@ grokdeclarator (const struct c_declarator *declarator,
                    /* The type is complete.  C99 6.7.5.2p4  */
                    TYPE_SIZE (type) = bitsize_zero_node;
                    TYPE_SIZE_UNIT (type) = size_zero_node;
+                   SET_TYPE_STRUCTURAL_EQUALITY (type);
                  }
              }
 
@@ -5349,7 +5504,7 @@ grokdeclarator (const struct c_declarator *declarator,
            if (type == error_mark_node)
              continue;
 
-           size_varies = 0;
+           size_varies = false;
 
            /* Warn about some types functions can't return.  */
            if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -5414,12 +5569,11 @@ grokdeclarator (const struct c_declarator *declarator,
               the formal parameter list of this FUNCTION_TYPE to point to
               the FUNCTION_TYPE node itself.  */
            {
-             tree link;
+             c_arg_tag *tag;
+             unsigned ix;
 
-             for (link = arg_info->tags;
-                  link;
-                  link = TREE_CHAIN (link))
-               TYPE_CONTEXT (TREE_VALUE (link)) = type;
+             FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+               TYPE_CONTEXT (tag->type) = type;
            }
            break;
          }
@@ -5434,7 +5588,7 @@ grokdeclarator (const struct c_declarator *declarator,
                       "ISO C forbids qualified function types");
            if (type_quals)
              type = c_build_qualified_type (type, type_quals);
-           size_varies = 0;
+           size_varies = false;
 
            /* When the pointed-to type involves components of variable size,
               care must be taken to ensure that the size evaluation code is
@@ -5488,6 +5642,59 @@ grokdeclarator (const struct c_declarator *declarator,
   /* Now TYPE has the actual type, apart from any qualifiers in
      TYPE_QUALS.  */
 
+  /* Warn about address space used for things other than static memory or
+     pointers.  */
+  address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
+  if (!ADDR_SPACE_GENERIC_P (address_space))
+    {
+      if (decl_context == NORMAL)
+       {
+         switch (storage_class)
+           {
+           case csc_auto:
+             error ("%qs combined with %<auto%> qualifier for %qE",
+                    c_addr_space_name (address_space), name);
+             break;
+           case csc_register:
+             error ("%qs combined with %<register%> qualifier for %qE",
+                    c_addr_space_name (address_space), name);
+             break;
+           case csc_none:
+             if (current_function_scope)
+               {
+                 error ("%qs specified for auto variable %qE",
+                        c_addr_space_name (address_space), name);
+                 break;
+               }
+             break;
+           case csc_static:
+           case csc_extern:
+           case csc_typedef:
+             break;
+           default:
+             gcc_unreachable ();
+           }
+       }
+      else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
+       {
+         if (name)
+           error ("%qs specified for parameter %qE",
+                  c_addr_space_name (address_space), name);
+         else
+           error ("%qs specified for unnamed parameter",
+                  c_addr_space_name (address_space));
+       }
+      else if (decl_context == FIELD)
+       {
+         if (name)
+           error ("%qs specified for structure field %qE",
+                  c_addr_space_name (address_space), name);
+         else
+           error ("%qs specified for structure field",
+                  c_addr_space_name (address_space));
+       }
+    }
+
   /* Check the type and width of a bit-field.  */
   if (bitfield)
     check_bitfield_type_and_width (&type, width, name);
@@ -5620,7 +5827,7 @@ grokdeclarator (const struct c_declarator *declarator,
              warning_at (loc, OPT_Wattributes,
                          "attributes in parameter array declarator ignored");
 
-           size_varies = 0;
+           size_varies = false;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
          {
@@ -5721,12 +5928,6 @@ grokdeclarator (const struct c_declarator *declarator,
          pedwarn (loc, OPT_pedantic,
                   "ISO C forbids qualified function types");
 
-       /* GNU C interprets a volatile-qualified function type to indicate
-          that the function does not return.  */
-       if ((type_quals & TYPE_QUAL_VOLATILE)
-           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
-         warning_at (loc, 0, "%<noreturn%> function returns non-void value");
-
        /* Every function declaration is an external reference
           (DECL_EXTERNAL) except for those which are not at file
           scope and are explicitly declared "auto".  This is
@@ -5875,6 +6076,19 @@ grokdeclarator (const struct c_declarator *declarator,
      name of a variable.  Thus, if it's known before this, die horribly.  */
     gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
 
+    if (warn_cxx_compat
+       && TREE_CODE (decl) == VAR_DECL
+       && TREE_PUBLIC (decl)
+       && TREE_STATIC (decl)
+       && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+           || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+           || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+       && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
+      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                 ("non-local variable %qD with anonymous type is "
+                  "questionable in C++"),
+                 decl);
+
     return decl;
   }
 }
@@ -5938,7 +6152,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
 
       for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
           parm;
-          parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+          parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
        {
          type = TREE_VALUE (typelt);
          if (type == error_mark_node)
@@ -5949,23 +6163,28 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
              if (funcdef_flag)
                {
                  if (DECL_NAME (parm))
-                   error ("parameter %u (%q+D) has incomplete type",
-                          parmno, parm);
+                   error_at (input_location,
+                             "parameter %u (%q+D) has incomplete type",
+                             parmno, parm);
                  else
-                   error ("%Jparameter %u has incomplete type",
-                          parm, parmno);
+                   error_at (DECL_SOURCE_LOCATION (parm),
+                             "parameter %u has incomplete type",
+                             parmno);
 
                  TREE_VALUE (typelt) = error_mark_node;
                  TREE_TYPE (parm) = error_mark_node;
+                 arg_types = NULL_TREE;
                }
              else if (VOID_TYPE_P (type))
                {
                  if (DECL_NAME (parm))
-                   warning (0, "parameter %u (%q+D) has void type",
-                            parmno, parm);
+                   warning_at (input_location, 0,
+                               "parameter %u (%q+D) has void type",
+                               parmno, parm);
                  else
-                   warning (0, "%Jparameter %u has void type",
-                            parm, parmno);
+                   warning_at (DECL_SOURCE_LOCATION (parm), 0,
+                               "parameter %u has void type",
+                               parmno);
                }
            }
 
@@ -5975,6 +6194,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
              error (errmsg);
              TREE_VALUE (typelt) = error_mark_node;
              TREE_TYPE (parm) = error_mark_node;
+             arg_types = NULL_TREE;
            }
 
          if (DECL_NAME (parm) && TREE_USED (parm))
@@ -5984,6 +6204,22 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
     }
 }
 
+/* Allocate and initialize a c_arg_info structure from the parser's
+   obstack.  */
+
+struct c_arg_info *
+build_arg_info (void)
+{
+  struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+  ret->parms = NULL_TREE;
+  ret->tags = NULL;
+  ret->types = NULL_TREE;
+  ret->others = NULL_TREE;
+  ret->pending_sizes = NULL;
+  ret->had_vla_unspec = 0;
+  return ret;
+}
+
 /* Take apart the current scope and return a c_arg_info structure with
    info on a parameter list just parsed.
 
@@ -5996,21 +6232,16 @@ struct c_arg_info *
 get_parm_info (bool ellipsis)
 {
   struct c_binding *b = current_scope->bindings;
-  struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
-                                       struct c_arg_info);
+  struct c_arg_info *arg_info = build_arg_info ();
+
   tree parms    = 0;
-  tree tags     = 0;
+  VEC(c_arg_tag,gc) *tags = NULL;
   tree types    = 0;
   tree others   = 0;
 
   static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
-  arg_info->parms = 0;
-  arg_info->tags = 0;
-  arg_info->types = 0;
-  arg_info->others = 0;
-  arg_info->pending_sizes = 0;
   arg_info->had_vla_unspec = current_scope->had_vla_unspec;
 
   /* The bindings in this scope must not get put into a block.
@@ -6053,6 +6284,7 @@ get_parm_info (bool ellipsis)
     {
       tree decl = b->decl;
       tree type = TREE_TYPE (decl);
+      c_arg_tag *tag;
       const char *keyword;
 
       switch (TREE_CODE (decl))
@@ -6079,7 +6311,7 @@ get_parm_info (bool ellipsis)
          else
            {
              /* Valid parameter, add it to the list.  */
-             TREE_CHAIN (decl) = parms;
+             DECL_CHAIN (decl) = parms;
              parms = decl;
 
              /* Since there is a prototype, args are passed in their
@@ -6126,7 +6358,9 @@ get_parm_info (bool ellipsis)
                }
            }
 
-         tags = tree_cons (b->id, decl, tags);
+         tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
+         tag->id = b->id;
+         tag->type = decl;
          break;
 
        case CONST_DECL:
@@ -6138,7 +6372,12 @@ get_parm_info (bool ellipsis)
             type itself.  FUNCTION_DECLs appear when there is an implicit
             function declaration in the parameter list.  */
 
-         TREE_CHAIN (decl) = others;
+         /* When we reinsert this decl in the function body, we need
+            to reconstruct whether it was marked as nested.  */
+         gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+                     ? b->nested
+                     : !b->nested);
+         DECL_CHAIN (decl) = others;
          others = decl;
          /* fall through */
 
@@ -6276,16 +6515,14 @@ xref_tag (enum tree_code code, tree name)
    LOC is the location of the struct's definition.
    CODE says which kind of tag NAME ought to be.
 
-   This stores the current value of the file static IN_STRUCT in
-   *ENCLOSING_IN_STRUCT, and sets IN_STRUCT to true.  Similarly, this
-   sets STRUCT_TYPES in *ENCLOSING_STRUCT_TYPES, and sets STRUCT_TYPES
-   to an empty vector.  The old values are restored in
-   finish_struct.  */
+   This stores the current value of the file static STRUCT_PARSE_INFO
+   in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
+   new c_struct_parse_info structure.  The old value of
+   STRUCT_PARSE_INFO is restored in finish_struct.  */
 
 tree
 start_struct (location_t loc, enum tree_code code, tree name,
-             bool *enclosing_in_struct,
-             VEC(tree,heap) **enclosing_struct_types)
+             struct c_struct_parse_info **enclosing_struct_parse_info)
 {
   /* If there is already a tag defined at this scope
      (as a forward reference), just return it.  */
@@ -6333,10 +6570,11 @@ start_struct (location_t loc, enum tree_code code, tree name,
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
 
-  *enclosing_in_struct = in_struct;
-  *enclosing_struct_types = struct_types;
-  in_struct = true;
-  struct_types = VEC_alloc(tree, heap, 0);
+  *enclosing_struct_parse_info = struct_parse_info;
+  struct_parse_info = XNEW (struct c_struct_parse_info);
+  struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
+  struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
+  struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
 
   /* FIXME: This will issue a warning for a use of a type defined
      within a statement expr used within sizeof, et. al.  This is not
@@ -6384,6 +6622,8 @@ grokfield (location_t loc,
           Otherwise this is a forward declaration of a structure tag.
 
         If this is something of the form "foo;" and foo is a TYPE_DECL, then
+          If foo names a structure or union without a tag, then this
+            is an anonymous struct (this is permitted by C1X).
           If MS extensions are enabled and foo names a structure, then
             again this is an anonymous struct.
           Otherwise this is an error.
@@ -6397,14 +6637,11 @@ grokfield (location_t loc,
                      || TREE_CODE (type) == UNION_TYPE);
       bool ok = false;
 
-      if (type_ok
-         && (flag_ms_extensions || !declspecs->typedef_p))
+      if (type_ok)
        {
          if (flag_ms_extensions)
            ok = true;
-         else if (flag_iso)
-           ok = false;
-         else if (TYPE_NAME (type) == NULL)
+         else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
            ok = true;
          else
            ok = false;
@@ -6414,7 +6651,15 @@ grokfield (location_t loc,
          pedwarn (loc, 0, "declaration does not declare anything");
          return NULL_TREE;
        }
-      pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
+      if (!flag_isoc1x)
+       {
+         if (flag_isoc99)
+           pedwarn (loc, OPT_pedantic,
+                    "ISO C99 doesn%'t support unnamed structs/unions");
+         else
+           pedwarn (loc, OPT_pedantic,
+                    "ISO C90 doesn%'t support unnamed structs/unions");
+       }
     }
 
   value = grokdeclarator (declarator, declspecs, FIELD, false,
@@ -6424,9 +6669,53 @@ grokfield (location_t loc,
   finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
+  if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
+    {
+      /* If we currently have a binding for this field, set the
+        in_struct field in the binding, so that we warn about lookups
+        which find it.  */
+      struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
+      if (b != NULL)
+       {
+         /* If the in_struct field is not yet set, push it on a list
+            to be cleared when this struct is finished.  */
+         if (!b->in_struct)
+           {
+             VEC_safe_push (c_binding_ptr, heap,
+                            struct_parse_info->fields, b);
+             b->in_struct = 1;
+           }
+       }
+    }
+
   return value;
 }
 \f
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+   to HTAB, giving errors for any duplicates.  */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+  tree x, y;
+  void **slot;
+
+  for (x = fieldlist; x ; x = DECL_CHAIN (x))
+    if ((y = DECL_NAME (x)) != 0)
+      {
+       slot = htab_find_slot (htab, y, INSERT);
+       if (*slot)
+         {
+           error ("duplicate member %q+D", x);
+           DECL_NAME (x) = NULL_TREE;
+         }
+       *slot = y;
+      }
+    else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+            || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+      detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+}
+
 /* Generate an error for any duplicate field names in FIELDLIST.  Munge
    the list such that this does not present a problem later.  */
 
@@ -6440,19 +6729,24 @@ detect_field_duplicates (tree fieldlist)
      This is trivially true if there are zero or one fields.  */
   if (!fieldlist)
     return;
-  x = TREE_CHAIN (fieldlist);
+  x = DECL_CHAIN (fieldlist);
   if (!x)
     return;
   do {
     timeout--;
-    x = TREE_CHAIN (x);
+    if (DECL_NAME (x) == NULL_TREE
+       && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+           || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+      timeout = 0;
+    x = DECL_CHAIN (x);
   } while (timeout > 0 && x);
 
-  /* If there were "few" fields, avoid the overhead of allocating
-     a hash table.  Instead just do the nested traversal thing.  */
+  /* If there were "few" fields and no anonymous structures or unions,
+     avoid the overhead of allocating a hash table.  Instead just do
+     the nested traversal thing.  */
   if (timeout > 0)
     {
-      for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
+      for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
        if (DECL_NAME (x))
          {
            for (y = fieldlist; y != x; y = TREE_CHAIN (y))
@@ -6466,43 +6760,82 @@ detect_field_duplicates (tree fieldlist)
   else
     {
       htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
-      void **slot;
-
-      for (x = fieldlist; x ; x = TREE_CHAIN (x))
-       if ((y = DECL_NAME (x)) != 0)
-         {
-           slot = htab_find_slot (htab, y, INSERT);
-           if (*slot)
-             {
-               error ("duplicate member %q+D", x);
-               DECL_NAME (x) = NULL_TREE;
-             }
-           *slot = y;
-         }
 
+      detect_field_duplicates_hash (fieldlist, htab);
       htab_delete (htab);
     }
 }
 
+/* Finish up struct info used by -Wc++-compat.  */
+
+static void
+warn_cxx_compat_finish_struct (tree fieldlist)
+{
+  unsigned int ix;
+  tree x;
+  struct c_binding *b;
+
+  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+     the current struct.  We do this now at the end of the struct
+     because the flag is used to issue visibility warnings, and we
+     only want to issue those warnings if the type is referenced
+     outside of the struct declaration.  */
+  FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x)
+    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+  /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
+     typedefs used when declaring fields in this struct.  If the name
+     of any of the fields is also a typedef name then the struct would
+     not parse in C++, because the C++ lookup rules say that the
+     typedef name would be looked up in the context of the struct, and
+     would thus be the field rather than the typedef.  */
+  if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
+      && fieldlist != NULL_TREE)
+    {
+      /* Use a pointer_set using the name of the typedef.  We can use
+        a pointer_set because identifiers are interned.  */
+      struct pointer_set_t *tset = pointer_set_create ();
+
+      FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x)
+       pointer_set_insert (tset, DECL_NAME (x));
+
+      for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
+       {
+         if (pointer_set_contains (tset, DECL_NAME (x)))
+           {
+             warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
+                         ("using %qD as both field and typedef name is "
+                          "invalid in C++"),
+                         x);
+             /* FIXME: It would be nice to report the location where
+                the typedef name is used.  */
+           }
+       }
+
+      pointer_set_destroy (tset);
+    }
+
+  /* For each field which has a binding and which was not defined in
+     an enclosing struct, clear the in_struct field.  */
+  FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
+    b->in_struct = 0;
+}
+
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
    ATTRIBUTES are attributes to be applied to the structure.
 
-   ENCLOSING_IN_STRUCT is the value of IN_STRUCT, and
-   ENCLOSING_STRUCT_TYPES is the value of STRUCT_TYPES, when the
-   struct was started.  This sets the C_TYPE_DEFINED_IN_STRUCT flag
-   for any type defined in the current struct.  */
+   ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
+   the struct was started.  */
 
 tree
 finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
-              bool enclosing_in_struct,
-              VEC(tree,heap) *enclosing_struct_types)
+              struct c_struct_parse_info *enclosing_struct_parse_info)
 {
   tree x;
   bool toplevel = file_scope == current_scope;
   int saw_named_field;
-  unsigned int ix;
 
   /* If this type was previously laid out as a forward reference,
      make sure we lay it out again.  */
@@ -6513,9 +6846,15 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 
   if (pedantic)
     {
-      for (x = fieldlist; x; x = TREE_CHAIN (x))
-       if (DECL_NAME (x) != 0)
-         break;
+      for (x = fieldlist; x; x = DECL_CHAIN (x))
+       {
+         if (DECL_NAME (x) != 0)
+           break;
+         if (flag_isoc1x
+             && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+           break;
+       }
 
       if (x == 0)
        {
@@ -6544,7 +6883,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
      until now.)  */
 
   saw_named_field = 0;
-  for (x = fieldlist; x; x = TREE_CHAIN (x))
+  for (x = fieldlist; x; x = DECL_CHAIN (x))
     {
       if (TREE_TYPE (x) == error_mark_node)
        continue;
@@ -6557,9 +6896,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       else
        {
          /* A field that is pseudo-const makes the structure likewise.  */
-         tree t1 = TREE_TYPE (x);
-         while (TREE_CODE (t1) == ARRAY_TYPE)
-           t1 = TREE_TYPE (t1);
+         tree t1 = strip_array_types (TREE_TYPE (x));
          if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
              && C_TYPE_FIELDS_READONLY (t1))
            C_TYPE_FIELDS_READONLY (t) = 1;
@@ -6596,30 +6933,31 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
          if (TREE_CODE (t) == UNION_TYPE)
            {
              error_at (DECL_SOURCE_LOCATION (x),
-                       "%Jflexible array member in union", x);
+                       "flexible array member in union");
              TREE_TYPE (x) = error_mark_node;
            }
-         else if (TREE_CHAIN (x) != NULL_TREE)
+         else if (DECL_CHAIN (x) != NULL_TREE)
            {
              error_at (DECL_SOURCE_LOCATION (x),
-                       "%Jflexible array member not at end of struct", x);
+                       "flexible array member not at end of struct");
              TREE_TYPE (x) = error_mark_node;
            }
          else if (!saw_named_field)
            {
              error_at (DECL_SOURCE_LOCATION (x),
-                       "%Jflexible array member in otherwise empty struct",
-                       x);
+                       "flexible array member in otherwise empty struct");
              TREE_TYPE (x) = error_mark_node;
            }
        }
 
-      if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
+      if (pedantic && TREE_CODE (t) == RECORD_TYPE
          && flexible_array_type_p (TREE_TYPE (x)))
-       pedwarn (loc, OPT_pedantic, 
-                "%Jinvalid use of structure with flexible array member", x);
+       pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
+                "invalid use of structure with flexible array member");
 
-      if (DECL_NAME (x))
+      if (DECL_NAME (x)
+         || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+         || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
        saw_named_field = 1;
     }
 
@@ -6651,7 +6989,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
          DECL_INITIAL (*fieldlistp) = 0;
        }
       else
-       fieldlistp = &TREE_CHAIN (*fieldlistp);
+       fieldlistp = &DECL_CHAIN (*fieldlistp);
   }
 
   /* Now we have the truly final field list.
@@ -6665,7 +7003,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
   {
     int len = 0;
 
-    for (x = fieldlist; x; x = TREE_CHAIN (x))
+    for (x = fieldlist; x; x = DECL_CHAIN (x))
       {
        if (len > 15 || DECL_NAME (x) == NULL)
          break;
@@ -6684,14 +7022,14 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
          ensure that this lives as long as the rest of the struct decl.
          All decls in an inline function need to be saved.  */
 
-       space = GGC_CNEW (struct lang_type);
-       space2 = GGC_NEWVAR (struct sorted_fields_type,
-                            sizeof (struct sorted_fields_type) + len * sizeof (tree));
+       space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+       space2 = ggc_alloc_sorted_fields_type
+         (sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
        len = 0;
        space->s = space2;
        field_array = &space2->elts[0];
-       for (x = fieldlist; x; x = TREE_CHAIN (x))
+       for (x = fieldlist; x; x = DECL_CHAIN (x))
          {
            field_array[len++] = x;
 
@@ -6722,10 +7060,10 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
   /* If this was supposed to be a transparent union, but we can't
      make it one, warn and turn off the flag.  */
   if (TREE_CODE (t) == UNION_TYPE
-      && TYPE_TRANSPARENT_UNION (t)
+      && TYPE_TRANSPARENT_AGGR (t)
       && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
     {
-      TYPE_TRANSPARENT_UNION (t) = 0;
+      TYPE_TRANSPARENT_AGGR (t) = 0;
       warning_at (loc, 0, "union cannot be made transparent");
     }
 
@@ -6750,6 +7088,11 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
     }
   C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
 
+  /* Update type location to the one of the definition, instead of e.g.
+     a forward declaration.  */
+  if (TYPE_STUB_DECL (t))
+    DECL_SOURCE_LOCATION (TYPE_STUB_DECL (t)) = loc;
+
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
@@ -6760,23 +7103,22 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
     add_stmt (build_stmt (loc,
                          DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
 
-  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
-     the current struct.  We do this now at the end of the struct
-     because the flag is used to issue visibility warnings when using
-     -Wc++-compat, and we only want to issue those warnings if the
-     type is referenced outside of the struct declaration.  */
-  for (ix = 0; VEC_iterate (tree, struct_types, ix, x); ++ix)
-    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+  if (warn_cxx_compat)
+    warn_cxx_compat_finish_struct (fieldlist);
 
-  VEC_free (tree, heap, struct_types);
+  VEC_free (tree, heap, struct_parse_info->struct_types);
+  VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
+  VEC_free (tree, heap, struct_parse_info->typedefs_seen);
+  XDELETE (struct_parse_info);
 
-  in_struct = enclosing_in_struct;
-  struct_types = enclosing_struct_types;
+  struct_parse_info = enclosing_struct_parse_info;
 
   /* If this struct is defined inside a struct, add it to
-     STRUCT_TYPES.  */
-  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_types, t);
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
 
   return t;
 }
@@ -6963,7 +7305,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
   /* Record the min/max values so that we can warn about bit-field
      enumerations that are too small for the values.  */
-  lt = GGC_CNEW (struct lang_type);
+  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
   lt->enum_min = minnode;
   lt->enum_max = maxnode;
   TYPE_LANG_SPECIFIC (enumtype) = lt;
@@ -6990,9 +7332,11 @@ finish_enum (tree enumtype, tree values, tree attributes)
   rest_of_type_compilation (enumtype, toplevel);
 
   /* If this enum is defined inside a struct, add it to
-     STRUCT_TYPES.  */
-  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_types, enumtype);
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
 
   return enumtype;
 }
@@ -7061,7 +7405,7 @@ build_enumerator (location_t loc,
      (6.4.4.3/2 in the C99 Standard).  GCC allows any integer type as
      an extension.  */
   else if (!int_fits_type_p (value, integer_type_node))
-    pedwarn (loc, OPT_pedantic, 
+    pedwarn (loc, OPT_pedantic,
             "ISO C restricts enumerator values to range of %<int%>");
 
   /* The ISO C Standard mandates enumerators to have type int, even
@@ -7173,7 +7517,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
     }
 
   if (warn_about_return_type)
-    pedwarn_c99 (loc, flag_isoc99 ? 0 
+    pedwarn_c99 (loc, flag_isoc99 ? 0
                 : (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
                 "return type defaults to %<int%>");
 
@@ -7181,6 +7525,10 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
      error_mark_node is replaced below (in pop_scope) with the BLOCK.  */
   DECL_INITIAL (decl1) = error_mark_node;
 
+  /* A nested function is not global.  */
+  if (current_function_decl != 0)
+    TREE_PUBLIC (decl1) = 0;
+
   /* If this definition isn't a prototype and we had a prototype declaration
      before, copy the arg type info from that prototype.  */
   old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
@@ -7281,10 +7629,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
 
-  /* A nested function is not global.  */
-  if (current_function_decl != 0)
-    TREE_PUBLIC (decl1) = 0;
-
   /* This is the earliest point at which we might know the assembler
      name of the function.  Thus, if it's set before this, die horribly.  */
   gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
@@ -7335,11 +7679,14 @@ static void
 store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
 {
   tree decl;
+  c_arg_tag *tag;
+  unsigned ix;
 
   if (current_scope->bindings)
     {
-      error ("%Jold-style parameter declarations in prototyped "
-            "function definition", fndecl);
+      error_at (DECL_SOURCE_LOCATION (fndecl),
+               "old-style parameter declarations in prototyped "
+               "function definition");
 
       /* Get rid of the old-style declarations.  */
       pop_scope ();
@@ -7351,13 +7698,12 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
      its parameter list).  */
   else if (!in_system_header && !current_function_scope
           && arg_info->types != error_mark_node)
-    warning (OPT_Wtraditional,
-            "%Jtraditional C rejects ISO C style function definitions",
-            fndecl);
+    warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
+               "traditional C rejects ISO C style function definitions");
 
   /* Now make all the parameter declarations visible in the function body.
      We can bypass most of the grunt work of pushdecl.  */
-  for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
@@ -7369,25 +7715,27 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
            warn_if_shadowing (decl);
        }
       else
-       error ("%Jparameter name omitted", decl);
+       error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
     }
 
   /* Record the parameter list in the function declaration.  */
   DECL_ARGUMENTS (fndecl) = arg_info->parms;
 
   /* Now make all the ancillary declarations visible, likewise.  */
-  for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
        bind (DECL_NAME (decl), decl, current_scope,
-             /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+             /*invisible=*/false,
+             /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
+             UNKNOWN_LOCATION);
     }
 
   /* And all the tag declarations.  */
-  for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
-    if (TREE_PURPOSE (decl))
-      bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+  FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+    if (tag->id)
+      bind (tag->id, tag->type, current_scope,
            /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
 }
 
@@ -7470,7 +7818,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
          if (flag_isoc99)
            pedwarn (DECL_SOURCE_LOCATION (decl),
                     0, "type of %qD defaults to %<int%>", decl);
-         else 
+         else
            warning_at (DECL_SOURCE_LOCATION (decl),
                        OPT_Wmissing_parameter_type,
                        "type of %qD defaults to %<int%>", decl);
@@ -7526,10 +7874,10 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
        if (TREE_PURPOSE (parm))
          {
-           TREE_CHAIN (last) = TREE_PURPOSE (parm);
+           DECL_CHAIN (last) = TREE_PURPOSE (parm);
            last = TREE_PURPOSE (parm);
          }
-      TREE_CHAIN (last) = 0;
+      DECL_CHAIN (last) = 0;
     }
 
   pointer_set_destroy (seen_args);
@@ -7545,7 +7893,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
             type = current_function_prototype_arg_types;
           parm || (type && TREE_VALUE (type) != error_mark_node
                    && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
-          parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+          parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
        {
          if (parm == 0 || type == 0
              || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
@@ -7636,7 +7984,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
     {
       tree actual = 0, last = 0, type;
 
-      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
        {
          type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
          if (last)
@@ -7726,9 +8074,12 @@ store_parm_decls (void)
      thus won't naturally see the SAVE_EXPR containing the increment.  All
      other pending sizes would be handled by gimplify_parameters.  */
   {
+    VEC(tree,gc) *pending_sizes = get_pending_sizes ();
     tree t;
-    for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
-      add_stmt (TREE_VALUE (t));
+    int i;
+
+    FOR_EACH_VEC_ELT (tree, pending_sizes, i, t)
+      add_stmt (t);
   }
 
   /* Even though we're inside a function body, we still don't want to
@@ -7738,30 +8089,9 @@ store_parm_decls (void)
   cfun->dont_save_pending_sizes_p = 1;
 }
 \f
-/* Emit diagnostics that require gimple input for detection.  Operate on
-   FNDECL and all its nested functions.  */
-
-static void
-c_gimple_diagnostics_recursively (tree fndecl)
-{
-  struct cgraph_node *cgn;
-  gimple_seq body = gimple_body (fndecl);
-
-  /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
-  c_warn_unused_result (body);
-
-  /* Notice when OpenMP structured block constraints are violated.  */
-  if (flag_openmp)
-    diagnose_omp_structured_block_errors (fndecl);
-
-  /* Finalize all nested functions now.  */
-  cgn = cgraph_node (fndecl);
-  for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
-    c_gimple_diagnostics_recursively (cgn->decl);
-}
 
 /* Finish up a function declaration and compile that function
-   all the way to assembler language output.  The free the storage
+   all the way to assembler language output.  Then free the storage
    for the function definition.
 
    This is called after parsing the body of the function definition.  */
@@ -7775,7 +8105,7 @@ finish_function (void)
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
     {
       tree args = DECL_ARGUMENTS (fndecl);
-      for (; args; args = TREE_CHAIN (args))
+      for (; args; args = DECL_CHAIN (args))
        {
          tree type = TREE_TYPE (args);
          if (INTEGRAL_TYPE_P (type)
@@ -7816,6 +8146,8 @@ finish_function (void)
       && !current_function_returns_value && !current_function_returns_null
       /* Don't complain if we are no-return.  */
       && !current_function_returns_abnormally
+      /* Don't complain if we are declared noreturn.  */
+      && !TREE_THIS_VOLATILE (fndecl)
       /* Don't warn for main().  */
       && !MAIN_NAME_P (DECL_NAME (fndecl))
       /* Or if they didn't actually specify a return type.  */
@@ -7829,6 +8161,25 @@ finish_function (void)
       TREE_NO_WARNING (fndecl) = 1;
     }
 
+  /* Complain about parameters that are only set, but never otherwise used.  */
+  if (warn_unused_but_set_parameter)
+    {
+      tree decl;
+
+      for (decl = DECL_ARGUMENTS (fndecl);
+          decl;
+          decl = DECL_CHAIN (decl))
+       if (TREE_USED (decl)
+           && TREE_CODE (decl) == PARM_DECL
+           && !DECL_READ_P (decl)
+           && DECL_NAME (decl)
+           && !DECL_ARTIFICIAL (decl)
+           && !TREE_NO_WARNING (decl))
+         warning_at (DECL_SOURCE_LOCATION (decl),
+                     OPT_Wunused_but_set_parameter,
+                     "parameter %qD set but not used", decl);
+    }
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -7837,7 +8188,7 @@ finish_function (void)
   c_determine_visibility (fndecl);
 
   /* For GNU C extern inline functions disregard inline limits.  */
-  if (DECL_EXTERNAL (fndecl) 
+  if (DECL_EXTERNAL (fndecl)
       && DECL_DECLARED_INLINE_P (fndecl))
     DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
 
@@ -7850,8 +8201,8 @@ finish_function (void)
     {
       if (!decl_function_context (fndecl))
        {
+         invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
          c_genericize (fndecl);
-         c_gimple_diagnostics_recursively (fndecl);
 
          /* ??? Objc emits functions after finalizing the compilation unit.
             This should be cleaned up later and this conditional removed.  */
@@ -7979,7 +8330,7 @@ void
 c_push_function_context (void)
 {
   struct language_function *p;
-  p = GGC_NEW (struct language_function);
+  p = ggc_alloc_language_function ();
   cfun->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
@@ -8027,21 +8378,6 @@ c_pop_function_context (void)
   warn_about_return_type = p->warn_about_return_type;
 }
 
-/* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
-
-void
-c_dup_lang_specific_decl (tree decl)
-{
-  struct lang_decl *ld;
-
-  if (!DECL_LANG_SPECIFIC (decl))
-    return;
-
-  ld = GGC_NEW (struct lang_decl);
-  memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
-  DECL_LANG_SPECIFIC (decl) = ld;
-}
-
 /* The functions below are required for functionality of doing
    function at once processing in the C front end. Currently these
    functions are not called from anywhere in the C front end, but as
@@ -8212,9 +8548,29 @@ build_null_declspecs (void)
   ret->volatile_p = false;
   ret->restrict_p = false;
   ret->saturating_p = false;
+  ret->address_space = ADDR_SPACE_GENERIC;
   return ret;
 }
 
+/* Add the address space ADDRSPACE to the declaration specifiers
+   SPECS, returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
+{
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+
+  if (!ADDR_SPACE_GENERIC_P (specs->address_space)
+      && specs->address_space != as)
+    error ("incompatible address space qualifiers %qs and %qs",
+          c_addr_space_name (as),
+          c_addr_space_name (specs->address_space));
+  else
+    specs->address_space = as;
+  return specs;
+}
+
 /* Add the type qualifier QUAL to the declaration specifiers SPECS,
    returning SPECS.  */
 
@@ -8254,7 +8610,8 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
+declspecs_add_type (location_t loc, struct c_declspecs *specs,
+                   struct c_typespec spec)
 {
   tree type = spec.spec;
   specs->non_sc_seen_p = true;
@@ -8271,7 +8628,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
       enum rid i = C_RID_CODE (type);
       if (specs->type)
        {
-         error ("two or more data types in declaration specifiers");
+         error_at (loc, "two or more data types in declaration specifiers");
          return specs;
        }
       if ((int) i <= (int) RID_LAST_MODIFIER)
@@ -8283,203 +8640,271 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
            case RID_LONG:
              if (specs->long_long_p)
                {
-                 error ("%<long long long%> is too long for GCC");
+                 error_at (loc, "%<long long long%> is too long for GCC");
                  break;
                }
              if (specs->long_p)
                {
                  if (specs->typespec_word == cts_double)
                    {
-                     error ("both %<long long%> and %<double%> in "
-                            "declaration specifiers");
+                     error_at (loc,
+                               ("both %<long long%> and %<double%> in "
+                                "declaration specifiers"));
                      break;
                    }
-                 pedwarn_c90 (input_location, OPT_Wlong_long, 
+                 pedwarn_c90 (loc, OPT_Wlong_long,
                               "ISO C90 does not support %<long long%>");
                  specs->long_long_p = 1;
                  break;
                }
              if (specs->short_p)
-               error ("both %<long%> and %<short%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<short%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_void)
-               error ("both %<long%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_int128)
+                 error_at (loc,
+                           ("both %<long%> and %<__int128%> in "
+                            "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<long%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_char)
-               error ("both %<long%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<char%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_float)
-               error ("both %<long%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat32)
-               error ("both %<long%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<long%> and %<_Decimal64%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<long%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else
                specs->long_p = true;
              break;
            case RID_SHORT:
              dupe = specs->short_p;
              if (specs->long_p)
-               error ("both %<long%> and %<short%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<short%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_void)
-               error ("both %<short%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_int128)
+               error_at (loc,
+                         ("both %<short%> and %<__int128%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<short%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_char)
-               error ("both %<short%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<char%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_float)
-               error ("both %<short%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_double)
-               error ("both %<short%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat32)
-                error ("both %<short%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+                error_at (loc,
+                         ("both %<short%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<short%> and %<_Decimal64%> in "
-                                       "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<short%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else
                specs->short_p = true;
              break;
            case RID_SIGNED:
              dupe = specs->signed_p;
              if (specs->unsigned_p)
-               error ("both %<signed%> and %<unsigned%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<unsigned%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_void)
-               error ("both %<signed%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<signed%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_float)
-               error ("both %<signed%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_double)
-               error ("both %<signed%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat32)
-               error ("both %<signed%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<signed%> and %<_Decimal64%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<signed%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else
                specs->signed_p = true;
              break;
            case RID_UNSIGNED:
              dupe = specs->unsigned_p;
              if (specs->signed_p)
-               error ("both %<signed%> and %<unsigned%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<unsigned%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_void)
-               error ("both %<unsigned%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<unsigned%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_float)
-               error ("both %<unsigned%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_double)
-               error ("both %<unsigned%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<double%> in "
+                          "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-               error ("both %<unsigned%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<unsigned%> and %<_Decimal64%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<unsigned%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else
                specs->unsigned_p = true;
              break;
            case RID_COMPLEX:
              dupe = specs->complex_p;
              if (!flag_isoc99 && !in_system_header)
-               pedwarn (input_location, OPT_pedantic, "ISO C90 does not support complex types");
+               pedwarn (loc, OPT_pedantic,
+                        "ISO C90 does not support complex types");
              if (specs->typespec_word == cts_void)
-               error ("both %<complex%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<complex%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Bool%> in "
+                          "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-               error ("both %<complex%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<complex%> and %<_Decimal64%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<complex%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_fract)
-               error ("both %<complex%> and %<_Fract%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Fract%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_accum)
-               error ("both %<complex%> and %<_Accum%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Accum%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<complex%> and %<_Sat%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Sat%> in "
+                          "declaration specifiers"));
              else
                specs->complex_p = true;
              break;
            case RID_SAT:
              dupe = specs->saturating_p;
-             pedwarn (input_location, OPT_pedantic, "ISO C does not support saturating types");
-             if (specs->typespec_word == cts_void)
-               error ("both %<_Sat%> and %<void%> in "
-                      "declaration specifiers");
+             pedwarn (loc, OPT_pedantic,
+                      "ISO C does not support saturating types");
+             if (specs->typespec_word == cts_int128)
+               {
+                 error_at (loc,
+                           ("both %<_Sat%> and %<__int128%> in "
+                            "declaration specifiers"));
+               }
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<_Sat%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_bool)
-               error ("both %<_Sat%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_char)
-               error ("both %<_Sat%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<char%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_int)
-               error ("both %<_Sat%> and %<int%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<int%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_float)
-               error ("both %<_Sat%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_double)
-               error ("both %<_Sat%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<double%> in "
+                          "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-               error ("both %<_Sat%> and %<_Decimal32%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat64)
-               error ("both %<_Sat%> and %<_Decimal64%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
              else if (specs->typespec_word == cts_dfloat128)
-               error ("both %<_Sat%> and %<_Decimal128%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
              else if (specs->complex_p)
-               error ("both %<_Sat%> and %<complex%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<complex%> in "
+                          "declaration specifiers"));
              else
                specs->saturating_p = true;
              break;
@@ -8488,127 +8913,179 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
            }
 
          if (dupe)
-           error ("duplicate %qE", type);
+           error_at (loc, "duplicate %qE", type);
 
          return specs;
        }
       else
        {
          /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-            "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
+            "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
          if (specs->typespec_word != cts_none)
            {
-             error ("two or more data types in declaration specifiers");
+             error_at (loc,
+                       "two or more data types in declaration specifiers");
              return specs;
            }
          switch (i)
            {
+           case RID_INT128:
+             if (int128_integer_type_node == NULL_TREE)
+               {
+                 error_at (loc, "%<__int128%> is not supported for this target");
+                 return specs;
+               }
+             if (!in_system_header)
+               pedwarn (loc, OPT_pedantic,
+                        "ISO C does not support %<__int128%> type");
+
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<__int128%> and %<long%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<__int128%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<__int128%> and %<short%> in "
+                          "declaration specifiers"));
+             else
+               specs->typespec_word = cts_int128;
+             return specs;
            case RID_VOID:
              if (specs->long_p)
-               error ("both %<long%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->short_p)
-               error ("both %<short%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->signed_p)
-               error ("both %<signed%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->unsigned_p)
-               error ("both %<unsigned%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->complex_p)
-               error ("both %<complex%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<void%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<_Sat%> and %<void%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<void%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_void;
              return specs;
            case RID_BOOL:
              if (specs->long_p)
-               error ("both %<long%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->short_p)
-               error ("both %<short%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->signed_p)
-               error ("both %<signed%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->unsigned_p)
-               error ("both %<unsigned%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->complex_p)
-               error ("both %<complex%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<complex%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<_Sat%> and %<_Bool%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Bool%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_bool;
              return specs;
            case RID_CHAR:
              if (specs->long_p)
-               error ("both %<long%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<char%> in "
+                          "declaration specifiers"));
              else if (specs->short_p)
-               error ("both %<short%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<char%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<_Sat%> and %<char%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<char%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_char;
              return specs;
            case RID_INT:
              if (specs->saturating_p)
-               error ("both %<_Sat%> and %<int%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<int%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_int;
              return specs;
            case RID_FLOAT:
              if (specs->long_p)
-               error ("both %<long%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->short_p)
-               error ("both %<short%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->signed_p)
-               error ("both %<signed%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->unsigned_p)
-               error ("both %<unsigned%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<float%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<_Sat%> and %<float%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<float%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_float;
              return specs;
            case RID_DOUBLE:
              if (specs->long_long_p)
-               error ("both %<long long%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<long long%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->short_p)
-               error ("both %<short%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<short%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->signed_p)
-               error ("both %<signed%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<signed%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->unsigned_p)
-               error ("both %<unsigned%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<unsigned%> and %<double%> in "
+                          "declaration specifiers"));
              else if (specs->saturating_p)
-               error ("both %<_Sat%> and %<double%> in "
-                      "declaration specifiers");
+               error_at (loc,
+                         ("both %<_Sat%> and %<double%> in "
+                          "declaration specifiers"));
              else
                specs->typespec_word = cts_double;
              return specs;
            case RID_DFLOAT32:
            case RID_DFLOAT64:
            case RID_DFLOAT128:
-             { 
+             {
                const char *str;
                if (i == RID_DFLOAT32)
                  str = "_Decimal32";
@@ -8617,26 +9094,40 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
                else
                  str = "_Decimal128";
                if (specs->long_long_p)
-                 error ("both %<long long%> and %<%s%> in "
-                        "declaration specifiers", str);
+                 error_at (loc,
+                           ("both %<long long%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                if (specs->long_p)
-                 error ("both %<long%> and %<%s%> in "
-                        "declaration specifiers", str);
+                 error_at (loc,
+                           ("both %<long%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                else if (specs->short_p)
-                 error ("both %<short%> and %<%s%> in "
-                        "declaration specifiers", str);
+                 error_at (loc,
+                           ("both %<short%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                else if (specs->signed_p)
-                 error ("both %<signed%> and %<%s%> in "
-                        "declaration specifiers", str);
+                 error_at (loc,
+                           ("both %<signed%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                else if (specs->unsigned_p)
-                 error ("both %<unsigned%> and %<%s%> in "
-                        "declaration specifiers", str);
+                 error_at (loc,
+                           ("both %<unsigned%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                 else if (specs->complex_p)
-                  error ("both %<complex%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+                           ("both %<complex%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                 else if (specs->saturating_p)
-                  error ("both %<_Sat%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+                           ("both %<_Sat%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                else if (i == RID_DFLOAT32)
                  specs->typespec_word = cts_dfloat32;
                else if (i == RID_DFLOAT64)
@@ -8645,8 +9136,10 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
                  specs->typespec_word = cts_dfloat128;
              }
              if (!targetm.decimal_float_supported_p ())
-               error ("decimal floating point not supported for this target");
-             pedwarn (input_location, OPT_pedantic, 
+               error_at (loc,
+                         ("decimal floating point not supported "
+                          "for this target"));
+             pedwarn (loc, OPT_pedantic,
                       "ISO C does not support decimal floating point");
              return specs;
            case RID_FRACT:
@@ -8658,16 +9151,19 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
                else
                  str = "_Accum";
                 if (specs->complex_p)
-                  error ("both %<complex%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+                           ("both %<complex%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
                else if (i == RID_FRACT)
                    specs->typespec_word = cts_fract;
                else
                    specs->typespec_word = cts_accum;
              }
              if (!targetm.fixed_point_supported_p ())
-               error ("fixed-point types not supported for this target");
-             pedwarn (input_location, OPT_pedantic, 
+               error_at (loc,
+                         "fixed-point types not supported for this target");
+             pedwarn (loc, OPT_pedantic,
                       "ISO C does not support fixed-point types");
              return specs;
            default:
@@ -8685,7 +9181,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
   if (specs->type || specs->typespec_word != cts_none
       || specs->long_p || specs->short_p || specs->signed_p
       || specs->unsigned_p || specs->complex_p)
-    error ("two or more data types in declaration specifiers");
+    error_at (loc, "two or more data types in declaration specifiers");
   else if (TREE_CODE (type) == TYPE_DECL)
     {
       if (TREE_TYPE (type) == error_mark_node)
@@ -8696,13 +9192,26 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
          specs->decl_attr = DECL_ATTRIBUTES (type);
          specs->typedef_p = true;
          specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+
+         /* If this typedef name is defined in a struct, then a C++
+            lookup would return a different value.  */
+         if (warn_cxx_compat
+             && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
+           warning_at (loc, OPT_Wc___compat,
+                       "C++ lookup of %qD would return a field, not a type",
+                       type);
+
+         /* If we are parsing a struct, record that a struct field
+            used a typedef.  */
+         if (warn_cxx_compat && struct_parse_info != NULL)
+           VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
        }
     }
   else if (TREE_CODE (type) == IDENTIFIER_NODE)
     {
       tree t = lookup_name (type);
       if (!t || TREE_CODE (t) != TYPE_DECL)
-       error ("%qE fails to be a typedef or built in type", type);
+       error_at (loc, "%qE fails to be a typedef or built in type", type);
       else if (TREE_TYPE (t) == error_mark_node)
        ;
       else
@@ -8745,7 +9254,7 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
              && C_IS_RESERVED_WORD (scspec));
   i = C_RID_CODE (scspec);
   if (specs->non_sc_seen_p)
-    warning (OPT_Wold_style_declaration, 
+    warning (OPT_Wold_style_declaration,
              "%qE is not at beginning of declaration", scspec);
   switch (i)
     {
@@ -8867,7 +9376,7 @@ finish_declspecs (struct c_declspecs *specs)
       else if (specs->complex_p)
        {
          specs->typespec_word = cts_double;
-         pedwarn (input_location, OPT_pedantic, 
+         pedwarn (input_location, OPT_pedantic,
                   "ISO C does not support plain %<complex%> meaning "
                   "%<double complex%>");
        }
@@ -8912,7 +9421,20 @@ finish_declspecs (struct c_declspecs *specs)
        specs->type = char_type_node;
       if (specs->complex_p)
        {
-         pedwarn (input_location, OPT_pedantic, 
+         pedwarn (input_location, OPT_pedantic,
+                  "ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_int128:
+      gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      specs->type = (specs->unsigned_p
+                    ? int128_unsigned_type_node
+                    : int128_integer_type_node);
+      if (specs->complex_p)
+       {
+         pedwarn (input_location, OPT_pedantic,
                   "ISO C does not support complex integer types");
          specs->type = build_complex_type (specs->type);
        }
@@ -8938,7 +9460,7 @@ finish_declspecs (struct c_declspecs *specs)
                       : integer_type_node);
       if (specs->complex_p)
        {
-         pedwarn (input_location, OPT_pedantic, 
+         pedwarn (input_location, OPT_pedantic,
                   "ISO C does not support complex integer types");
          specs->type = build_complex_type (specs->type);
        }
@@ -9082,7 +9604,7 @@ c_write_global_declarations_1 (tree globals)
   bool reconsider;
 
   /* Process the decls in the order they were written.  */
-  for (decl = globals; decl; decl = TREE_CHAIN (decl))
+  for (decl = globals; decl; decl = DECL_CHAIN (decl))
     {
       /* Check for used but undefined static functions using the C
         standard's definition of "used", and set TREE_NO_WARNING so
@@ -9103,12 +9625,12 @@ c_write_global_declarations_1 (tree globals)
   do
     {
       reconsider = false;
-      for (decl = globals; decl; decl = TREE_CHAIN (decl))
+      for (decl = globals; decl; decl = DECL_CHAIN (decl))
        reconsider |= wrapup_global_declaration_2 (decl);
     }
   while (reconsider);
 
-  for (decl = globals; decl; decl = TREE_CHAIN (decl))
+  for (decl = globals; decl; decl = DECL_CHAIN (decl))
     check_global_declaration_1 (decl);
 }
 
@@ -9120,10 +9642,47 @@ c_write_global_declarations_2 (tree globals)
 {
   tree decl;
 
-  for (decl = globals; decl ; decl = TREE_CHAIN (decl))
+  for (decl = globals; decl ; decl = DECL_CHAIN (decl))
     debug_hooks->global_decl (decl);
 }
 
+/* Callback to collect a source_ref from a DECL.  */
+
+static void
+collect_source_ref_cb (tree decl)
+{
+  if (!DECL_IS_BUILTIN (decl))
+    collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
+}
+
+/* Collect all references relevant to SOURCE_FILE.  */
+
+static void
+collect_all_refs (const char *source_file)
+{
+  tree t;
+
+  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+    collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
+}
+
+/* Iterate over all global declarations and call CALLBACK.  */
+
+static void
+for_each_global_decl (void (*callback) (tree decl))
+{
+  tree t;
+  tree decls;
+  tree decl;
+
+  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+    { 
+      decls = DECL_INITIAL (t);
+      for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
+       callback (decl);
+    }
+}
+
 /* Preserve the external declarations scope across a garbage collect.  */
 static GTY(()) tree ext_block;
 
@@ -9136,16 +9695,23 @@ c_write_global_declarations (void)
   if (pch_file)
     return;
 
-  /* Don't waste time on further processing if -fsyntax-only or we've
-     encountered errors.  */
-  if (flag_syntax_only || errorcount || sorrycount)
-    return;
-
   /* Close the external scope.  */
   ext_block = pop_scope ();
   external_scope = 0;
   gcc_assert (!current_scope);
 
+  /* Handle -fdump-ada-spec[-slim]. */
+  if (dump_enabled_p (TDI_ada))
+    {
+      /* Build a table of files to generate specs for */
+      if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+       collect_source_ref (main_input_filename);
+      else
+       for_each_global_decl (collect_source_ref_cb);
+
+      dump_ada_specs (collect_all_refs, NULL);
+    }
+
   if (ext_block)
     {
       tree tmp = BLOCK_VARS (ext_block);
@@ -9160,20 +9726,20 @@ c_write_global_declarations (void)
 
   /* Process all file scopes in this compilation, and the external_scope,
      through wrapup_global_declarations and check_global_declarations.  */
-  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+  for (t = all_translation_units; t; t = DECL_CHAIN (t))
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
   /* We're done parsing; proceed to optimize and emit assembly.
      FIXME: shouldn't be the front end's responsibility to call this.  */
-  cgraph_optimize ();
+  cgraph_finalize_compilation_unit ();
 
   /* After cgraph has had a chance to emit everything that's going to
      be emitted, output debug information for globals.  */
-  if (errorcount == 0 && sorrycount == 0)
+  if (!seen_error ())
     {
       timevar_push (TV_SYMOUT);
-      for (t = all_translation_units; t; t = TREE_CHAIN (t))
+      for (t = all_translation_units; t; t = DECL_CHAIN (t))
        c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
       c_write_global_declarations_2 (BLOCK_VARS (ext_block));
       timevar_pop (TV_SYMOUT);
@@ -9182,4 +9748,23 @@ c_write_global_declarations (void)
   ext_block = NULL;
 }
 
+/* Register reserved keyword WORD as qualifier for address space AS.  */
+
+void
+c_register_addr_space (const char *word, addr_space_t as)
+{
+  int rid = RID_FIRST_ADDR_SPACE + as;
+  tree id;
+
+  /* Address space qualifiers are only supported
+     in C with GNU extensions enabled.  */
+  if (c_dialect_objc () || flag_no_asm)
+    return;
+
+  id = get_identifier (word);
+  C_SET_RID_CODE (id, rid);
+  C_IS_RESERVED_WORD (id) = 1;
+  ridpointers [rid] = id;
+}
+
 #include "gt-c-decl.h"