diff gcc/c-decl.c @ 69:1b10fe6932e1

merge 69
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Sun, 21 Aug 2011 07:53:12 +0900
parents 326d9e06c2e3 f6334be47118
children b81903832de2
line wrap: on
line diff
--- a/gcc/c-decl.c	Tue Dec 14 03:58:33 2010 +0900
+++ b/gcc/c-decl.c	Sun Aug 21 07:53:12 2011 +0900
@@ -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,33 +34,28 @@
 #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-objc.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"
@@ -70,8 +65,8 @@
 tree cbc_return_f;
 location_t cbc_return;
 #endif
-
 #include "plugin.h"
+#include "c-family/c-ada-spec.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -131,12 +126,6 @@
 tree c_break_label;
 tree c_cont_label;
 
-/* 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.  */
-
-static GTY(()) tree all_translation_units;
-
 /* A list of decls to be made automatically visible in each file scope.  */
 static GTY(()) tree visible_builtins;
 
@@ -422,6 +411,13 @@
      up searching for labels when popping scopes, particularly since
      labels are normally only found at function scope.  */
   BOOL_BITFIELD has_label_bindings : 1;
+
+  /* True if we should issue a warning if a goto statement crosses any
+     of the bindings.  We still need to check the list of bindings to
+     find the specific ones we need to warn about.  This is true if
+     decl_jump_unsafe would return true for any of the bindings.  This
+     is used to avoid looping over all the bindings unnecessarily.  */
+  BOOL_BITFIELD has_jump_unsafe_decl : 1;
 };
 
 /* The scope currently in effect.  */
@@ -572,6 +568,31 @@
   return t;
 }
 
+/* Return true if we will want to say something if a goto statement
+   crosses DECL.  */
+
+static bool
+decl_jump_unsafe (tree decl)
+{
+  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+    return false;
+
+  /* Always warn about crossing variably modified types.  */
+  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
+      && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+    return true;
+
+  /* Otherwise, only warn if -Wgoto-misses-init and this is an
+     initialized automatic decl.  */
+  if (warn_jump_misses_init
+      && TREE_CODE (decl) == VAR_DECL
+      && !TREE_STATIC (decl)
+      && DECL_INITIAL (decl) != NULL_TREE)
+    return true;
+
+  return false;
+}
+
 
 void
 c_print_identifier (FILE *file, tree node, int indent)
@@ -603,7 +624,7 @@
       binding_freelist = b->prev;
     }
   else
-    b = GGC_NEW (struct c_binding);
+    b = ggc_alloc_c_binding ();
 
   b->shadowed = 0;
   b->decl = decl;
@@ -620,6 +641,9 @@
   b->prev = scope->bindings;
   scope->bindings = b;
 
+  if (decl_jump_unsafe (decl))
+    scope->has_jump_unsafe_decl = 1;
+
   if (!name)
     return;
 
@@ -717,7 +741,7 @@
 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;
@@ -776,31 +800,6 @@
   p->left_stmt_expr = false;
 }
 
-/* Return true if we will want to say something if a goto statement
-   crosses DECL.  */
-
-static bool
-decl_jump_unsafe (tree decl)
-{
-  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
-    return false;
-
-  /* Always warn about crossing variably modified types.  */
-  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
-      && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-    return true;
-
-  /* Otherwise, only warn if -Wgoto-misses-init and this is an
-     initialized automatic decl.  */
-  if (warn_jump_misses_init
-      && TREE_CODE (decl) == VAR_DECL
-      && !TREE_STATIC (decl)
-      && DECL_INITIAL (decl) != NULL_TREE)
-    return true;
-
-  return false;
-}
-
 /* Update spot bindings P as we pop out of SCOPE.  Return true if we
    should push decls for a label.  */
 
@@ -941,7 +940,7 @@
       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)
@@ -980,44 +979,51 @@
   while (s != NULL)
     {
       if (s->has_label_bindings)
-    {
-      struct c_binding *b;
-
-      for (b = s->bindings; b != NULL; b = b->prev)
-        {
-          struct c_label_vars *label_vars;
-          struct c_binding *b1;
-          unsigned int ix;
-          struct c_goto_bindings *g;
-
-          if (TREE_CODE (b->decl) != LABEL_DECL)
-        continue;
-          label_vars = b->u.label;
-
-          b1 = label_vars->label_bindings.bindings_in_scope;
-          if (update_spot_bindings (scope, &label_vars->label_bindings))
-        {
-          /* This label is defined in this scope.  */
-          for (; b1 != NULL;  b1 = b1->prev)
-            {
-              /* A goto from later in the function to this
-             label will never see the initialization of
-             B1, if any.  Save it to issue a warning if
-             needed.  */
-              if (decl_jump_unsafe (b1->decl))
-            VEC_safe_push (tree, gc, label_vars->decls_in_scope,
-                       b1->decl);
-            }
-        }
-
-          /* 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)
-        update_spot_bindings (scope, &g->goto_bindings);
-        }
-    }
+	{
+	  struct c_binding *b;
+
+	  for (b = s->bindings; b != NULL; b = b->prev)
+	    {
+	      struct c_label_vars *label_vars;
+	      struct c_binding *b1;
+	      bool hjud;
+	      unsigned int ix;
+	      struct c_goto_bindings *g;
+
+	      if (TREE_CODE (b->decl) != LABEL_DECL)
+		continue;
+	      label_vars = b->u.label;
+
+	      b1 = label_vars->label_bindings.bindings_in_scope;
+	      if (label_vars->label_bindings.scope == NULL)
+		hjud = false;
+	      else
+		hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl;
+	      if (update_spot_bindings (scope, &label_vars->label_bindings))
+		{
+		  /* This label is defined in this scope.  */
+		  if (hjud)
+		    {
+		      for (; b1 != NULL; b1 = b1->prev)
+			{
+			  /* A goto from later in the function to this
+			     label will never see the initialization
+			     of B1, if any.  Save it to issue a
+			     warning if needed.  */
+			  if (decl_jump_unsafe (b1->decl))
+			    VEC_safe_push (tree, gc,
+					   label_vars->decls_in_scope,
+					   b1->decl);
+			}
+		    }
+		}
+
+	      /* Update the bindings of any goto statements associated
+		 with this label.  */
+	      FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+		update_spot_bindings (scope, &g->goto_bindings);
+	    }
+	}
 
       /* Don't search beyond the current function.  */
       if (s == current_function_scope)
@@ -1087,10 +1093,7 @@
     context = current_function_decl;
   else if (scope == file_scope)
     {
-      tree file_decl = build_decl (UNKNOWN_LOCATION,
-                   TRANSLATION_UNIT_DECL, 0, 0);
-      TREE_CHAIN (file_decl) = all_translation_units;
-      all_translation_units = file_decl;
+      tree file_decl = build_translation_unit_decl (NULL_TREE);
       context = file_decl;
     }
   else
@@ -1101,159 +1104,166 @@
     {
       p = b->decl;
       switch (TREE_CODE (p))
-    {
-    case LABEL_DECL:
-      /* Warnings for unused labels, errors for undefined labels.  */
-      if (TREE_USED (p) && !DECL_INITIAL (p))
-        {
-          error ("label %q+D used but not defined", p);
-          DECL_INITIAL (p) = error_mark_node;
-        }
-      else
-        warn_for_unused_label (p);
-
-      /* Labels go in BLOCK_VARS.  */
-      TREE_CHAIN (p) = BLOCK_VARS (block);
-      BLOCK_VARS (block) = p;
-      gcc_assert (I_LABEL_BINDING (b->id) == b);
-      I_LABEL_BINDING (b->id) = b->shadowed;
-
-      /* Also pop back to the shadowed label_vars.  */
-      release_tree_vector (b->u.label->decls_in_scope);
-      b->u.label = b->u.label->shadowed;
-      break;
-
-    case ENUMERAL_TYPE:
-    case UNION_TYPE:
-    case RECORD_TYPE:
-      set_type_context (p, context);
-
-      /* Types may not have tag-names, in which case the type
-         appears in the bindings list with b->id NULL.  */
-      if (b->id)
-        {
-          gcc_assert (I_TAG_BINDING (b->id) == b);
-          I_TAG_BINDING (b->id) = b->shadowed;
-        }
-      break;
-
-    case FUNCTION_DECL:
-      /* Propagate TREE_ADDRESSABLE from nested functions to their
-         containing functions.  */
-      if (!TREE_ASM_WRITTEN (p)
-          && DECL_INITIAL (p) != 0
-          && TREE_ADDRESSABLE (p)
-          && DECL_ABSTRACT_ORIGIN (p) != 0
-          && DECL_ABSTRACT_ORIGIN (p) != p)
-        TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
-      if (!DECL_EXTERNAL (p)
-          && !DECL_INITIAL (p)
-          && scope != file_scope
-          && scope != external_scope)
-        {
-          error ("nested function %q+D declared but never defined", p);
-          undef_nested_function = true;
-        }
-      else if (DECL_DECLARED_INLINE_P (p)
-           && TREE_PUBLIC (p)
-           && !DECL_INITIAL (p))
-        {
-          /* C99 6.7.4p6: "a function with external linkage... declared
-         with an inline function specifier ... shall also be defined
-         in the same translation unit."  */
-          if (!flag_gnu89_inline)
-        pedwarn (input_location, 0,
-             "inline function %q+D declared but never defined", p);
-          DECL_EXTERNAL (p) = 1;
-        }
-
-      goto common_symbol;
-
-    case VAR_DECL:
-      /* Warnings for unused variables.  */
-      if (!TREE_USED (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 (b->inner_comp)
-        {
-          error ("type of array %q+D completed incompatibly with"
-             " implicit initialization", p);
-        }
-
-      /* Fall through.  */
-    case TYPE_DECL:
-    case CONST_DECL:
-    common_symbol:
-      /* All of these go in BLOCK_VARS, but only if this is the
-         binding in the home scope.  */
-      if (!b->nested)
-        {
-          TREE_CHAIN (p) = BLOCK_VARS (block);
-          BLOCK_VARS (block) = p;
-        }
-      else if (VAR_OR_FUNCTION_DECL_P (p))
-        {
-          /* For block local externs add a special
-         DECL_EXTERNAL decl for debug info generation.  */
-          tree extp = copy_node (p);
-
-          DECL_EXTERNAL (extp) = 1;
-          TREE_STATIC (extp) = 0;
-          TREE_PUBLIC (extp) = 1;
-          DECL_INITIAL (extp) = NULL_TREE;
-          DECL_LANG_SPECIFIC (extp) = NULL;
-          DECL_CONTEXT (extp) = current_function_decl;
-          if (TREE_CODE (p) == FUNCTION_DECL)
-        {
-          DECL_RESULT (extp) = NULL_TREE;
-          DECL_SAVED_TREE (extp) = NULL_TREE;
-          DECL_STRUCT_FUNCTION (extp) = NULL;
-        }
-          if (b->locus != UNKNOWN_LOCATION)
-        DECL_SOURCE_LOCATION (extp) = b->locus;
-          TREE_CHAIN (extp) = BLOCK_VARS (block);
-          BLOCK_VARS (block) = extp;
-        }
-      /* If this is the file scope, and we are processing more
-         than one translation unit in this compilation, set
-         DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
-         This makes same_translation_unit_p work, and causes
-         static declarations to be given disambiguating suffixes.  */
-      if (scope == file_scope && num_in_fnames > 1)
-        {
-          DECL_CONTEXT (p) = context;
-          if (TREE_CODE (p) == TYPE_DECL)
-        set_type_context (TREE_TYPE (p), context);
-        }
-
-      /* Fall through.  */
-      /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
-         already been put there by store_parm_decls.  Unused-
-         parameter warnings are handled by function.c.
-         error_mark_node obviously does not go in BLOCK_VARS and
-         does not get unused-variable warnings.  */
-    case PARM_DECL:
-    case ERROR_MARK:
-      /* It is possible for a decl not to have a name.  We get
-         here with b->id NULL in this case.  */
-      if (b->id)
-        {
-          gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-          I_SYMBOL_BINDING (b->id) = b->shadowed;
-          if (b->shadowed && b->shadowed->u.type)
-        TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
-        }
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
+	{
+	case LABEL_DECL:
+	  /* Warnings for unused labels, errors for undefined labels.  */
+	  if (TREE_USED (p) && !DECL_INITIAL (p))
+	    {
+	      error ("label %q+D used but not defined", p);
+	      DECL_INITIAL (p) = error_mark_node;
+	    }
+	  else
+	    warn_for_unused_label (p);
+	  /* Labels go in BLOCK_VARS.  */
+	  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;
+
+	  /* Also pop back to the shadowed label_vars.  */
+	  release_tree_vector (b->u.label->decls_in_scope);
+	  b->u.label = b->u.label->shadowed;
+	  break;
+
+	case ENUMERAL_TYPE:
+	case UNION_TYPE:
+	case RECORD_TYPE:
+	  set_type_context (p, context);
+
+	  /* Types may not have tag-names, in which case the type
+	     appears in the bindings list with b->id NULL.  */
+	  if (b->id)
+	    {
+	      gcc_assert (I_TAG_BINDING (b->id) == b);
+	      I_TAG_BINDING (b->id) = b->shadowed;
+	    }
+	  break;
+
+	case FUNCTION_DECL:
+	  /* Propagate TREE_ADDRESSABLE from nested functions to their
+	     containing functions.  */
+	  if (!TREE_ASM_WRITTEN (p)
+	      && DECL_INITIAL (p) != 0
+	      && TREE_ADDRESSABLE (p)
+	      && DECL_ABSTRACT_ORIGIN (p) != 0
+	      && DECL_ABSTRACT_ORIGIN (p) != p)
+	    TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
+	  if (!DECL_EXTERNAL (p)
+	      && !DECL_INITIAL (p)
+	      && scope != file_scope
+	      && scope != external_scope)
+	    {
+	      error ("nested function %q+D declared but never defined", p);
+	      undef_nested_function = true;
+	    }
+	  else if (DECL_DECLARED_INLINE_P (p)
+		   && TREE_PUBLIC (p)
+		   && !DECL_INITIAL (p))
+	    {
+	      /* C99 6.7.4p6: "a function with external linkage... declared
+		 with an inline function specifier ... shall also be defined
+		 in the same translation unit."  */
+	      if (!flag_gnu89_inline)
+		pedwarn (input_location, 0,
+			 "inline function %q+D declared but never defined", p);
+	      DECL_EXTERNAL (p) = 1;
+	    }
+
+	  goto common_symbol;
+
+	case VAR_DECL:
+	  /* Warnings for unused variables.  */
+	  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)
+	    {
+	      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)
+	    {
+	      error ("type of array %q+D completed incompatibly with"
+		     " implicit initialization", p);
+	    }
+
+	  /* Fall through.  */
+	case TYPE_DECL:
+	case CONST_DECL:
+	common_symbol:
+	  /* All of these go in BLOCK_VARS, but only if this is the
+	     binding in the home scope.  */
+	  if (!b->nested)
+	    {
+	      DECL_CHAIN (p) = BLOCK_VARS (block);
+	      BLOCK_VARS (block) = p;
+	    }
+	  else if (VAR_OR_FUNCTION_DECL_P (p))
+	    {
+	      /* For block local externs add a special
+		 DECL_EXTERNAL decl for debug info generation.  */
+	      tree extp = copy_node (p);
+
+
+	      DECL_EXTERNAL (extp) = 1;
+	      TREE_STATIC (extp) = 0;
+	      TREE_PUBLIC (extp) = 1;
+	      DECL_INITIAL (extp) = NULL_TREE;
+	      DECL_LANG_SPECIFIC (extp) = NULL;
+	      DECL_CONTEXT (extp) = current_function_decl;
+	      if (TREE_CODE (p) == FUNCTION_DECL)
+		{
+		  DECL_RESULT (extp) = NULL_TREE;
+		  DECL_SAVED_TREE (extp) = NULL_TREE;
+		  DECL_STRUCT_FUNCTION (extp) = NULL;
+		}
+	      if (b->locus != UNKNOWN_LOCATION)
+		DECL_SOURCE_LOCATION (extp) = b->locus;
+	      DECL_CHAIN (extp) = BLOCK_VARS (block);
+	      BLOCK_VARS (block) = extp;
+	    }
+	  /* If this is the file scope set DECL_CONTEXT of each decl to
+	     the TRANSLATION_UNIT_DECL.  This makes same_translation_unit_p
+	     work.  */
+	  if (scope == file_scope)
+	    {
+	      DECL_CONTEXT (p) = context;
+	      if (TREE_CODE (p) == TYPE_DECL
+		  && TREE_TYPE (p) != error_mark_node)
+		set_type_context (TREE_TYPE (p), context);
+	    }
+
+
+	  /* Fall through.  */
+	  /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
+	     already been put there by store_parm_decls.  Unused-
+	     parameter warnings are handled by function.c.
+	     error_mark_node obviously does not go in BLOCK_VARS and
+	     does not get unused-variable warnings.  */
+	case PARM_DECL:
+	case ERROR_MARK:
+	  /* It is possible for a decl not to have a name.  We get
+	     here with b->id NULL in this case.  */
+	  if (b->id)
+	    {
+	      gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+	      I_SYMBOL_BINDING (b->id) = b->shadowed;
+	      if (b->shadowed && b->shadowed->u.type)
+		TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
+	    }
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
 
@@ -1299,7 +1309,7 @@
 
   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));
 }
@@ -1349,20 +1359,18 @@
     continue;
 
       for (b = scope->bindings; b != NULL; b = b->prev)
-    {
-      struct c_label_vars *label_vars;
-      unsigned int ix;
-      struct c_goto_bindings *g;
-
-      if (TREE_CODE (b->decl) != LABEL_DECL)
-        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)
-        ++g->goto_bindings.stmt_exprs;
-    }
+	{
+	  struct c_label_vars *label_vars;
+	  unsigned int ix;
+	  struct c_goto_bindings *g;
+
+	  if (TREE_CODE (b->decl) != LABEL_DECL)
+	    continue;
+	  label_vars = b->u.label;
+	  ++label_vars->label_bindings.stmt_exprs;
+	  FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+	    ++g->goto_bindings.stmt_exprs;
+	}
     }
 
   if (switch_bindings != NULL)
@@ -1384,32 +1392,30 @@
     continue;
 
       for (b = scope->bindings; b != NULL; b = b->prev)
-    {
-      struct c_label_vars *label_vars;
-      unsigned int ix;
-      struct c_goto_bindings *g;
-
-      if (TREE_CODE (b->decl) != LABEL_DECL)
-        continue;
-      label_vars = b->u.label;
-      --label_vars->label_bindings.stmt_exprs;
-      if (label_vars->label_bindings.stmt_exprs < 0)
-        {
-          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)
-        {
-          --g->goto_bindings.stmt_exprs;
-          if (g->goto_bindings.stmt_exprs < 0)
-        {
-          g->goto_bindings.left_stmt_expr = true;
-          g->goto_bindings.stmt_exprs = 0;
-        }
-        }
-    }
+	{
+	  struct c_label_vars *label_vars;
+	  unsigned int ix;
+	  struct c_goto_bindings *g;
+
+	  if (TREE_CODE (b->decl) != LABEL_DECL)
+	    continue;
+	  label_vars = b->u.label;
+	  --label_vars->label_bindings.stmt_exprs;
+	  if (label_vars->label_bindings.stmt_exprs < 0)
+	    {
+	      label_vars->label_bindings.left_stmt_expr = true;
+	      label_vars->label_bindings.stmt_exprs = 0;
+	    }
+	  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)
+		{
+		  g->goto_bindings.left_stmt_expr = true;
+		  g->goto_bindings.stmt_exprs = 0;
+		}
+	    }
+	}
     }
 
   if (switch_bindings != NULL)
@@ -1522,9 +1528,8 @@
 
   if (TREE_CODE (olddecl) != FUNCTION_DECL
       || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
-      || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
-       ||
-       (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
+      || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == 0)
+	   || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == 0)))
     return;
 
   t = TYPE_ARG_TYPES (oldtype);
@@ -1792,18 +1797,48 @@
 
   /* 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
@@ -1821,16 +1856,16 @@
      can't validate the argument list) the built-in definition is
      overridden, but optionally warn this was a bad choice of name.  */
       if (DECL_BUILT_IN (olddecl)
-      && !C_DECL_DECLARED_BUILTIN (olddecl)
-      && (!TREE_PUBLIC (newdecl)
-          || (DECL_INITIAL (newdecl)
-          && !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
-    {
-      warning (OPT_Wshadow, "declaration of %q+D shadows "
-           "a built-in function", newdecl);
-      /* Discard the old built-in function.  */
-      return false;
-    }
+	  && !C_DECL_DECLARED_BUILTIN (olddecl)
+	  && (!TREE_PUBLIC (newdecl)
+	      || (DECL_INITIAL (newdecl)
+		  && !prototype_p (TREE_TYPE (newdecl)))))
+	{
+	  warning (OPT_Wshadow, "declaration of %q+D shadows "
+		   "a built-in function", newdecl);
+	  /* Discard the old built-in function.  */
+	  return false;
+	}
 
       if (DECL_INITIAL (newdecl))
     {
@@ -1861,13 +1896,13 @@
       /* If we have a prototype after an old-style function definition,
      the argument types must be checked specially.  */
       else if (DECL_INITIAL (olddecl)
-           && !TYPE_ARG_TYPES (oldtype) && TYPE_ARG_TYPES (newtype)
-           && TYPE_ACTUAL_ARG_TYPES (oldtype)
-           && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
-    {
-      locate_old_decl (olddecl);
-      return false;
-    }
+	       && !prototype_p (oldtype) && prototype_p (newtype)
+	       && TYPE_ACTUAL_ARG_TYPES (oldtype)
+	       && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
+	{
+	  locate_old_decl (olddecl);
+	  return false;
+	}
       /* A non-static declaration (even an "extern") followed by a
      static declaration is undefined behavior per C99 6.2.2p3-5,7.
      The same is true for a static forward declaration at block
@@ -2130,9 +2165,9 @@
   bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
                 && DECL_INITIAL (newdecl) != 0);
   bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
-               && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+			   && prototype_p (TREE_TYPE (newdecl)));
   bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
-               && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+			   && prototype_p (TREE_TYPE (olddecl)));
   bool extern_changed = false;
 
   /* For real parm decl following a forward decl, rechain the old decl
@@ -2369,22 +2404,21 @@
 
       /* Also preserve various other info from the definition.  */
       if (!new_is_definition)
-    {
-      tree t;
-      DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-      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))
-        DECL_CONTEXT (t) = newdecl;
-
-      /* See if we've got a function to instantiate from.  */
-      if (DECL_SAVED_TREE (olddecl))
-        DECL_ABSTRACT_ORIGIN (newdecl)
-          = DECL_ABSTRACT_ORIGIN (olddecl);
-    }
+	{
+	  tree t;
+	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
+	  DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+	  DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
+	  DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+	  DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
+	  for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
+	    DECL_CONTEXT (t) = newdecl;
+
+	  /* See if we've got a function to instantiate from.  */
+	  if (DECL_SAVED_TREE (olddecl))
+	    DECL_ABSTRACT_ORIGIN (newdecl)
+	      = DECL_ABSTRACT_ORIGIN (olddecl);
+	}
     }
 
   extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
@@ -2394,6 +2428,12 @@
     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, DECL_CONTEXT and
@@ -2411,9 +2451,6 @@
     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:
@@ -2961,14 +2998,14 @@
     }
   else
     {
-      error_at (loc, "%qE undeclared (first use in this function)", id);
-
+      if (!objc_diagnose_private_ivar (id))
+        error_at (loc, "%qE undeclared (first use in this function)", id);
       if (!already)
-    {
-      error_at (loc, "(Each undeclared identifier is reported only once");
-      error_at (loc, "for each function it appears in.)");
-      already = true;
-    }
+	{
+          inform (loc, "each undeclared identifier is reported only"
+                  " once for each function it appears in");
+	  already = true;
+	}
 
       /* If we are parsing old-style parameter decls, current_function_decl
      will be nonnull but current_function_scope will be null.  */
@@ -2992,7 +3029,7 @@
   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 ();
@@ -3013,7 +3050,7 @@
   tree label;
   struct c_label_vars *label_vars;
 
-  if (current_function_decl == 0)
+  if (current_function_scope == 0)
     {
       error ("label %qE referenced outside of any function", name);
       return 0;
@@ -3090,7 +3127,7 @@
     {
       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);
@@ -3105,7 +3142,7 @@
        ...
        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)
@@ -3157,41 +3194,45 @@
   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;
 
       /* We have a goto to this label.  The goto is going forward.  In
-     g->scope, the goto is going to skip any binding which was
-     defined after g->bindings_in_scope.  */
-      for (b = g->goto_bindings.scope->bindings;
-       b != g->goto_bindings.bindings_in_scope;
-       b = b->prev)
-    {
-      if (decl_jump_unsafe (b->decl))
-        warn_about_goto (g->loc, label, b->decl);
-    }
+	 g->scope, the goto is going to skip any binding which was
+	 defined after g->bindings_in_scope.  */
+      if (g->goto_bindings.scope->has_jump_unsafe_decl)
+	{
+	  for (b = g->goto_bindings.scope->bindings;
+	       b != g->goto_bindings.bindings_in_scope;
+	       b = b->prev)
+	    {
+	      if (decl_jump_unsafe (b->decl))
+		warn_about_goto (g->loc, label, b->decl);
+	    }
+	}
 
       /* We also need to warn about decls defined in any scopes
      between the scope of the label and the scope of the goto.  */
       for (scope = label_vars->label_bindings.scope;
-       scope != g->goto_bindings.scope;
-       scope = scope->outer)
-    {
-      gcc_assert (scope != NULL);
-      if (scope == label_vars->label_bindings.scope)
-        b = label_vars->label_bindings.bindings_in_scope;
-      else
-        b = scope->bindings;
-      for (; b != NULL; b = b->prev)
-        {
-          if (decl_jump_unsafe (b->decl))
-        warn_about_goto (g->loc, label, b->decl);
-        }
-    }
+	   scope != g->goto_bindings.scope;
+	   scope = scope->outer)
+	{
+	  gcc_assert (scope != NULL);
+	  if (scope->has_jump_unsafe_decl)
+	    {
+	      if (scope == label_vars->label_bindings.scope)
+		b = label_vars->label_bindings.bindings_in_scope;
+	      else
+		b = scope->bindings;
+	      for (; b != NULL; b = b->prev)
+		{
+		  if (decl_jump_unsafe (b->decl))
+		    warn_about_goto (g->loc, label, b->decl);
+		}
+	    }
+	}
 
       if (g->goto_bindings.stmt_exprs > 0)
     {
@@ -3305,6 +3346,10 @@
       struct c_binding *b;
 
       gcc_assert (scope != NULL);
+
+      if (!scope->has_jump_unsafe_decl)
+	continue;
+
       for (b = scope->bindings; b != NULL; b = b->prev)
     {
       if (decl_jump_unsafe (b->decl))
@@ -3459,7 +3504,7 @@
      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 ();
 
@@ -3518,10 +3563,10 @@
          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))
+	 the __FUNCTION__ is believed to appear in K&R style function
+	 parameter declarator.  In that case we still don't have
+	 function_scope.  */
+      && (!seen_error () || current_function_scope))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       bind (id, decl, current_function_scope,
@@ -3540,7 +3585,7 @@
   tree   id = DECL_NAME (decl);
 
   const char *name = IDENTIFIER_POINTER (id);
-  C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
 
   /* Should never be called on a symbol with a preexisting meaning.  */
   gcc_assert (!I_SYMBOL_BINDING (id));
@@ -3552,7 +3597,7 @@
      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;
     }
 
@@ -3566,7 +3611,7 @@
   tree   id = DECL_NAME (decl);
 
   const char *name = IDENTIFIER_POINTER (id);
-  C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
 
   /* Should never be called on a symbol with a preexisting meaning.  */
   gcc_assert (!I_SYMBOL_BINDING (id));
@@ -3578,7 +3623,7 @@
      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;
     }
 
@@ -3612,53 +3657,67 @@
       enum tree_code code = TREE_CODE (value);
 
       if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
-    /* Used to test also that TYPE_SIZE (value) != 0.
-       That caused warning for `struct foo;' at top level in the file.  */
-    {
-      tree name = TYPE_NAME (value);
-      tree t;
-
-      found_tag = true;
-
-      if (declspecs->restrict_p)
-        {
-          error ("invalid use of %<restrict%>");
-          warned = 1;
-        }
-
-      if (name == 0)
-        {
-          if (warned != 1 && code != ENUMERAL_TYPE)
-        /* Empty unnamed enum OK */
-        {
-          pedwarn (input_location, 0,
-               "unnamed struct/union that defines no instances");
-          warned = 1;
-        }
-        }
-      else if (!declspecs->tag_defined_p
-           && declspecs->storage_class != csc_none)
-        {
-          if (warned != 1)
-        pedwarn (input_location, 0,
-             "empty declaration with storage class specifier "
-             "does not redeclare tag");
-          warned = 1;
-          pending_xref_error ();
-        }
-      else if (!declspecs->tag_defined_p
-           && (declspecs->const_p
-               || declspecs->volatile_p
-               || declspecs->restrict_p
-               || declspecs->address_space))
-        {
-          if (warned != 1)
-        pedwarn (input_location, 0,
-             "empty declaration with type qualifier "
-              "does not redeclare tag");
-          warned = 1;
-          pending_xref_error ();
-        }
+	/* Used to test also that TYPE_SIZE (value) != 0.
+	   That caused warning for `struct foo;' at top level in the file.  */
+	{
+	  tree name = TYPE_NAME (value);
+	  tree t;
+
+	  found_tag = true;
+
+	  if (declspecs->restrict_p)
+	    {
+	      error ("invalid use of %<restrict%>");
+	      warned = 1;
+	    }
+
+	  if (name == 0)
+	    {
+	      if (warned != 1 && code != ENUMERAL_TYPE)
+		/* Empty unnamed enum OK */
+		{
+		  pedwarn (input_location, 0,
+			   "unnamed struct/union that defines no instances");
+		  warned = 1;
+		}
+	    }
+	  else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+		   && declspecs->storage_class != csc_none)
+	    {
+	      if (warned != 1)
+		pedwarn (input_location, 0,
+			 "empty declaration with storage class specifier "
+			 "does not redeclare tag");
+	      warned = 1;
+	      pending_xref_error ();
+	    }
+	  else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+		   && (declspecs->const_p
+		       || declspecs->volatile_p
+		       || declspecs->restrict_p
+		       || declspecs->address_space))
+	    {
+	      if (warned != 1)
+		pedwarn (input_location, 0,
+			 "empty declaration with type qualifier "
+			  "does not redeclare tag");
+	      warned = 1;
+	      pending_xref_error ();
+	    }
+	  else
+	    {
+	      pending_invalid_xref = 0;
+	      t = lookup_tag (code, name, 1, NULL);
+
+	      if (t == 0)
+		{
+		  t = make_node (code);
+		  pushtag (input_location, name, t);
+		}
+	    }
+	}
       else
         {
           pending_invalid_xref = 0;
@@ -4000,7 +4059,7 @@
      prototypes file (if requested).  */
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0);
+    gen_aux_info_record (decl, 0, 0, prototype_p (TREE_TYPE (decl)));
 
   /* ANSI specifies that a tentative definition which is not merged with
      a non-tentative definition behaves exactly like a definition with an
@@ -4044,16 +4103,16 @@
       if (ce->kind == cdk_pointer)
     ce = declarator->declarator;
       if (ce->kind == cdk_function)
-    {
-      tree args = ce->u.arg_info->parms;
-      for (; args; args = TREE_CHAIN (args))
-        {
-          tree type = TREE_TYPE (args);
-          if (type && INTEGRAL_TYPE_P (type)
-          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-        DECL_ARG_TYPE (args) = integer_type_node;
-        }
-    }
+	{
+	  tree args = ce->u.arg_info->parms;
+	  for (; args; args = DECL_CHAIN (args))
+	    {
+	      tree type = TREE_TYPE (args);
+	      if (type && INTEGRAL_TYPE_P (type)
+		  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+		DECL_ARG_TYPE (args) = integer_type_node;
+	    }
+	}
     }
 
   if (TREE_CODE (decl) == FUNCTION_DECL
@@ -4075,6 +4134,11 @@
     record_inline_static (input_location, current_function_decl,
               decl, csi_modifiable);
 
+  if (c_dialect_objc () 
+      && (TREE_CODE (decl) == VAR_DECL
+          || TREE_CODE (decl) == FUNCTION_DECL))
+      objc_check_global_decl (decl);
+
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
@@ -4088,6 +4152,35 @@
   return tem;
 }
 
+/* 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. */
+
+static void
+diagnose_uninitialized_cst_member (tree decl, tree type)
+{
+  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);
+	}
+
+      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;
    install its initial value.
    If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
@@ -4246,7 +4339,10 @@
     }
 
       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
@@ -4377,35 +4473,43 @@
     {
       tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
       if (attr)
-    {
-      tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
-      tree cleanup_decl = lookup_name (cleanup_id);
-      tree cleanup;
-      VEC(tree,gc) *vec;
-
-      /* Build "cleanup(&decl)" for the destructor.  */
-      cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
-      vec = VEC_alloc (tree, gc, 1);
-      VEC_quick_push (tree, vec, cleanup);
-      cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
-                             cleanup_decl, vec, NULL);
-      VEC_free (tree, gc, vec);
-
-      /* Don't warn about decl unused; the cleanup uses it.  */
-      TREE_USED (decl) = 1;
-      TREE_USED (cleanup_decl) = 1;
-
-      push_cleanup (decl, cleanup, false);
-    }
+	{
+	  tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+	  tree cleanup_decl = lookup_name (cleanup_id);
+	  tree cleanup;
+	  VEC(tree,gc) *vec;
+
+	  /* Build "cleanup(&decl)" for the destructor.  */
+	  cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+	  vec = VEC_alloc (tree, gc, 1);
+	  VEC_quick_push (tree, vec, cleanup);
+	  cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
+	      				     cleanup_decl, vec, NULL);
+	  VEC_free (tree, gc, vec);
+
+	  /* Don't warn about decl unused; the cleanup uses it.  */
+	  TREE_USED (decl) = 1;
+	  TREE_USED (cleanup_decl) = 1;
+	  DECL_READ_P (decl) = 1;
+
+	  push_cleanup (decl, cleanup, false);
+	}
     }
 
   if (warn_cxx_compat
       && TREE_CODE (decl) == VAR_DECL
-      && TREE_READONLY (decl)
       && !DECL_EXTERNAL (decl)
       && DECL_INITIAL (decl) == NULL_TREE)
-    warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
-        "uninitialized const %qD is invalid in C++", decl);
+    {
+      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.  */
@@ -4476,7 +4580,8 @@
   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);
@@ -4485,6 +4590,7 @@
   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);
@@ -4535,7 +4641,9 @@
 void
 check_compound_literal_type (location_t loc, struct c_type_name *type_name)
 {
-  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+  if (warn_cxx_compat
+      && (type_name->specs->typespec_kind == ctsk_tagdef
+          || type_name->specs->typespec_kind == ctsk_tagfirstref))
     warning_at (loc, OPT_Wc___compat,
         "defining a type in a compound literal is invalid in C++");
 }
@@ -4552,9 +4660,9 @@
     case RECORD_TYPE:
       x = TYPE_FIELDS (type);
       if (x == NULL_TREE)
-    return false;
-      while (TREE_CHAIN (x) != NULL_TREE)
-    x = TREE_CHAIN (x);
+	return false;
+      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
@@ -4562,11 +4670,11 @@
     return true;
       return false;
     case UNION_TYPE:
-      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
-    {
-      if (flexible_array_type_p (TREE_TYPE (x)))
-        return true;
-    }
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+	{
+	  if (flexible_array_type_p (TREE_TYPE (x)))
+	    return true;
+	}
       return false;
     default:
     return false;
@@ -4815,6 +4923,8 @@
   tree expr_dummy;
   bool expr_const_operands_dummy;
 
+  if (TREE_CODE (type) == ERROR_MARK)
+    return error_mark_node;
   if (expr == NULL)
     expr = &expr_dummy;
   if (expr_const_operands == NULL)
@@ -5105,411 +5215,415 @@
     }
 
       switch (declarator->kind)
-    {
-    case cdk_attrs:
-      {
-        /* A declarator with embedded attributes.  */
-        tree attrs = declarator->u.attrs;
-        const struct c_declarator *inner_decl;
-        int attr_flags = 0;
-        declarator = declarator->declarator;
-        inner_decl = declarator;
-        while (inner_decl->kind == cdk_attrs)
-          inner_decl = inner_decl->declarator;
-        if (inner_decl->kind == cdk_id)
-          attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-        else if (inner_decl->kind == cdk_function)
-          attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-        else if (inner_decl->kind == cdk_array)
-          attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
-        returned_attrs = decl_attributes (&type,
-                          chainon (returned_attrs, attrs),
-                          attr_flags);
-        break;
-      }
-    case cdk_array:
-      {
-        tree itype = NULL_TREE;
-        tree size = declarator->u.array.dimen;
-        /* The index is a signed object `sizetype' bits wide.  */
-        tree index_type = c_common_signed_type (sizetype);
-
-        array_ptr_quals = declarator->u.array.quals;
-        array_ptr_attrs = declarator->u.array.attrs;
-        array_parm_static = declarator->u.array.static_p;
-        array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
-
-        declarator = declarator->declarator;
-
-        /* Check for some types that there cannot be arrays of.  */
-
-        if (VOID_TYPE_P (type))
-          {
-        if (name)
-          error_at (loc, "declaration of %qE as array of voids", name);
-        else
-          error_at (loc, "declaration of type name as array of voids");
-        type = error_mark_node;
-          }
-
-        if (TREE_CODE (type) == FUNCTION_TYPE)
-          {
-        if (name)
-          error_at (loc, "declaration of %qE as array of functions",
-                    name);
-        else
-          error_at (loc, "declaration of type name as array of "
-                    "functions");
-        type = error_mark_node;
-          }
-
-        if (pedantic && !in_system_header && flexible_array_type_p (type))
-          pedwarn (loc, OPT_pedantic,
-               "invalid use of structure with flexible array member");
-
-        if (size == error_mark_node)
-          type = error_mark_node;
-
-        if (type == error_mark_node)
-          continue;
-
-        /* If size was specified, set ITYPE to a range-type for
-           that size.  Otherwise, ITYPE remains null.  finish_decl
-           may figure it out from an initial value.  */
-
-        if (size)
-          {
-        bool size_maybe_const = true;
-        bool size_int_const = (TREE_CODE (size) == INTEGER_CST
-                       && !TREE_OVERFLOW (size));
-        bool this_size_varies = false;
-
-        /* Strip NON_LVALUE_EXPRs since we aren't using as an
-           lvalue.  */
-        STRIP_TYPE_NOPS (size);
-
-        if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
-          {
-            if (name)
-              error_at (loc, "size of array %qE has non-integer type",
-                name);
-            else
-              error_at (loc,
-                "size of unnamed array has non-integer type");
-            size = integer_one_node;
-          }
-
-        size = c_fully_fold (size, false, &size_maybe_const);
-
-        if (pedantic && size_maybe_const && integer_zerop (size))
-          {
-            if (name)
-              pedwarn (loc, OPT_pedantic,
-                   "ISO C forbids zero-size array %qE", name);
-            else
-              pedwarn (loc, OPT_pedantic,
-                   "ISO C forbids zero-size array");
-          }
-
-        if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
-          {
-            constant_expression_warning (size);
-            if (tree_int_cst_sgn (size) < 0)
-              {
-            if (name)
-              error_at (loc, "size of array %qE is negative", name);
-            else
-              error_at (loc, "size of unnamed array is negative");
-            size = integer_one_node;
-              }
-            /* Handle a size folded to an integer constant but
-               not an integer constant expression.  */
-            if (!size_int_const)
-              {
-            /* If this is a file scope declaration of an
-               ordinary identifier, this is invalid code;
-               diagnosing it here and not subsequently
-               treating the type as variable-length avoids
-               more confusing diagnostics later.  */
-            if ((decl_context == NORMAL || decl_context == FIELD)
-                && current_scope == file_scope)
-              pedwarn (input_location, 0,
-                   "variably modified %qE at file scope",
-                   name);
-            else
-              this_size_varies = size_varies = true;
-            warn_variable_length_array (name, size);
-              }
-          }
-        else if ((decl_context == NORMAL || decl_context == FIELD)
-             && current_scope == file_scope)
-          {
-            error_at (loc, "variably modified %qE at file scope", name);
-            size = integer_one_node;
-          }
-        else
-          {
-            /* Make sure the array size remains visibly
-               nonconstant even if it is (eg) a const variable
-               with known value.  */
-            this_size_varies = size_varies = true;
-            warn_variable_length_array (name, size);
-          }
-
-        if (integer_zerop (size) && !this_size_varies)
-          {
-            /* A zero-length array cannot be represented with
-               an unsigned index type, which is what we'll
-               get with build_index_type.  Create an
-               open-ended range instead.  */
-            itype = build_range_type (sizetype, size, NULL_TREE);
-          }
-        else
-          {
-            /* Arrange for the SAVE_EXPR on the inside of the
-               MINUS_EXPR, which allows the -1 to get folded
-               with the +1 that happens when building TYPE_SIZE.  */
-            if (size_varies)
-              size = c_variable_size (size);
-            if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
-              size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
-                     integer_zero_node, size);
-
-            /* Compute the maximum valid index, that is, size
-               - 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_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
-               cause an overflow (because we subtract 1), the
-               overflow is recorded during the conversion to
-               index_type, before the subtraction.  Handling
-               this case seems like an unnecessary
-               complication.  */
-            if (TREE_CODE (itype) == INTEGER_CST
-            && TREE_OVERFLOW (itype))
-              {
-            if (name)
-              error_at (loc, "size of array %qE is too large",
-                        name);
-            else
-              error_at (loc, "size of unnamed array is too large");
-            type = error_mark_node;
-            continue;
-              }
-
-            itype = build_index_type (itype);
-          }
-        if (this_size_varies)
-          {
-            if (*expr)
-              *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
-                      *expr, size);
-            else
-              *expr = size;
-            *expr_const_operands &= size_maybe_const;
-          }
-          }
-        else if (decl_context == FIELD)
-          {
-        bool flexible_array_member = false;
-        if (array_parm_vla_unspec_p)
-          /* Field names can in fact have function prototype
-             scope so [*] is disallowed here through making
-             the field variably modified, not through being
-             something other than a declaration with function
-             prototype scope.  */
-          size_varies = true;
-        else
-          {
-            const struct c_declarator *t = declarator;
-            while (t->kind == cdk_attrs)
-              t = t->declarator;
-            flexible_array_member = (t->kind == cdk_id);
-          }
-        if (flexible_array_member
-            && pedantic && !flag_isoc99 && !in_system_header)
-          pedwarn (loc, OPT_pedantic,
-               "ISO C90 does not support flexible array members");
-
-        /* ISO C99 Flexible array members are effectively
-           identical to GCC's zero-length array extension.  */
-        if (flexible_array_member || array_parm_vla_unspec_p)
-          itype = build_range_type (sizetype, size_zero_node,
-                        NULL_TREE);
-          }
-        else if (decl_context == PARM)
-          {
-        if (array_parm_vla_unspec_p)
-          {
-            itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
-            size_varies = true;
-          }
-          }
-        else if (decl_context == TYPENAME)
-          {
-        if (array_parm_vla_unspec_p)
-          {
-            /* C99 6.7.5.2p4 */
-            warning (0, "%<[*]%> not in a declaration");
-            /* We use this to avoid messing up with incomplete
-               array types of the same type, that would
-               otherwise be modified below.  */
-            itype = build_range_type (sizetype, size_zero_node,
-                          NULL_TREE);
-            size_varies = true;
-          }
-          }
-
-         /* Complain about arrays of incomplete types.  */
-        if (!COMPLETE_TYPE_P (type))
-          {
-        error_at (loc, "array type has incomplete element type");
-        type = error_mark_node;
-          }
-        else
-        /* When itype is NULL, a shared incomplete array type is
-           returned for all array of a given type.  Elsewhere we
-           make sure we don't complete that type before copying
-           it, but here we want to make sure we don't ever
-           modify the shared type, so we gcc_assert (itype)
-           below.  */
-          {
-        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)
-          {
-        if (size_varies)
-          {
-            /* It is ok to modify type here even if itype is
-               NULL: if size_varies, we're in a
-               multi-dimensional array and the inner type has
-               variable size, so the enclosing shared array type
-               must too.  */
-            if (size && TREE_CODE (size) == INTEGER_CST)
-              type
-            = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-            C_TYPE_VARIABLE_SIZE (type) = 1;
-          }
-
-        /* The GCC extension for zero-length arrays differs from
-           ISO flexible array members in that sizeof yields
-           zero.  */
-        if (size && integer_zerop (size))
-          {
-            gcc_assert (itype);
-            TYPE_SIZE (type) = bitsize_zero_node;
-            TYPE_SIZE_UNIT (type) = size_zero_node;
-          }
-        if (array_parm_vla_unspec_p)
-          {
-            gcc_assert (itype);
-            /* The type is complete.  C99 6.7.5.2p4  */
-            TYPE_SIZE (type) = bitsize_zero_node;
-            TYPE_SIZE_UNIT (type) = size_zero_node;
-          }
-          }
-
-        if (decl_context != PARM
-        && (array_ptr_quals != TYPE_UNQUALIFIED
-            || array_ptr_attrs != NULL_TREE
-            || array_parm_static))
-          {
-        error_at (loc, "static or type qualifiers in non-parameter array declarator");
-        array_ptr_quals = TYPE_UNQUALIFIED;
-        array_ptr_attrs = NULL_TREE;
-        array_parm_static = 0;
-          }
-        break;
-      }
-    case cdk_function:
-      {
-        /* Say it's a definition only for the declarator closest
-           to the identifier, apart possibly from some
-           attributes.  */
-        bool really_funcdef = false;
-        tree arg_types;
-        if (funcdef_flag)
-          {
-        const struct c_declarator *t = declarator->declarator;
-        while (t->kind == cdk_attrs)
-          t = t->declarator;
-        really_funcdef = (t->kind == cdk_id);
-          }
-
-        /* Declaring a function type.  Make sure we have a valid
-           type for the function to return.  */
-        if (type == error_mark_node)
-          continue;
-
-        size_varies = false;
-
-        /* Warn about some types functions can't return.  */
-        if (TREE_CODE (type) == FUNCTION_TYPE)
-          {
-        if (name)
-          error_at (loc, "%qE declared as function returning a "
-                     "function", name);
-        else
-          error_at (loc, "type name declared as function "
-                "returning a function");
-        type = integer_type_node;
-          }
-        if (TREE_CODE (type) == ARRAY_TYPE)
-          {
-        if (name)
-          error_at (loc, "%qE declared as function returning an array",
-                    name);
-        else
-          error_at (loc, "type name declared as function returning "
-                    "an array");
-        type = integer_type_node;
-          }
-        errmsg = targetm.invalid_return_type (type);
-        if (errmsg)
-          {
-        error (errmsg);
-        type = integer_type_node;
-          }
-
-        /* Construct the function type and go to the next
-           inner layer of declarator.  */
-        arg_info = declarator->u.arg_info;
-        arg_types = grokparms (arg_info, really_funcdef);
-        if (really_funcdef)
-          put_pending_sizes (arg_info->pending_sizes);
-
-        /* Type qualifiers before the return type of the function
-           qualify the return type, not the function type.  */
-        if (type_quals)
-          {
-        /* Type qualifiers on a function return type are
-           normally permitted by the standard but have no
-           effect, so give a warning at -Wreturn-type.
-           Qualifiers on a void return type are banned on
-           function definitions in ISO C; GCC used to used
-           them for noreturn functions.  */
-        if (VOID_TYPE_P (type) && really_funcdef)
-          pedwarn (loc, 0,
-               "function definition has qualified void return type");
-        else
-          warning_at (loc, OPT_Wignored_qualifiers,
-               "type qualifiers ignored on function return type");
-
-        type = c_build_qualified_type (type, type_quals);
-          }
-        type_quals = TYPE_UNQUALIFIED;
+	{
+	case cdk_attrs:
+	  {
+	    /* A declarator with embedded attributes.  */
+	    tree attrs = declarator->u.attrs;
+	    const struct c_declarator *inner_decl;
+	    int attr_flags = 0;
+	    declarator = declarator->declarator;
+	    inner_decl = declarator;
+	    while (inner_decl->kind == cdk_attrs)
+	      inner_decl = inner_decl->declarator;
+	    if (inner_decl->kind == cdk_id)
+	      attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+	    else if (inner_decl->kind == cdk_function)
+	      attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+	    else if (inner_decl->kind == cdk_array)
+	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+	    returned_attrs = decl_attributes (&type,
+					      chainon (returned_attrs, attrs),
+					      attr_flags);
+	    break;
+	  }
+	case cdk_array:
+	  {
+	    tree itype = NULL_TREE;
+	    tree size = declarator->u.array.dimen;
+	    /* The index is a signed object `sizetype' bits wide.  */
+	    tree index_type = c_common_signed_type (sizetype);
+
+	    array_ptr_quals = declarator->u.array.quals;
+	    array_ptr_attrs = declarator->u.array.attrs;
+	    array_parm_static = declarator->u.array.static_p;
+	    array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
+
+	    declarator = declarator->declarator;
+
+	    /* Check for some types that there cannot be arrays of.  */
+
+	    if (VOID_TYPE_P (type))
+	      {
+		if (name)
+		  error_at (loc, "declaration of %qE as array of voids", name);
+		else
+		  error_at (loc, "declaration of type name as array of voids");
+		type = error_mark_node;
+	      }
+
+	    if (TREE_CODE (type) == FUNCTION_TYPE)
+	      {
+		if (name)
+		  error_at (loc, "declaration of %qE as array of functions",
+		      	    name);
+		else
+		  error_at (loc, "declaration of type name as array of "
+		            "functions");
+		type = error_mark_node;
+	      }
+	    if (pedantic && !in_system_header && flexible_array_type_p (type))
+	      pedwarn (loc, OPT_pedantic,
+		       "invalid use of structure with flexible array member");
+
+	    if (size == error_mark_node)
+	      type = error_mark_node;
+
+	    if (type == error_mark_node)
+	      continue;
+
+	    /* If size was specified, set ITYPE to a range-type for
+	       that size.  Otherwise, ITYPE remains null.  finish_decl
+	       may figure it out from an initial value.  */
+
+	    if (size)
+	      {
+		bool size_maybe_const = true;
+		bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+				       && !TREE_OVERFLOW (size));
+		bool this_size_varies = false;
+
+		/* Strip NON_LVALUE_EXPRs since we aren't using as an
+		   lvalue.  */
+		STRIP_TYPE_NOPS (size);
+
+		if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+		  {
+		    if (name)
+		      error_at (loc, "size of array %qE has non-integer type",
+			  	name);
+		    else
+		      error_at (loc,
+			  	"size of unnamed array has non-integer type");
+		    size = integer_one_node;
+		  }
+
+		size = c_fully_fold (size, false, &size_maybe_const);
+
+		if (pedantic && size_maybe_const && integer_zerop (size))
+		  {
+		    if (name)
+		      pedwarn (loc, OPT_pedantic,
+			       "ISO C forbids zero-size array %qE", name);
+		    else
+		      pedwarn (loc, OPT_pedantic,
+			       "ISO C forbids zero-size array");
+		  }
+
+		if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
+		  {
+		    constant_expression_warning (size);
+		    if (tree_int_cst_sgn (size) < 0)
+		      {
+			if (name)
+			  error_at (loc, "size of array %qE is negative", name);
+			else
+			  error_at (loc, "size of unnamed array is negative");
+			size = integer_one_node;
+		      }
+		    /* Handle a size folded to an integer constant but
+		       not an integer constant expression.  */
+		    if (!size_int_const)
+		      {
+			/* If this is a file scope declaration of an
+			   ordinary identifier, this is invalid code;
+			   diagnosing it here and not subsequently
+			   treating the type as variable-length avoids
+			   more confusing diagnostics later.  */
+			if ((decl_context == NORMAL || decl_context == FIELD)
+			    && current_scope == file_scope)
+			  pedwarn (input_location, 0,
+				   "variably modified %qE at file scope",
+				   name);
+			else
+			  this_size_varies = size_varies = true;
+			warn_variable_length_array (name, size);
+		      }
+		  }
+		else if ((decl_context == NORMAL || decl_context == FIELD)
+			 && current_scope == file_scope)
+		  {
+		    error_at (loc, "variably modified %qE at file scope", name);
+		    size = integer_one_node;
+		  }
+		else
+		  {
+		    /* Make sure the array size remains visibly
+		       nonconstant even if it is (eg) a const variable
+		       with known value.  */
+		    this_size_varies = size_varies = true;
+		    warn_variable_length_array (name, size);
+		  }
+
+		if (integer_zerop (size) && !this_size_varies)
+		  {
+		    /* A zero-length array cannot be represented with
+		       an unsigned index type, which is what we'll
+		       get with build_index_type.  Create an
+		       open-ended range instead.  */
+		    itype = build_range_type (sizetype, size, NULL_TREE);
+		  }
+		else
+		  {
+		    /* Arrange for the SAVE_EXPR on the inside of the
+		       MINUS_EXPR, which allows the -1 to get folded
+		       with the +1 that happens when building TYPE_SIZE.  */
+		    if (size_varies)
+		      size = c_variable_size (size);
+		    if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+		      size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+				     integer_zero_node, size);
+
+		    /* Compute the maximum valid index, that is, size
+		       - 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_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
+		       cause an overflow (because we subtract 1), the
+		       overflow is recorded during the conversion to
+		       index_type, before the subtraction.  Handling
+		       this case seems like an unnecessary
+		       complication.  */
+		    if (TREE_CODE (itype) == INTEGER_CST
+			&& TREE_OVERFLOW (itype))
+		      {
+			if (name)
+			  error_at (loc, "size of array %qE is too large",
+			            name);
+			else
+			  error_at (loc, "size of unnamed array is too large");
+			type = error_mark_node;
+			continue;
+		      }
+
+		    itype = build_index_type (itype);
+		  }
+		if (this_size_varies)
+		  {
+		    if (*expr)
+		      *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+				      *expr, size);
+		    else
+		      *expr = size;
+		    *expr_const_operands &= size_maybe_const;
+		  }
+	      }
+	    else if (decl_context == FIELD)
+	      {
+		bool flexible_array_member = false;
+		if (array_parm_vla_unspec_p)
+		  /* Field names can in fact have function prototype
+		     scope so [*] is disallowed here through making
+		     the field variably modified, not through being
+		     something other than a declaration with function
+		     prototype scope.  */
+		  size_varies = true;
+		else
+		  {
+		    const struct c_declarator *t = declarator;
+		    while (t->kind == cdk_attrs)
+		      t = t->declarator;
+		    flexible_array_member = (t->kind == cdk_id);
+		  }
+		if (flexible_array_member
+		    && pedantic && !flag_isoc99 && !in_system_header)
+		  pedwarn (loc, OPT_pedantic,
+			   "ISO C90 does not support flexible array members");
+
+		/* ISO C99 Flexible array members are effectively
+		   identical to GCC's zero-length array extension.  */
+		if (flexible_array_member || array_parm_vla_unspec_p)
+		  itype = build_range_type (sizetype, size_zero_node,
+					    NULL_TREE);
+	      }
+	    else if (decl_context == PARM)
+	      {
+		if (array_parm_vla_unspec_p)
+		  {
+		    itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+		    size_varies = true;
+		  }
+	      }
+	    else if (decl_context == TYPENAME)
+	      {
+		if (array_parm_vla_unspec_p)
+		  {
+		    /* C99 6.7.5.2p4 */
+		    warning (0, "%<[*]%> not in a declaration");
+		    /* We use this to avoid messing up with incomplete
+		       array types of the same type, that would
+		       otherwise be modified below.  */
+		    itype = build_range_type (sizetype, size_zero_node,
+					      NULL_TREE);
+		    size_varies = true;
+		  }
+	      }
+
+	     /* Complain about arrays of incomplete types.  */
+	    if (!COMPLETE_TYPE_P (type))
+	      {
+		error_at (loc, "array type has incomplete element type");
+		type = error_mark_node;
+	      }
+	    else
+	    /* When itype is NULL, a shared incomplete array type is
+	       returned for all array of a given type.  Elsewhere we
+	       make sure we don't complete that type before copying
+	       it, but here we want to make sure we don't ever
+	       modify the shared type, so we gcc_assert (itype)
+	       below.  */
+	      {
+		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)
+	      {
+		if (size_varies)
+		  {
+		    /* It is ok to modify type here even if itype is
+		       NULL: if size_varies, we're in a
+		       multi-dimensional array and the inner type has
+		       variable size, so the enclosing shared array type
+		       must too.  */
+		    if (size && TREE_CODE (size) == INTEGER_CST)
+		      type
+			= build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+		    C_TYPE_VARIABLE_SIZE (type) = 1;
+		  }
+
+		/* The GCC extension for zero-length arrays differs from
+		   ISO flexible array members in that sizeof yields
+		   zero.  */
+		if (size && integer_zerop (size))
+		  {
+		    gcc_assert (itype);
+		    type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+		    TYPE_SIZE (type) = bitsize_zero_node;
+		    TYPE_SIZE_UNIT (type) = size_zero_node;
+		    SET_TYPE_STRUCTURAL_EQUALITY (type);
+		  }
+		if (array_parm_vla_unspec_p)
+		  {
+		    gcc_assert (itype);
+		    /* The type is complete.  C99 6.7.5.2p4  */
+		    type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+		    TYPE_SIZE (type) = bitsize_zero_node;
+		    TYPE_SIZE_UNIT (type) = size_zero_node;
+		    SET_TYPE_STRUCTURAL_EQUALITY (type);
+		  }
+	      }
+
+	    if (decl_context != PARM
+		&& (array_ptr_quals != TYPE_UNQUALIFIED
+		    || array_ptr_attrs != NULL_TREE
+		    || array_parm_static))
+	      {
+		error_at (loc, "static or type qualifiers in non-parameter array declarator");
+		array_ptr_quals = TYPE_UNQUALIFIED;
+		array_ptr_attrs = NULL_TREE;
+		array_parm_static = 0;
+	      }
+	    break;
+	  }
+	case cdk_function:
+	  {
+	    /* Say it's a definition only for the declarator closest
+	       to the identifier, apart possibly from some
+	       attributes.  */
+	    bool really_funcdef = false;
+	    tree arg_types;
+	    if (funcdef_flag)
+	      {
+		const struct c_declarator *t = declarator->declarator;
+		while (t->kind == cdk_attrs)
+		  t = t->declarator;
+		really_funcdef = (t->kind == cdk_id);
+	      }
+
+
+	    /* Declaring a function type.  Make sure we have a valid
+	       type for the function to return.  */
+	    if (type == error_mark_node)
+	      continue;
+
+	    size_varies = false;
+
+	    /* Warn about some types functions can't return.  */
+	    if (TREE_CODE (type) == FUNCTION_TYPE)
+	      {
+		if (name)
+		  error_at (loc, "%qE declared as function returning a "
+		      		 "function", name);
+		else
+		  error_at (loc, "type name declared as function "
+			    "returning a function");
+		type = integer_type_node;
+	      }
+	    if (TREE_CODE (type) == ARRAY_TYPE)
+	      {
+		if (name)
+		  error_at (loc, "%qE declared as function returning an array",
+		      	    name);
+		else
+		  error_at (loc, "type name declared as function returning "
+		      	    "an array");
+		type = integer_type_node;
+	      }
+	    errmsg = targetm.invalid_return_type (type);
+	    if (errmsg)
+	      {
+		error (errmsg);
+		type = integer_type_node;
+	      }
+
+	    /* Construct the function type and go to the next
+	       inner layer of declarator.  */
+	    arg_info = declarator->u.arg_info;
+	    arg_types = grokparms (arg_info, really_funcdef);
+	    if (really_funcdef)
+	      put_pending_sizes (arg_info->pending_sizes);
+
+	    /* Type qualifiers before the return type of the function
+	       qualify the return type, not the function type.  */
+	    if (type_quals)
+	      {
+		/* Type qualifiers on a function return type are
+		   normally permitted by the standard but have no
+		   effect, so give a warning at -Wreturn-type.
+		   Qualifiers on a void return type are banned on
+		   function definitions in ISO C; GCC used to used
+		   them for noreturn functions.  */
+		if (VOID_TYPE_P (type) && really_funcdef)
+		  pedwarn (loc, 0,
+			   "function definition has qualified void return type");
+		else
+		  warning_at (loc, OPT_Wignored_qualifiers,
+			   "type qualifiers ignored on function return type");
+
+		type = c_build_qualified_type (type, type_quals);
+	      }
+	    type_quals = TYPE_UNQUALIFIED;
 
 #ifndef noCbC
           if ( declspecs->typespec_word == cts_CbC_code )
@@ -5521,81 +5635,76 @@
             {
               type = build_function_type (type, arg_types);
             }
-
-        declarator = declarator->declarator;
-
-        /* Set the TYPE_CONTEXTs for each tagged type which is local to
-           the formal parameter list of this FUNCTION_TYPE to point to
-           the FUNCTION_TYPE node itself.  */
-        {
-          tree link;
-
-          for (link = arg_info->tags;
-           link;
-           link = TREE_CHAIN (link))
-        TYPE_CONTEXT (TREE_VALUE (link)) = type;
-        }
-        break;
-      }
-    case cdk_pointer:
-      {
-        /* Merge any constancy or volatility into the target type
-           for the pointer.  */
-
-        if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-        && type_quals)
-          pedwarn (loc, OPT_pedantic,
-               "ISO C forbids qualified function types");
-        if (type_quals)
-          type = c_build_qualified_type (type, type_quals);
-        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
-           emitted early enough to dominate all the possible later uses
-           and late enough for the variables on which it depends to have
-           been assigned.
-
-           This is expected to happen automatically when the pointed-to
-           type has a name/declaration of it's own, but special attention
-           is required if the type is anonymous.
-
-           We handle the NORMAL and FIELD contexts here by attaching an
-           artificial TYPE_DECL to such pointed-to type.  This forces the
-           sizes evaluation at a safe point and ensures it is not deferred
-           until e.g. within a deeper conditional context.
-
-           We expect nothing to be needed here for PARM or TYPENAME.
-           Pushing a TYPE_DECL at this point for TYPENAME would actually
-           be incorrect, as we might be in the middle of an expression
-           with side effects on the pointed-to type size "arguments" prior
-           to the pointer declaration point and the fake TYPE_DECL in the
-           enclosing context would force the size evaluation prior to the
-           side effects.  */
-
-        if (!TYPE_NAME (type)
-        && (decl_context == NORMAL || decl_context == FIELD)
-        && variably_modified_type_p (type, NULL_TREE))
-          {
-        tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
-        DECL_ARTIFICIAL (decl) = 1;
-        pushdecl (decl);
-        finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
-        TYPE_NAME (type) = decl;
-          }
-
-        type = build_pointer_type (type);
-
-        /* Process type qualifiers (such as const or volatile)
-           that were given inside the `*'.  */
-        type_quals = declarator->u.pointer_quals;
-
-        declarator = declarator->declarator;
-        break;
-      }
-    default:
-      gcc_unreachable ();
-    }
+	    declarator = declarator->declarator;
+
+	    /* Set the TYPE_CONTEXTs for each tagged type which is local to
+	       the formal parameter list of this FUNCTION_TYPE to point to
+	       the FUNCTION_TYPE node itself.  */
+	    {
+	      c_arg_tag *tag;
+	      unsigned ix;
+
+	      FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+		TYPE_CONTEXT (tag->type) = type;
+	    }
+	    break;
+	  }
+	case cdk_pointer:
+	  {
+	    /* Merge any constancy or volatility into the target type
+	       for the pointer.  */
+	    if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+		&& type_quals)
+	      pedwarn (loc, OPT_pedantic,
+		       "ISO C forbids qualified function types");
+	    if (type_quals)
+	      type = c_build_qualified_type (type, type_quals);
+	    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
+	       emitted early enough to dominate all the possible later uses
+	       and late enough for the variables on which it depends to have
+	       been assigned.
+	       This is expected to happen automatically when the pointed-to
+	       type has a name/declaration of it's own, but special attention
+	       is required if the type is anonymous.
+	       We handle the NORMAL and FIELD contexts here by attaching an
+	       artificial TYPE_DECL to such pointed-to type.  This forces the
+	       sizes evaluation at a safe point and ensures it is not deferred
+	       until e.g. within a deeper conditional context.
+	       We expect nothing to be needed here for PARM or TYPENAME.
+	       Pushing a TYPE_DECL at this point for TYPENAME would actually
+	       be incorrect, as we might be in the middle of an expression
+	       with side effects on the pointed-to type size "arguments" prior
+	       to the pointer declaration point and the fake TYPE_DECL in the
+	       enclosing context would force the size evaluation prior to the
+	       side effects.  */
+
+	    if (!TYPE_NAME (type)
+		&& (decl_context == NORMAL || decl_context == FIELD)
+		&& variably_modified_type_p (type, NULL_TREE))
+	      {
+		tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
+		DECL_ARTIFICIAL (decl) = 1;
+		pushdecl (decl);
+		finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
+		TYPE_NAME (type) = decl;
+	      }
+
+	    type = build_pointer_type (type);
+
+	    /* Process type qualifiers (such as const or volatile)
+	       that were given inside the `*'.  */
+	    type_quals = declarator->u.pointer_quals;
+
+
+	    declarator = declarator->declarator;
+	    break;
+	  }
+	default:
+	  gcc_unreachable ();
+	}
     }
   *decl_attrs = chainon (returned_attrs, *decl_attrs);
 
@@ -5856,83 +5965,78 @@
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
-    if (storage_class == csc_register || threadp)
-      {
-        error_at (loc, "invalid storage class for function %qE", name);
-       }
-    else if (current_scope != file_scope)
-      {
-        /* Function declaration not at file scope.  Storage
-           classes other than `extern' are not allowed, C99
-           6.7.1p5, and `extern' makes no difference.  However,
-           GCC allows 'auto', perhaps with 'inline', to support
-           nested functions.  */
-        if (storage_class == csc_auto)
-        pedwarn (loc, OPT_pedantic,
-             "invalid storage class for function %qE", name);
-        else if (storage_class == csc_static)
-          {
-        error_at (loc, "invalid storage class for function %qE", name);
-        if (funcdef_flag)
-          storage_class = declspecs->storage_class = csc_none;
-        else
-          return 0;
-          }
-      }
-
-    decl = build_decl (declarator->id_loc,
-               FUNCTION_DECL, declarator->u.id, type);
-    decl = build_decl_attribute_variant (decl, decl_attr);
-
-    if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
-      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
-       forbidden by standard C (C99 6.7.1p5) and is interpreted by
-       GCC to signify a forward declaration of a nested function.  */
-    if (storage_class == csc_auto && current_scope != file_scope)
-      DECL_EXTERNAL (decl) = 0;
-    /* In C99, a function which is declared 'inline' with 'extern'
-       is not an external reference (which is confusing).  It
-       means that the later definition of the function must be output
-       in this file, C99 6.7.4p6.  In GNU C89, a function declared
-       'extern inline' is an external reference.  */
-    else if (declspecs->inline_p && storage_class != csc_static)
-      DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
-                  == flag_gnu89_inline);
-    else
-      DECL_EXTERNAL (decl) = !initialized;
-
-    /* Record absence of global scope for `static' or `auto'.  */
-    TREE_PUBLIC (decl)
-      = !(storage_class == csc_static || storage_class == csc_auto);
-
-    /* For a function definition, record the argument information
-       block where store_parm_decls will look for it.  */
-    if (funcdef_flag)
-      current_function_arg_info = arg_info;
-
-    if (declspecs->default_int_p)
-      C_FUNCTION_IMPLICIT_INT (decl) = 1;
-
-    /* Record presence of `inline', if it is reasonable.  */
-    if (flag_hosted && MAIN_NAME_P (declarator->u.id))
-      {
-        if (declspecs->inline_p)
-          pedwarn (loc, 0, "cannot inline function %<main%>");
-      }
-    else if (declspecs->inline_p)
-      /* Record that the function is declared `inline'.  */
-      DECL_DECLARED_INLINE_P (decl) = 1;
+	if (storage_class == csc_register || threadp)
+	  {
+	    error_at (loc, "invalid storage class for function %qE", name);
+	   }
+	else if (current_scope != file_scope)
+	  {
+	    /* Function declaration not at file scope.  Storage
+	       classes other than `extern' are not allowed, C99
+	       6.7.1p5, and `extern' makes no difference.  However,
+	       GCC allows 'auto', perhaps with 'inline', to support
+	       nested functions.  */
+	    if (storage_class == csc_auto)
+		pedwarn (loc, OPT_pedantic,
+			 "invalid storage class for function %qE", name);
+	    else if (storage_class == csc_static)
+	      {
+		error_at (loc, "invalid storage class for function %qE", name);
+		if (funcdef_flag)
+		  storage_class = declspecs->storage_class = csc_none;
+		else
+		  return 0;
+	      }
+	  }
+
+
+	decl = build_decl (declarator->id_loc,
+			   FUNCTION_DECL, declarator->u.id, type);
+	decl = build_decl_attribute_variant (decl, decl_attr);
+
+	if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
+	  pedwarn (loc, OPT_pedantic,
+		   "ISO C forbids qualified function types");
+
+	/* 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
+	   forbidden by standard C (C99 6.7.1p5) and is interpreted by
+	   GCC to signify a forward declaration of a nested function.  */
+	if (storage_class == csc_auto && current_scope != file_scope)
+	  DECL_EXTERNAL (decl) = 0;
+	/* In C99, a function which is declared 'inline' with 'extern'
+	   is not an external reference (which is confusing).  It
+	   means that the later definition of the function must be output
+	   in this file, C99 6.7.4p6.  In GNU C89, a function declared
+	   'extern inline' is an external reference.  */
+	else if (declspecs->inline_p && storage_class != csc_static)
+	  DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
+				  == flag_gnu89_inline);
+	else
+	  DECL_EXTERNAL (decl) = !initialized;
+
+	/* Record absence of global scope for `static' or `auto'.  */
+	TREE_PUBLIC (decl)
+	  = !(storage_class == csc_static || storage_class == csc_auto);
+
+	/* For a function definition, record the argument information
+	   block where store_parm_decls will look for it.  */
+	if (funcdef_flag)
+	  current_function_arg_info = arg_info;
+
+	if (declspecs->default_int_p)
+	  C_FUNCTION_IMPLICIT_INT (decl) = 1;
+
+	/* Record presence of `inline', if it is reasonable.  */
+	if (flag_hosted && MAIN_NAME_P (declarator->u.id))
+	  {
+	    if (declspecs->inline_p)
+	      pedwarn (loc, 0, "cannot inline function %<main%>");
+	  }
+	else if (declspecs->inline_p)
+	  /* Record that the function is declared `inline'.  */
+	  DECL_DECLARED_INLINE_P (decl) = 1;
       }
     else
       {
@@ -6095,9 +6199,12 @@
   else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
     {
       if (!funcdef_flag)
-    pedwarn (input_location, 0, "parameter names (without types) in function declaration");
-
-      arg_info->parms = arg_info->types;
+	{
+	  pedwarn (input_location, 0, "parameter names (without types) in function declaration");
+	  arg_info->parms = NULL_TREE;
+	}
+      else
+	arg_info->parms = arg_info->types;
       arg_info->types = 0;
       return 0;
     }
@@ -6117,57 +6224,75 @@
      warn.  */
 
       for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
-       parm;
-       parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
-    {
-      type = TREE_VALUE (typelt);
-      if (type == error_mark_node)
-        continue;
-
-      if (!COMPLETE_TYPE_P (type))
-        {
-          if (funcdef_flag)
-        {
-          if (DECL_NAME (parm))
-            error_at (input_location,
-                  "parameter %u (%q+D) has incomplete type",
-                  parmno, parm);
-          else
-            error_at (DECL_SOURCE_LOCATION (parm),
-                  "parameter %u has incomplete type",
-                  parmno);
-
-          TREE_VALUE (typelt) = error_mark_node;
-          TREE_TYPE (parm) = error_mark_node;
-        }
-          else if (VOID_TYPE_P (type))
-        {
-          if (DECL_NAME (parm))
-            warning_at (input_location, 0,
-                "parameter %u (%q+D) has void type",
-                parmno, parm);
-          else
-            warning_at (DECL_SOURCE_LOCATION (parm), 0,
-                "parameter %u has void type",
-                parmno);
-        }
-        }
-
-      errmsg = targetm.invalid_parameter_type (type);
-      if (errmsg)
-        {
-          error (errmsg);
-          TREE_VALUE (typelt) = error_mark_node;
-          TREE_TYPE (parm) = error_mark_node;
-        }
-
-      if (DECL_NAME (parm) && TREE_USED (parm))
-        warn_if_shadowing (parm);
-    }
+	   parm;
+	   parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+	{
+	  type = TREE_VALUE (typelt);
+	  if (type == error_mark_node)
+	    continue;
+
+	  if (!COMPLETE_TYPE_P (type))
+	    {
+	      if (funcdef_flag)
+		{
+		  if (DECL_NAME (parm))
+		    error_at (input_location,
+			      "parameter %u (%q+D) has incomplete type",
+			      parmno, parm);
+		  else
+		    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_at (input_location, 0,
+				"parameter %u (%q+D) has void type",
+				parmno, parm);
+		  else
+		    warning_at (DECL_SOURCE_LOCATION (parm), 0,
+				"parameter %u has void type",
+				parmno);
+		}
+	    }
+
+	  errmsg = targetm.invalid_parameter_type (type);
+	  if (errmsg)
+	    {
+	      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))
+	    warn_if_shadowing (parm);
+	}
       return arg_types;
     }
 }
 
+/* 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.
 
@@ -6180,21 +6305,16 @@
 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.
@@ -6237,111 +6357,119 @@
     {
       tree decl = b->decl;
       tree type = TREE_TYPE (decl);
+      c_arg_tag *tag;
       const char *keyword;
 
       switch (TREE_CODE (decl))
-    {
-    case PARM_DECL:
-      if (b->id)
-        {
-          gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-          I_SYMBOL_BINDING (b->id) = b->shadowed;
-        }
-
-      /* Check for forward decls that never got their actual decl.  */
-      if (TREE_ASM_WRITTEN (decl))
-        error ("parameter %q+D has just a forward declaration", decl);
-      /* Check for (..., void, ...) and issue an error.  */
-      else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
-        {
-          if (!gave_void_only_once_err)
-        {
-          error ("%<void%> must be the only parameter");
-          gave_void_only_once_err = true;
-        }
-        }
-      else
-        {
-          /* Valid parameter, add it to the list.  */
-          TREE_CHAIN (decl) = parms;
-          parms = decl;
-
-          /* Since there is a prototype, args are passed in their
-         declared types.  The back end may override this later.  */
-          DECL_ARG_TYPE (decl) = type;
-          types = tree_cons (0, type, types);
-        }
-      break;
-
-    case ENUMERAL_TYPE: keyword = "enum"; goto tag;
-    case UNION_TYPE:    keyword = "union"; goto tag;
-    case RECORD_TYPE:   keyword = "struct"; goto tag;
-    tag:
-      /* Types may not have tag-names, in which case the type
-         appears in the bindings list with b->id NULL.  */
-      if (b->id)
-        {
-          gcc_assert (I_TAG_BINDING (b->id) == b);
-          I_TAG_BINDING (b->id) = b->shadowed;
-        }
-
-      /* Warn about any struct, union or enum tags defined in a
-         parameter list.  The scope of such types is limited to
-         the parameter list, which is rarely if ever desirable
-         (it's impossible to call such a function with type-
-         correct arguments).  An anonymous union parm type is
-         meaningful as a GNU extension, so don't warn for that.  */
-      if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
-        {
-          if (b->id)
-        /* The %s will be one of 'struct', 'union', or 'enum'.  */
-        warning (0, "%<%s %E%> declared inside parameter list",
-             keyword, b->id);
-          else
-        /* The %s will be one of 'struct', 'union', or 'enum'.  */
-        warning (0, "anonymous %s declared inside parameter list",
-             keyword);
-
-          if (!explained_incomplete_types)
-        {
-          warning (0, "its scope is only this definition or declaration,"
-               " which is probably not what you want");
-          explained_incomplete_types = true;
-        }
-        }
-
-      tags = tree_cons (b->id, decl, tags);
-      break;
-
-    case CONST_DECL:
-    case TYPE_DECL:
-    case FUNCTION_DECL:
-      /* CONST_DECLs appear here when we have an embedded enum,
-         and TYPE_DECLs appear here when we have an embedded struct
-         or union.  No warnings for this - we already warned about the
-         type itself.  FUNCTION_DECLs appear when there is an implicit
-         function declaration in the parameter list.  */
-
-      TREE_CHAIN (decl) = others;
-      others = decl;
-      /* fall through */
-
-    case ERROR_MARK:
-      /* error_mark_node appears here when we have an undeclared
-         variable.  Just throw it away.  */
-      if (b->id)
-        {
-          gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-          I_SYMBOL_BINDING (b->id) = b->shadowed;
-        }
-      break;
-
-      /* Other things that might be encountered.  */
-    case LABEL_DECL:
-    case VAR_DECL:
-    default:
-      gcc_unreachable ();
-    }
+	{
+	case PARM_DECL:
+	  if (b->id)
+	    {
+	      gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+	      I_SYMBOL_BINDING (b->id) = b->shadowed;
+	    }
+
+	  /* Check for forward decls that never got their actual decl.  */
+	  if (TREE_ASM_WRITTEN (decl))
+	    error ("parameter %q+D has just a forward declaration", decl);
+	  /* Check for (..., void, ...) and issue an error.  */
+	  else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+	    {
+	      if (!gave_void_only_once_err)
+		{
+		  error ("%<void%> must be the only parameter");
+		  gave_void_only_once_err = true;
+		}
+	    }
+	  else
+	    {
+	      /* Valid parameter, add it to the list.  */
+	      DECL_CHAIN (decl) = parms;
+	      parms = decl;
+
+	      /* Since there is a prototype, args are passed in their
+		 declared types.  The back end may override this later.  */
+	      DECL_ARG_TYPE (decl) = type;
+	      types = tree_cons (0, type, types);
+	    }
+	  break;
+
+	case ENUMERAL_TYPE: keyword = "enum"; goto tag;
+	case UNION_TYPE:    keyword = "union"; goto tag;
+	case RECORD_TYPE:   keyword = "struct"; goto tag;
+	tag:
+	  /* Types may not have tag-names, in which case the type
+	     appears in the bindings list with b->id NULL.  */
+	  if (b->id)
+	    {
+	      gcc_assert (I_TAG_BINDING (b->id) == b);
+	      I_TAG_BINDING (b->id) = b->shadowed;
+	    }
+
+	  /* Warn about any struct, union or enum tags defined in a
+	     parameter list.  The scope of such types is limited to
+	     the parameter list, which is rarely if ever desirable
+	     (it's impossible to call such a function with type-
+	     correct arguments).  An anonymous union parm type is
+	     meaningful as a GNU extension, so don't warn for that.  */
+	  if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
+	    {
+	      if (b->id)
+		/* The %s will be one of 'struct', 'union', or 'enum'.  */
+		warning (0, "%<%s %E%> declared inside parameter list",
+			 keyword, b->id);
+	      else
+		/* The %s will be one of 'struct', 'union', or 'enum'.  */
+		warning (0, "anonymous %s declared inside parameter list",
+			 keyword);
+
+	      if (!explained_incomplete_types)
+		{
+		  warning (0, "its scope is only this definition or declaration,"
+			   " which is probably not what you want");
+		  explained_incomplete_types = true;
+		}
+	    }
+
+	  tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
+	  tag->id = b->id;
+	  tag->type = decl;
+	  break;
+
+	case CONST_DECL:
+	case TYPE_DECL:
+	case FUNCTION_DECL:
+	  /* CONST_DECLs appear here when we have an embedded enum,
+	     and TYPE_DECLs appear here when we have an embedded struct
+	     or union.  No warnings for this - we already warned about the
+	     type itself.  FUNCTION_DECLs appear when there is an implicit
+	     function declaration in the parameter list.  */
+
+	  /* 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 */
+
+	case ERROR_MARK:
+	  /* error_mark_node appears here when we have an undeclared
+	     variable.  Just throw it away.  */
+	  if (b->id)
+	    {
+	      gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+	      I_SYMBOL_BINDING (b->id) = b->shadowed;
+	    }
+	  break;
+
+	  /* Other things that might be encountered.  */
+	case LABEL_DECL:
+	case VAR_DECL:
+	default:
+	  gcc_unreachable ();
+	}
 
       b = free_binding_and_advance (b);
     }
@@ -6558,46 +6686,55 @@
     {
       /* This is an unnamed decl.
 
-     If we have something of the form "union { list } ;" then this
-     is the anonymous union extension.  Similarly for struct.
-
-     If this is something of the form "struct foo;", then
-       If MS extensions are enabled, this is handled as an
-         anonymous struct.
-       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 MS extensions are enabled and foo names a structure, then
-         again this is an anonymous struct.
-       Otherwise this is an error.
-
-     Oh what a horrid tangled web we weave.  I wonder if MS consciously
-     took this from Plan 9 or if it was an accident of implementation
-     that took root before someone noticed the bug...  */
+	 If we have something of the form "union { list } ;" then this
+	 is the anonymous union extension.  Similarly for struct.
+
+	 If this is something of the form "struct foo;", then
+	   If MS or Plan 9 extensions are enabled, this is handled as
+	     an anonymous struct.
+	   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 or Plan 9 extensions are enabled and foo names a
+	     structure, then again this is an anonymous struct.
+	   Otherwise this is an error.
+
+	 Oh what a horrid tangled web we weave.  I wonder if MS consciously
+	 took this from Plan 9 or if it was an accident of implementation
+	 that took root before someone noticed the bug...  */
 
       tree type = declspecs->type;
       bool type_ok = (TREE_CODE (type) == RECORD_TYPE
               || TREE_CODE (type) == UNION_TYPE);
       bool ok = false;
 
-      if (type_ok
-      && (flag_ms_extensions || !declspecs->typedef_p))
-    {
-      if (flag_ms_extensions)
-        ok = true;
-      else if (flag_iso)
-        ok = false;
-      else if (TYPE_NAME (type) == NULL)
-        ok = true;
-      else
-        ok = false;
-    }
+      if (type_ok)
+	{
+	  if (flag_ms_extensions || flag_plan9_extensions)
+	    ok = true;
+	  else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
+	    ok = true;
+	  else
+	    ok = false;
+	}
+
+
       if (!ok)
-    {
-      pedwarn (loc, 0, "declaration does not declare anything");
-      return NULL_TREE;
-    }
-      pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
+	{
+	  pedwarn (loc, 0, "declaration does not declare anything");
+	  return NULL_TREE;
+	}
+      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,
@@ -6629,6 +6766,90 @@
   return value;
 }
 
+/* Subroutine of detect_field_duplicates: return whether X and Y,
+   which are both fields in the same struct, have duplicate field
+   names.  */
+
+static bool
+is_duplicate_field (tree x, tree y)
+{
+  if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
+    return true;
+
+  /* When using -fplan9-extensions, an anonymous field whose name is a
+     typedef can duplicate a field name.  */
+  if (flag_plan9_extensions
+      && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
+    {
+      tree xt, xn, yt, yn;
+
+      xt = TREE_TYPE (x);
+      if (DECL_NAME (x) != NULL_TREE)
+	xn = DECL_NAME (x);
+      else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
+	       && TYPE_NAME (xt) != NULL_TREE
+	       && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
+	xn = DECL_NAME (TYPE_NAME (xt));
+      else
+	xn = NULL_TREE;
+
+      yt = TREE_TYPE (y);
+      if (DECL_NAME (y) != NULL_TREE)
+	yn = DECL_NAME (y);
+      else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
+	       && TYPE_NAME (yt) != NULL_TREE
+	       && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
+	yn = DECL_NAME (TYPE_NAME (yt));
+      else
+	yn = NULL_TREE;
+
+      if (xn != NULL_TREE && xn == yn)
+	return true;
+    }
+
+  return false;
+}
+
+/* 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);
+
+	/* When using -fplan9-extensions, an anonymous field whose
+	   name is a typedef can duplicate a field name.  */
+	if (flag_plan9_extensions
+	    && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+	    && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
+	  {
+	    tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
+	    slot = htab_find_slot (htab, xn, INSERT);
+	    if (*slot)
+	      error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
+	    *slot = xn;
+	  }
+      }
+}
+
 /* Generate an error for any duplicate field names in FIELDLIST.  Munge
    the list such that this does not present a problem later.  */
 
@@ -6638,50 +6859,60 @@
   tree x, y;
   int timeout = 10;
 
+  /* If the struct is the list of instance variables of an Objective-C
+     class, then we need to add all the instance variables of
+     superclasses before checking for duplicates (since you can't have
+     an instance variable in a subclass with the same name as an
+     instance variable in a superclass).  objc_get_interface_ivars()
+     leaves fieldlist unchanged if we are not in this case, so in that
+     case nothing changes compared to C.
+  */
+  if (c_dialect_objc ())
+    fieldlist = objc_get_interface_ivars (fieldlist);
+
   /* First, see if there are more than "a few" fields.
      This is trivially true if there are zero or one fields.  */
-  if (!fieldlist)
+  if (!fieldlist || !DECL_CHAIN (fieldlist))
     return;
-  x = TREE_CHAIN (fieldlist);
-  if (!x)
-    return;
+  x = fieldlist;
   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))
-    if (DECL_NAME (x))
-      {
-        for (y = fieldlist; y != x; y = TREE_CHAIN (y))
-          if (DECL_NAME (y) == DECL_NAME (x))
-        {
-          error ("duplicate member %q+D", x);
-          DECL_NAME (x) = NULL_TREE;
-        }
-      }
+      for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
+	/* When using -fplan9-extensions, we can have duplicates
+	   between typedef names and fields.  */
+	if (DECL_NAME (x)
+	    || (flag_plan9_extensions
+		&& DECL_NAME (x) == NULL_TREE
+		&& (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+		    || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+		&& TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+		&& TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
+	  {
+	    for (y = fieldlist; y != x; y = TREE_CHAIN (y))
+	      if (is_duplicate_field (y, x))
+		{
+		  error ("duplicate member %q+D", x);
+		  DECL_NAME (x) = NULL_TREE;
+		}
+	  }
     }
   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);
     }
 }
@@ -6700,7 +6931,7 @@
      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 (ix = 0; VEC_iterate (tree, struct_parse_info->struct_types, ix, x); ++ix)
+  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
@@ -6716,32 +6947,28 @@
      a pointer_set because identifiers are interned.  */
       struct pointer_set_t *tset = pointer_set_create ();
 
-      for (ix = 0;
-       VEC_iterate (tree, struct_parse_info->typedefs_seen, ix, x);
-       ++ix)
-    pointer_set_insert (tset, DECL_NAME (x));
-
-      for (x = fieldlist; x != NULL_TREE; x = TREE_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.  */
-        }
-    }
-
+      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 (DECL_NAME (x) != NULL_TREE
+	      && 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 (ix = 0;
-       VEC_iterate (c_binding_ptr, struct_parse_info->fields, ix, b);
-       ++ix)
+  FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
     b->in_struct = 0;
 }
 
@@ -6770,9 +6997,15 @@
 
   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)
     {
@@ -6801,7 +7034,7 @@
      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;
@@ -6812,15 +7045,13 @@
       if (TREE_READONLY (x))
     C_TYPE_FIELDS_READONLY (t) = 1;
       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);
-      if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
-          && C_TYPE_FIELDS_READONLY (t1))
-        C_TYPE_FIELDS_READONLY (t) = 1;
-    }
+	{
+	  /* A field that is pseudo-const makes the structure likewise.  */
+	  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;
+	}
 
       /* Any field that is volatile means variables of this type must be
      treated in some ways as volatile.  */
@@ -6846,37 +7077,39 @@
 
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
-      && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
-      && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
-      && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
-    {
-      if (TREE_CODE (t) == UNION_TYPE)
-        {
-          error_at (DECL_SOURCE_LOCATION (x),
-            "flexible array member in union");
-          TREE_TYPE (x) = error_mark_node;
-        }
-      else if (TREE_CHAIN (x) != NULL_TREE)
-        {
-          error_at (DECL_SOURCE_LOCATION (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),
-            "flexible array member in otherwise empty struct");
-          TREE_TYPE (x) = error_mark_node;
-        }
-    }
+	  && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+	  && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+	  && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+	{
+	  if (TREE_CODE (t) == UNION_TYPE)
+	    {
+	      error_at (DECL_SOURCE_LOCATION (x),
+			"flexible array member in union");
+	      TREE_TYPE (x) = error_mark_node;
+	    }
+	  else if (DECL_CHAIN (x) != NULL_TREE)
+	    {
+	      error_at (DECL_SOURCE_LOCATION (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),
+			"flexible array member in otherwise empty struct");
+	      TREE_TYPE (x) = error_mark_node;
+	    }
+	}
 
       if (pedantic && TREE_CODE (t) == RECORD_TYPE
       && flexible_array_type_p (TREE_TYPE (x)))
     pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
          "invalid use of structure with flexible array member");
 
-      if (DECL_NAME (x))
-    saw_named_field = 1;
+      if (DECL_NAME (x)
+	  || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+	  || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+	saw_named_field = 1;
     }
 
   detect_field_duplicates (fieldlist);
@@ -6907,7 +7140,7 @@
       DECL_INITIAL (*fieldlistp) = 0;
     }
       else
-    fieldlistp = &TREE_CHAIN (*fieldlistp);
+	fieldlistp = &DECL_CHAIN (*fieldlistp);
   }
 
   /* Now we have the truly final field list.
@@ -6921,7 +7154,7 @@
   {
     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;
@@ -6930,39 +7163,39 @@
 
     if (len > 15)
       {
-    tree *field_array;
-    struct lang_type *space;
-    struct sorted_fields_type *space2;
-
-    len += list_length (x);
-
-    /* Use the same allocation policy here that make_node uses, to
-      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));
-
-    len = 0;
-    space->s = space2;
-    field_array = &space2->elts[0];
-    for (x = fieldlist; x; x = TREE_CHAIN (x))
-      {
-        field_array[len++] = x;
-
-        /* If there is anonymous struct or union, break out of the loop.  */
-        if (DECL_NAME (x) == NULL)
-          break;
-      }
-    /* Found no anonymous struct/union.  Add the TYPE_LANG_SPECIFIC.  */
-    if (x == NULL)
-      {
-        TYPE_LANG_SPECIFIC (t) = space;
-        TYPE_LANG_SPECIFIC (t)->s->len = len;
-        field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
-        qsort (field_array, len, sizeof (tree), field_decl_cmp);
-      }
+	tree *field_array;
+	struct lang_type *space;
+	struct sorted_fields_type *space2;
+
+	len += list_length (x);
+
+	/* Use the same allocation policy here that make_node uses, to
+	  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_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 = DECL_CHAIN (x))
+	  {
+	    field_array[len++] = x;
+
+	    /* If there is anonymous struct or union, break out of the loop.  */
+	    if (DECL_NAME (x) == NULL)
+	      break;
+	  }
+	/* Found no anonymous struct/union.  Add the TYPE_LANG_SPECIFIC.  */
+	if (x == NULL)
+	  {
+	    TYPE_LANG_SPECIFIC (t) = space;
+	    TYPE_LANG_SPECIFIC (t)->s->len = len;
+	    field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
+	    qsort (field_array, len, sizeof (tree), field_decl_cmp);
+	  }
       }
   }
 
@@ -6978,10 +7211,10 @@
   /* 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");
     }
 
@@ -7223,7 +7456,7 @@
 
   /* 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;
@@ -7261,13 +7494,14 @@
 
 /* Build and install a CONST_DECL for one value of the
    current enumeration type (one that was begun with start_enum).
-   LOC is the location of the enumerator.
+   DECL_LOC is the location of the enumerator.
+   LOC is the location of the '=' operator if any, DECL_LOC otherwise.
    Return a tree-list containing the CONST_DECL and its value.
    Assignment of sequential values by default is handled here.  */
 
 tree
-build_enumerator (location_t loc,
-          struct c_enum_contents *the_enum, tree name, tree value)
+build_enumerator (location_t decl_loc, location_t loc,
+		  struct c_enum_contents *the_enum, tree name, tree value)
 {
   tree decl, type;
 
@@ -7340,9 +7574,8 @@
 
   /* Set basis for default for next value.  */
   the_enum->enum_next_value
-    = build_binary_op
-         (EXPR_HAS_LOCATION (value) ? EXPR_LOCATION (value) : input_location,
-     PLUS_EXPR, value, integer_one_node, 0);
+    = build_binary_op (EXPR_LOC_OR_HERE (value),
+		       PLUS_EXPR, value, integer_one_node, 0);
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 
   /* Now create a declaration for the enum value name.  */
@@ -7354,7 +7587,7 @@
                   >= TYPE_PRECISION (integer_type_node)
                   && TYPE_UNSIGNED (type)));
 
-  decl = build_decl (loc, CONST_DECL, name, type);
+  decl = build_decl (decl_loc, CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
   pushdecl (decl);
 
@@ -7515,6 +7748,10 @@
      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);
@@ -7523,7 +7760,7 @@
   current_function_prototype_locus = UNKNOWN_LOCATION;
   current_function_prototype_built_in = false;
   current_function_prototype_arg_types = NULL_TREE;
-  if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
+  if (!prototype_p (TREE_TYPE (decl1)))
     {
       if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
       && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
@@ -7572,7 +7809,7 @@
   /* Optionally warn of old-fashioned def with no previous prototype.  */
   if (warn_strict_prototypes
       && old_decl != error_mark_node
-      && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
+      && !prototype_p (TREE_TYPE (decl1))
       && C_DECL_ISNT_PROTOTYPE (old_decl))
     warning_at (loc, OPT_Wstrict_prototypes,
         "function declaration isn%'t a prototype");
@@ -7587,10 +7824,10 @@
   /* Optionally warn of any def with no previous prototype
      if the function has already been used.  */
   else if (warn_missing_prototypes
-       && old_decl != 0
-       && old_decl != error_mark_node
-       && TREE_USED (old_decl)
-       && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
+	   && old_decl != 0
+	   && old_decl != error_mark_node
+	   && TREE_USED (old_decl)
+	   && !prototype_p (TREE_TYPE (old_decl)))
     warning_at (loc, OPT_Wmissing_prototypes,
         "%qD was used with no prototype before its definition", decl1);
   /* Optionally warn of any global def with no previous declaration.  */
@@ -7615,10 +7852,6 @@
      (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));
@@ -7669,6 +7902,8 @@
 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)
     {
@@ -7691,7 +7926,7 @@
 
   /* 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))
@@ -7710,19 +7945,21 @@
   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);
+	bind (DECL_NAME (decl), decl, current_scope,
+	      /*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,
-        /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+  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);
 }
 
 /* Subroutine of store_parm_decls which handles old-style function
@@ -7754,33 +7991,36 @@
 
       b = I_SYMBOL_BINDING (TREE_VALUE (parm));
       if (b && B_IN_CURRENT_SCOPE (b))
-    {
-      decl = b->decl;
-      /* If we got something other than a PARM_DECL it is an error.  */
-      if (TREE_CODE (decl) != PARM_DECL)
-        error_at (DECL_SOURCE_LOCATION (decl),
-              "%qD declared as a non-parameter", decl);
-      /* If the declaration is already marked, we have a duplicate
-         name.  Complain and ignore the duplicate.  */
-      else if (pointer_set_contains (seen_args, decl))
-        {
-          error_at (DECL_SOURCE_LOCATION (decl),
-            "multiple parameters named %qD", decl);
-          TREE_PURPOSE (parm) = 0;
-          continue;
-        }
-      /* If the declaration says "void", complain and turn it into
-         an int.  */
-      else if (VOID_TYPE_P (TREE_TYPE (decl)))
-        {
-          error_at (DECL_SOURCE_LOCATION (decl),
-            "parameter %qD declared with void type", decl);
-          TREE_TYPE (decl) = integer_type_node;
-          DECL_ARG_TYPE (decl) = integer_type_node;
-          layout_decl (decl, 0);
-        }
-      warn_if_shadowing (decl);
-    }
+	{
+	  decl = b->decl;
+	  /* Skip erroneous parameters.  */
+	  if (decl == error_mark_node)
+	    continue;
+	  /* If we got something other than a PARM_DECL it is an error.  */
+	  if (TREE_CODE (decl) != PARM_DECL)
+	    error_at (DECL_SOURCE_LOCATION (decl),
+		      "%qD declared as a non-parameter", decl);
+	  /* If the declaration is already marked, we have a duplicate
+	     name.  Complain and ignore the duplicate.  */
+	  else if (pointer_set_contains (seen_args, decl))
+	    {
+	      error_at (DECL_SOURCE_LOCATION (decl),
+			"multiple parameters named %qD", decl);
+	      TREE_PURPOSE (parm) = 0;
+	      continue;
+	    }
+	  /* If the declaration says "void", complain and turn it into
+	     an int.  */
+	  else if (VOID_TYPE_P (TREE_TYPE (decl)))
+	    {
+	      error_at (DECL_SOURCE_LOCATION (decl),
+			"parameter %qD declared with void type", decl);
+	      TREE_TYPE (decl) = integer_type_node;
+	      DECL_ARG_TYPE (decl) = integer_type_node;
+	      layout_decl (decl, 0);
+	    }
+	  warn_if_shadowing (decl);
+	}
       /* If no declaration found, default to int.  */
       else
     {
@@ -7858,12 +8098,12 @@
       DECL_ARGUMENTS (fndecl) = last;
 
       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
-    if (TREE_PURPOSE (parm))
-      {
-        TREE_CHAIN (last) = TREE_PURPOSE (parm);
-        last = TREE_PURPOSE (parm);
-      }
-      TREE_CHAIN (last) = 0;
+	if (TREE_PURPOSE (parm))
+	  {
+	    DECL_CHAIN (last) = TREE_PURPOSE (parm);
+	    last = TREE_PURPOSE (parm);
+	  }
+      DECL_CHAIN (last) = 0;
     }
 
   pointer_set_destroy (seen_args);
@@ -7879,88 +8119,88 @@
          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))
-    {
-      if (parm == 0 || type == 0
-          || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
-        {
-          if (current_function_prototype_built_in)
-        warning_at (DECL_SOURCE_LOCATION (fndecl),
-                0, "number of arguments doesn%'t match "
-                "built-in prototype");
-          else
-        {
-          /* FIXME diagnostics: This should be the location of
-             FNDECL, but there is bug when a prototype is
-             declared inside function context, but defined
-             outside of it (e.g., gcc.dg/pr15698-2.c).  In
-             which case FNDECL gets the location of the
-             prototype, not the definition.  */
-          error_at (input_location,
-                "number of arguments doesn%'t match prototype");
-
-          error_at (current_function_prototype_locus,
-                "prototype declaration");
-        }
-          break;
-        }
-      /* Type for passing arg must be consistent with that
-         declared for the arg.  ISO C says we take the unqualified
-         type for parameters declared with qualified type.  */
-      if (TREE_TYPE (parm) != error_mark_node
-          && TREE_TYPE (type) != error_mark_node
-          && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
-                 TYPE_MAIN_VARIANT (TREE_VALUE (type))))
-        {
-          if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
-          == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
-        {
-          /* Adjust argument to match prototype.  E.g. a previous
-             `int foo(float);' prototype causes
-             `int foo(x) float x; {...}' to be treated like
-             `int foo(float x) {...}'.  This is particularly
-             useful for argument types like uid_t.  */
-          DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-
-          if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
-              && INTEGRAL_TYPE_P (TREE_TYPE (parm))
-              && TYPE_PRECISION (TREE_TYPE (parm))
-              < TYPE_PRECISION (integer_type_node))
-            DECL_ARG_TYPE (parm) = integer_type_node;
-
-          /* ??? Is it possible to get here with a
-             built-in prototype or will it always have
-             been diagnosed as conflicting with an
-             old-style definition and discarded?  */
-          if (current_function_prototype_built_in)
-            warning_at (DECL_SOURCE_LOCATION (parm),
-                OPT_pedantic, "promoted argument %qD "
-                "doesn%'t match built-in prototype", parm);
-          else
-            {
-              pedwarn (DECL_SOURCE_LOCATION (parm),
-                   OPT_pedantic, "promoted argument %qD "
-                   "doesn%'t match prototype", parm);
-              pedwarn (current_function_prototype_locus, OPT_pedantic,
-                   "prototype declaration");
-            }
-        }
-          else
-        {
-          if (current_function_prototype_built_in)
-            warning_at (DECL_SOURCE_LOCATION (parm),
-                0, "argument %qD doesn%'t match "
-                "built-in prototype", parm);
-          else
-            {
-              error_at (DECL_SOURCE_LOCATION (parm),
-                "argument %qD doesn%'t match prototype", parm);
-              error_at (current_function_prototype_locus,
-                "prototype declaration");
-            }
-        }
-        }
-    }
+	   parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
+	{
+	  if (parm == 0 || type == 0
+	      || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+	    {
+	      if (current_function_prototype_built_in)
+		warning_at (DECL_SOURCE_LOCATION (fndecl),
+			    0, "number of arguments doesn%'t match "
+			    "built-in prototype");
+	      else
+		{
+		  /* FIXME diagnostics: This should be the location of
+		     FNDECL, but there is bug when a prototype is
+		     declared inside function context, but defined
+		     outside of it (e.g., gcc.dg/pr15698-2.c).  In
+		     which case FNDECL gets the location of the
+		     prototype, not the definition.  */
+		  error_at (input_location,
+			    "number of arguments doesn%'t match prototype");
+
+		  error_at (current_function_prototype_locus,
+			    "prototype declaration");
+		}
+	      break;
+	    }
+	  /* Type for passing arg must be consistent with that
+	     declared for the arg.  ISO C says we take the unqualified
+	     type for parameters declared with qualified type.  */
+	  if (TREE_TYPE (parm) != error_mark_node
+	      && TREE_TYPE (type) != error_mark_node
+	      && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+			     TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+	    {
+	      if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+		  == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
+		{
+		  /* Adjust argument to match prototype.  E.g. a previous
+		     `int foo(float);' prototype causes
+		     `int foo(x) float x; {...}' to be treated like
+		     `int foo(float x) {...}'.  This is particularly
+		     useful for argument types like uid_t.  */
+		  DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
+
+		  if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
+		      && INTEGRAL_TYPE_P (TREE_TYPE (parm))
+		      && TYPE_PRECISION (TREE_TYPE (parm))
+		      < TYPE_PRECISION (integer_type_node))
+		    DECL_ARG_TYPE (parm) = integer_type_node;
+
+		  /* ??? Is it possible to get here with a
+		     built-in prototype or will it always have
+		     been diagnosed as conflicting with an
+		     old-style definition and discarded?  */
+		  if (current_function_prototype_built_in)
+		    warning_at (DECL_SOURCE_LOCATION (parm),
+				OPT_pedantic, "promoted argument %qD "
+				"doesn%'t match built-in prototype", parm);
+		  else
+		    {
+		      pedwarn (DECL_SOURCE_LOCATION (parm),
+			       OPT_pedantic, "promoted argument %qD "
+			       "doesn%'t match prototype", parm);
+		      pedwarn (current_function_prototype_locus, OPT_pedantic,
+			       "prototype declaration");
+		    }
+		}
+	      else
+		{
+		  if (current_function_prototype_built_in)
+		    warning_at (DECL_SOURCE_LOCATION (parm),
+				0, "argument %qD doesn%'t match "
+				"built-in prototype", parm);
+		  else
+		    {
+		      error_at (DECL_SOURCE_LOCATION (parm),
+				"argument %qD doesn%'t match prototype", parm);
+		      error_at (current_function_prototype_locus,
+				"prototype declaration");
+		    }
+		}
+	    }
+	}
       TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
     }
 
@@ -7970,15 +8210,15 @@
     {
       tree actual = 0, last = 0, type;
 
-      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
-    {
-      type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
-      if (last)
-        TREE_CHAIN (last) = type;
-      else
-        actual = type;
-      last = type;
-    }
+      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
+	{
+	  type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
+	  if (last)
+	    TREE_CHAIN (last) = type;
+	  else
+	    actual = type;
+	  last = type;
+	}
       type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
       if (last)
     TREE_CHAIN (last) = type;
@@ -8060,9 +8300,12 @@
      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
@@ -8074,7 +8317,7 @@
 
 
 /* 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.  */
@@ -8083,18 +8326,21 @@
 finish_function (void)
 {
   tree fndecl = current_function_decl;
+  
+  if (c_dialect_objc ())
+    objc_finish_function ();
 
   if (TREE_CODE (fndecl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
     {
       tree args = DECL_ARGUMENTS (fndecl);
-      for (; args; args = TREE_CHAIN (args))
-    {
-      tree type = TREE_TYPE (args);
-      if (INTEGRAL_TYPE_P (type)
-          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-        DECL_ARG_TYPE (args) = integer_type_node;
-    }
+      for (; args; args = DECL_CHAIN (args))
+	{
+	  tree type = TREE_TYPE (args);
+	  if (INTEGRAL_TYPE_P (type)
+	      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+	    DECL_ARG_TYPE (args) = integer_type_node;
+	}
     }
 
   if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
@@ -8129,6 +8375,8 @@
       && !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.  */
@@ -8142,6 +8390,25 @@
       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;
@@ -8196,16 +8463,23 @@
 
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  If exactly one such decl is found, return it.  LOC is
-   the location of the opening parenthesis of the for loop.  */
+   the location of the opening parenthesis of the for loop.  The last
+   parameter allows you to control the "for loop initial declarations
+   are only allowed in C99 mode".  Normally, you should pass
+   flag_isoc99 as that parameter.  But in some cases (Objective-C
+   foreach loop, for example) we want to run the checks in this
+   function even if not in C99 mode, so we allow the caller to turn
+   off the error about not being in C99 mode.
+*/
 
 tree
-check_for_loop_decls (location_t loc)
+check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 {
   struct c_binding *b;
   tree one_decl = NULL_TREE;
   int n_decls = 0;
 
-  if (!flag_isoc99)
+  if (!turn_off_iso_c99_error)
     {
       static bool hint = true;
       /* If we get here, declarations have been used in a for loop without
@@ -8292,7 +8566,7 @@
 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;
@@ -8491,10 +8765,9 @@
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
   ret->declspecs_seen_p = false;
-  ret->type_seen_p = false;
+  ret->typespec_kind = ctsk_none;
   ret->non_sc_seen_p = false;
   ret->typedef_p = false;
-  ret->tag_defined_p = false;
   ret->explicit_signed_p = false;
   ret->deprecated_p = false;
   ret->default_int_p = false;
@@ -8578,7 +8851,7 @@
   tree type = spec.spec;
   specs->non_sc_seen_p = true;
   specs->declspecs_seen_p = true;
-  specs->type_seen_p = true;
+  specs->typespec_kind = spec.kind;
   if (TREE_DEPRECATED (type))
     specs->deprecated_p = true;
 
@@ -8594,105 +8867,114 @@
       return specs;
     }
       if ((int) i <= (int) RID_LAST_MODIFIER)
-    {
-      /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat".  */
-      bool dupe = false;
-      switch (i)
-        {
-        case RID_LONG:
-          if (specs->long_long_p)
-        {
-          error_at (loc, "%<long long long%> is too long for GCC");
-          break;
-        }
-          if (specs->long_p)
-        {
-          if (specs->typespec_word == cts_double)
-            {
-              error_at (loc,
-                ("both %<long long%> and %<double%> in "
-                 "declaration specifiers"));
-              break;
-            }
-          pedwarn_c90 (loc, OPT_Wlong_long,
-                   "ISO C90 does not support %<long long%>");
-          specs->long_long_p = 1;
-          break;
-        }
-          if (specs->short_p)
-        error_at (loc,
-              ("both %<long%> and %<short%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_void)
-        error_at (loc,
-              ("both %<long%> and %<void%> in "
-               "declaration specifiers"));
+	{
+	  /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat".  */
+	  bool dupe = false;
+	  switch (i)
+	    {
+	    case RID_LONG:
+	      if (specs->long_long_p)
+		{
+		  error_at (loc, "%<long long long%> is too long for GCC");
+		  break;
+		}
+	      if (specs->long_p)
+		{
+		  if (specs->typespec_word == cts_double)
+		    {
+		      error_at (loc,
+				("both %<long long%> and %<double%> in "
+				 "declaration specifiers"));
+		      break;
+		    }
+		  pedwarn_c90 (loc, OPT_Wlong_long,
+			       "ISO C90 does not support %<long long%>");
+		  specs->long_long_p = 1;
+		  break;
+		}
+	      if (specs->short_p)
+		error_at (loc,
+			  ("both %<long%> and %<short%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_void)
+		error_at (loc,
+			  ("both %<long%> and %<void%> in "
+			   "declaration specifiers"));
 #ifndef noCbC
-          else if (specs->typespec_word == cts_CbC_code)
-        error_at (loc,
-              ("both %<long%> and %<void%> in "
-               "declaration specifiers"));
+	      else if (specs->typespec_word == cts_CbC_code)
+		error_at (loc,
+			  ("both %<long%> and %<void%> in "
+			   "declaration specifiers"));
 #endif
-          else if (specs->typespec_word == cts_bool)
-        error_at (loc,
-              ("both %<long%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_char)
-        error_at (loc,
-              ("both %<long%> and %<char%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_float)
-        error_at (loc,
-              ("both %<long%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat32)
-        error_at (loc,
-              ("both %<long%> and %<_Decimal32%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat64)
-        error_at (loc,
-              ("both %<long%> and %<_Decimal64%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat128)
-        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_at (loc,
-              ("both %<long%> and %<short%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_void)
-        error_at (loc,
-              ("both %<short%> 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_at (loc,
+			  ("both %<long%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_char)
+		error_at (loc,
+			  ("both %<long%> and %<char%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_float)
+		error_at (loc,
+			  ("both %<long%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat32)
+		error_at (loc,
+			  ("both %<long%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat64)
+		error_at (loc,
+			  ("both %<long%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat128)
+		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_at (loc,
+			  ("both %<long%> and %<short%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_void)
+		error_at (loc,
+			  ("both %<short%> and %<void%> in "
+			   "declaration specifiers"));
 #ifndef noCbC
-          else if (specs->typespec_word == cts_CbC_code)
-        error_at (loc,
-              ("both %<short%> and %<void%> in "
-               "declaration specifiers"));
+	      else if (specs->typespec_word == cts_CbC_code)
+		error_at (loc,
+			  ("both %<short%> and %<void%> in "
+			   "declaration specifiers"));
 #endif
-          else if (specs->typespec_word == cts_bool)
-        error_at (loc,
-              ("both %<short%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_char)
-        error_at (loc,
-              ("both %<short%> and %<char%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_float)
-        error_at (loc,
-              ("both %<short%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_double)
-        error_at (loc,
-              ("both %<short%> and %<double%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat32)
+	      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_at (loc,
+			  ("both %<short%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_char)
+		error_at (loc,
+			  ("both %<short%> and %<char%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_float)
+		error_at (loc,
+			  ("both %<short%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_double)
+		error_at (loc,
+			  ("both %<short%> and %<double%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat32)
+>>>>>>> other
                 error_at (loc,
               ("both %<short%> and %<_Decimal32%> in "
                "declaration specifiers"));
@@ -8813,60 +9095,66 @@
               ("both %<complex%> and %<_Bool%> in "
                "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-        error_at (loc,
-              ("both %<complex%> and %<_Decimal32%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat64)
-        error_at (loc,
-              ("both %<complex%> and %<_Decimal64%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_dfloat128)
-        error_at (loc,
-              ("both %<complex%> and %<_Decimal128%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_fract)
-        error_at (loc,
-              ("both %<complex%> and %<_Fract%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_accum)
-        error_at (loc,
-              ("both %<complex%> and %<_Accum%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        error_at (loc,
-              ("both %<complex%> and %<_Sat%> in "
-               "declaration specifiers"));
-          else
-        specs->complex_p = true;
-          break;
-        case RID_SAT:
-          dupe = specs->saturating_p;
-          pedwarn (loc, OPT_pedantic,
-               "ISO C does not support saturating types");
-          if (specs->typespec_word == cts_void)
-        error_at (loc,
-              ("both %<_Sat%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_bool)
-        error_at (loc,
-              ("both %<_Sat%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_char)
-        error_at (loc,
-              ("both %<_Sat%> and %<char%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_int)
-        error_at (loc,
-              ("both %<_Sat%> and %<int%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_float)
-        error_at (loc,
-              ("both %<_Sat%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->typespec_word == cts_double)
-        error_at (loc,
-              ("both %<_Sat%> and %<double%> in "
-               "declaration specifiers"));
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat64)
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_dfloat128)
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_fract)
+		error_at (loc,
+			  ("both %<complex%> and %<_Fract%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_accum)
+		error_at (loc,
+			  ("both %<complex%> and %<_Accum%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		error_at (loc,
+			  ("both %<complex%> and %<_Sat%> in "
+			   "declaration specifiers"));
+	      else
+		specs->complex_p = true;
+	      break;
+	    case RID_SAT:
+	      dupe = specs->saturating_p;
+	      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_at (loc,
+			  ("both %<_Sat%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_char)
+		error_at (loc,
+			  ("both %<_Sat%> and %<char%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_int)
+		error_at (loc,
+			  ("both %<_Sat%> and %<int%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_float)
+		error_at (loc,
+			  ("both %<_Sat%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_double)
+		error_at (loc,
+			  ("both %<_Sat%> and %<double%> in "
+			   "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
         error_at (loc,
               ("both %<_Sat%> and %<_Decimal32%> in "
@@ -8896,202 +9184,227 @@
       return specs;
     }
       else
-    {
-      /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-         "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
-      if (specs->typespec_word != cts_none)
-        {
-          error_at (loc,
-            "two or more data types in declaration specifiers");
-          return specs;
-        }
-      switch (i)
-        {
-        case RID_VOID:
-          if (specs->long_p)
-        error_at (loc,
-              ("both %<long%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->short_p)
-        error_at (loc,
-              ("both %<short%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->signed_p)
-        error_at (loc,
-              ("both %<signed%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->unsigned_p)
-        error_at (loc,
-              ("both %<unsigned%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->complex_p)
-        error_at (loc,
-              ("both %<complex%> and %<void%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        error_at (loc,
-              ("both %<_Sat%> and %<void%> in "
-               "declaration specifiers"));
-          else
-        specs->typespec_word = cts_void;
-          return specs;
+	{
+	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
+	     "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
+	  if (specs->typespec_word != cts_none)
+	    {
+	      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_at (loc,
+			  ("both %<long%> and %<void%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<short%> and %<void%> in "
+			   "declaration specifiers"));
+	      else if (specs->signed_p)
+		error_at (loc,
+			  ("both %<signed%> and %<void%> in "
+			   "declaration specifiers"));
+	      else if (specs->unsigned_p)
+		error_at (loc,
+			  ("both %<unsigned%> and %<void%> in "
+			   "declaration specifiers"));
+	      else if (specs->complex_p)
+		error_at (loc,
+			  ("both %<complex%> and %<void%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		error_at (loc,
+			  ("both %<_Sat%> and %<void%> in "
+			   "declaration specifiers"));
+	      else
+		specs->typespec_word = cts_void;
+	      return specs;
 #ifndef noCbC
-        case RID_CbC_CODE:
-          if (specs->long_p)
-        error ("both %<long%> and %<void%> in "
-               "declaration specifiers");
-          else if (specs->short_p)
-        error ("both %<short%> and %<void%> in "
-               "declaration specifiers");
-          else if (specs->signed_p)
-        error ("both %<signed%> and %<void%> in "
-               "declaration specifiers");
-          else if (specs->unsigned_p)
-        error ("both %<unsigned%> and %<void%> in "
-               "declaration specifiers");
-          else if (specs->complex_p)
-        error ("both %<complex%> and %<void%> in "
-               "declaration specifiers");
-          else
-        specs->typespec_word = cts_CbC_code;
-          return specs;
+	    case RID_CbC_CODE:
+	    if (specs->long_p)
+	      error ("both %<long%> and %<void%> in "
+		     "declaration specifiers");
+	    else if (specs->short_p)
+	      error ("both %<short%> and %<void%> in "
+		     "declaration specifiers");
+	    else if (specs->signed_p)
+	      error ("both %<signed%> and %<void%> in "
+		     "declaration specifiers");
+	    else if (specs->unsigned_p)
+	      error ("both %<unsigned%> and %<void%> in "
+		     "declaration specifiers");
+	    else if (specs->complex_p)
+	      error ("both %<complex%> and %<void%> in "
+		     "declaration specifiers");
+	    else
+	      specs->typespec_word = cts_CbC_code;
+	    return specs;
 #endif
-        case RID_BOOL:
-          if (specs->long_p)
-        error_at (loc,
-              ("both %<long%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->short_p)
-        error_at (loc,
-              ("both %<short%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->signed_p)
-        error_at (loc,
-              ("both %<signed%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->unsigned_p)
-        error_at (loc,
-              ("both %<unsigned%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->complex_p)
-        error_at (loc,
-              ("both %<complex%> and %<_Bool%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        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_at (loc,
-              ("both %<long%> and %<char%> in "
-               "declaration specifiers"));
-          else if (specs->short_p)
-        error_at (loc,
-              ("both %<short%> and %<char%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        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_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_at (loc,
-              ("both %<long%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->short_p)
-        error_at (loc,
-              ("both %<short%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->signed_p)
-        error_at (loc,
-              ("both %<signed%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->unsigned_p)
-        error_at (loc,
-              ("both %<unsigned%> and %<float%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        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_at (loc,
-              ("both %<long long%> and %<double%> in "
-               "declaration specifiers"));
-          else if (specs->short_p)
-        error_at (loc,
-              ("both %<short%> and %<double%> in "
-               "declaration specifiers"));
-          else if (specs->signed_p)
-        error_at (loc,
-              ("both %<signed%> and %<double%> in "
-               "declaration specifiers"));
-          else if (specs->unsigned_p)
-        error_at (loc,
-              ("both %<unsigned%> and %<double%> in "
-               "declaration specifiers"));
-          else if (specs->saturating_p)
-        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";
-        else if (i == RID_DFLOAT64)
-          str = "_Decimal64";
-        else
-          str = "_Decimal128";
-        if (specs->long_long_p)
-          error_at (loc,
-                ("both %<long long%> and %<%s%> in "
-                 "declaration specifiers"),
-                str);
-        if (specs->long_p)
-          error_at (loc,
-                ("both %<long%> and %<%s%> in "
-                 "declaration specifiers"),
-                str);
-        else if (specs->short_p)
-          error_at (loc,
-                ("both %<short%> and %<%s%> in "
-                 "declaration specifiers"),
-                str);
-        else if (specs->signed_p)
-          error_at (loc,
-                ("both %<signed%> and %<%s%> in "
-                 "declaration specifiers"),
-                str);
-        else if (specs->unsigned_p)
-          error_at (loc,
-                ("both %<unsigned%> and %<%s%> in "
-                 "declaration specifiers"),
-                str);
+	    case RID_BOOL:
+	      if (specs->long_p)
+		error_at (loc,
+			  ("both %<long%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<short%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->signed_p)
+		error_at (loc,
+			  ("both %<signed%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->unsigned_p)
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->complex_p)
+		error_at (loc,
+			  ("both %<complex%> and %<_Bool%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		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_at (loc,
+			  ("both %<long%> and %<char%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<short%> and %<char%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		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_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_at (loc,
+			  ("both %<long%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<short%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->signed_p)
+		error_at (loc,
+			  ("both %<signed%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->unsigned_p)
+		error_at (loc,
+			  ("both %<unsigned%> and %<float%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		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_at (loc,
+			  ("both %<long long%> and %<double%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<short%> and %<double%> in "
+			   "declaration specifiers"));
+	      else if (specs->signed_p)
+		error_at (loc,
+			  ("both %<signed%> and %<double%> in "
+			   "declaration specifiers"));
+	      else if (specs->unsigned_p)
+		error_at (loc,
+			  ("both %<unsigned%> and %<double%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		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";
+		else if (i == RID_DFLOAT64)
+		  str = "_Decimal64";
+		else
+		  str = "_Decimal128";
+		if (specs->long_long_p)
+		  error_at (loc,
+			    ("both %<long long%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
+		if (specs->long_p)
+		  error_at (loc,
+			    ("both %<long%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
+		else if (specs->short_p)
+		  error_at (loc,
+			    ("both %<short%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
+		else if (specs->signed_p)
+		  error_at (loc,
+			    ("both %<signed%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
+		else if (specs->unsigned_p)
+		  error_at (loc,
+			    ("both %<unsigned%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
                 else if (specs->complex_p)
                   error_at (loc,
                 ("both %<complex%> and %<%s%> in "
@@ -9191,23 +9504,21 @@
       else
     specs->type = TREE_TYPE (t);
     }
-  else if (TREE_CODE (type) != ERROR_MARK)
-    {
-      if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
-    specs->tag_defined_p = true;
-      if (spec.kind == ctsk_typeof)
-    {
-      specs->typedef_p = true;
-      if (spec.expr)
-        {
-          if (specs->expr)
-        specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
-                      specs->expr, spec.expr);
-          else
-        specs->expr = spec.expr;
-          specs->expr_const_operands &= spec.expr_const_operands;
-        }
-    }
+  else
+    {
+      if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
+	{
+	  specs->typedef_p = true;
+	  if (spec.expr)
+	    {
+	      if (specs->expr)
+		specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+				      specs->expr, spec.expr);
+	      else
+		specs->expr = spec.expr;
+	      specs->expr_const_operands &= spec.expr_const_operands;
+	    }
+	}
       specs->type = type;
     }
 
@@ -9323,8 +9634,12 @@
   if (specs->type != NULL_TREE)
     {
       gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
-          && !specs->signed_p && !specs->unsigned_p
-          && !specs->complex_p);
+		  && !specs->signed_p && !specs->unsigned_p
+		  && !specs->complex_p);
+
+      /* Set a dummy type.  */
+      if (TREE_CODE (specs->type) == ERROR_MARK)
+        specs->type = integer_type_node;
       return specs;
     }
 
@@ -9403,6 +9718,19 @@
       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);
+	}
+      break;
     case cts_int:
       gcc_assert (!(specs->long_p && specs->short_p));
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
@@ -9568,7 +9896,7 @@
   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
@@ -9589,12 +9917,12 @@
   do
     {
       reconsider = false;
-      for (decl = globals; decl; decl = TREE_CHAIN (decl))
-    reconsider |= wrapup_global_declaration_2 (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);
 }
 
@@ -9606,10 +9934,49 @@
 {
   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;
+  unsigned i;
+
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, 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;
+  unsigned i;
+
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, 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;
 
@@ -9617,21 +9984,35 @@
 c_write_global_declarations (void)
 {
   tree t;
+  unsigned i;
 
   /* We don't want to do this if generating a PCH.  */
   if (pch_file)
     return;
 
-  /* Don't waste time on further processing if -fsyntax-only.
-     Continue for warning and errors issued during lowering though.  */
-  if (flag_syntax_only)
-    return;
+  /* Do the Objective-C stuff.  This is where all the Objective-C
+     module stuff gets generated (symtab, class/protocol/selector
+     lists etc).  */
+  if (c_dialect_objc ())
+    objc_write_global_declarations ();
 
   /* 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);
@@ -9646,7 +10027,7 @@
 
   /* 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_EACH_VEC_ELT (tree, all_translation_units, i, t)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
@@ -9656,11 +10037,11 @@
 
   /* 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))
-    c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
+      FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+	c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
       c_write_global_declarations_2 (BLOCK_VARS (ext_block));
       timevar_pop (TV_SYMOUT);
     }
@@ -9668,4 +10049,23 @@
   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"