OSDN Git Service

* function.c (assign_parms): For a struct value address passed as
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 3dcb055..2aa0ee7 100644 (file)
@@ -28,6 +28,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "intl.h"
 #include "tree.h"
 #include "tree-inline.h"
@@ -37,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "expr.h"
 #include "c-tree.h"
-#include "c-lex.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "tm_p.h"
@@ -47,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "cgraph.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -104,26 +106,21 @@ static int current_function_prototype_line;
 
 /* The current statement tree.  */
 
-static struct stmt_tree_s c_stmt_tree;
+static GTY(()) struct stmt_tree_s c_stmt_tree;
 
 /* The current scope statement stack.  */
 
-static tree c_scope_stmt_stack;
+static GTY(()) tree c_scope_stmt_stack;
 
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
 
-static tree named_labels;
+static GTY(()) tree named_labels;
 
 /* A list of LABEL_DECLs from outer contexts that are currently shadowed.  */
 
-static tree shadowed_labels;
-
-/* Nonzero when store_parm_decls is called indicates a varargs function.
-   Value not meaningful after store_parm_decls.  */
-
-static int c_function_varargs;
+static GTY(()) tree shadowed_labels;
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
@@ -165,7 +162,7 @@ static int current_extern_inline;
 /* Note that the information in the `names' component of the global contour
    is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers.  */
 
-struct binding_level
+struct binding_level GTY(())
   {
     /* A chain of _DECL nodes for all variables, constants, functions,
        and typedef types.  These are in the reverse of the order supplied.
@@ -216,9 +213,9 @@ struct binding_level
     /* Nonzero means make a BLOCK if this level has any subblocks.  */
     char keep_if_subblocks;
 
-    /* Number of decls in `names' that have incomplete
-       structure or union types.  */
-    int n_incomplete;
+    /* List of decls in `names' that have incomplete structure or
+       union types.  */
+    tree incomplete_list;
 
     /* A list of decls giving the (reversed) specified order of parms,
        not including any forward-decls in the parmlist.
@@ -230,22 +227,22 @@ struct binding_level
 
 /* The binding level currently in effect.  */
 
-static struct binding_level *current_binding_level;
+static GTY(()) struct binding_level *current_binding_level;
 
 /* A chain of binding_level structures awaiting reuse.  */
 
-static struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct binding_level *free_binding_level;
 
 /* The outermost binding level, for names of file scope.
    This is created when the compiler is started and exists
    through the entire run.  */
 
-static struct binding_level *global_binding_level;
+static GTY(()) struct binding_level *global_binding_level;
 
 /* Binding level structures are initialized by copying this one.  */
 
 static struct binding_level clear_binding_level
-  = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0,
+  = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
      NULL};
 
 /* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
@@ -263,7 +260,7 @@ static int keep_next_if_subblocks;
    saved values of named_labels and shadowed_labels for
    a label binding level outside the current one.  */
 
-static struct binding_level *label_level_chain;
+static GTY(()) struct binding_level *label_level_chain;
 
 /* Functions called automatically at the beginning and end of execution.  */
 
@@ -272,7 +269,7 @@ tree static_ctors, static_dtors;
 /* Forward declarations.  */
 
 static struct binding_level * make_binding_level       PARAMS ((void));
-static void mark_binding_level         PARAMS ((void *));
+static void pop_binding_level          PARAMS ((struct binding_level **));
 static void clear_limbo_values         PARAMS ((tree));
 static int duplicate_decls             PARAMS ((tree, tree, int));
 static int redeclaration_error_message PARAMS ((tree, tree));
@@ -286,153 +283,10 @@ static tree grokdeclarator               PARAMS ((tree, tree, enum decl_context,
 static tree grokparms                  PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
 static tree c_make_fname_decl           PARAMS ((tree, int));
-static void c_expand_body               PARAMS ((tree, int, int));
+static void c_expand_body_1             PARAMS ((tree, int));
 static void warn_if_shadowing          PARAMS ((tree, tree));
+static bool flexible_array_type_p      PARAMS ((tree));
 \f
-/* C-specific option variables.  */
-
-/* Nonzero means allow type mismatches in conditional expressions;
-   just make their values `void'.  */
-
-int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'.  */
-
-int flag_no_asm;
-
-/* Nonzero means enable C89 Amendment 1 features.  */
-
-int flag_isoc94 = 0;
-
-/* Nonzero means use the ISO C99 dialect of C.  */
-
-int flag_isoc99 = 0;
-
-/* Nonzero means that we have builtin functions, and main is an int */
-
-int flag_hosted = 1;
-
-/* Nonzero means add default format_arg attributes for functions not
-   in ISO C.  */
-
-int flag_noniso_default_format_attributes = 1;
-
-/* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
-
-int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields = 0;
-
-/* Nonzero means warn about use of implicit int.  */
-
-int warn_implicit_int;
-
-/* Nonzero means warn about usage of long long when `-pedantic'.  */
-
-int warn_long_long = 1;
-
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error.  */
-
-int mesg_implicit_function_declaration = -1;
-
-/* Nonzero means give string constants the type `const char *'
-   to get extra warnings from them.  These warnings will be too numerous
-   to be useful, except in thoroughly ANSIfied programs.  */
-
-int flag_const_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
-   from the pointer target type.  */
-
-int warn_cast_qual;
-
-/* Nonzero means warn when casting a function call to a type that does
-   not match the return type (e.g. (float)sqrt() or (anything*)malloc()
-   when there is no previous declaration of sqrt or malloc.  */
-
-int warn_bad_function_cast;
-
-/* Warn about functions which might be candidates for format attributes.  */
-
-int warn_missing_format_attribute;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C.  */
-
-int warn_traditional;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
-   of function pointers.  */
-
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
-   or non-prototyped defs without previous prototype.  */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
-   without separate previous prototype decl.  */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn for any global function def
-   without separate previous decl.  */
-
-int warn_missing_declarations;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
-   variable or function.  */
-
-int warn_redundant_decls = 0;
-
-/* Nonzero means warn about extern declarations of objects not at
-   file-scope level and about *all* declarations of functions (whether
-   extern or static) not at file-scope level.  Note that we exclude
-   implicit function declarations.  To get warnings about those, use
-   -Wimplicit.  */
-
-int warn_nested_externs = 0;
-
-/* Warn about a subscript that has type char.  */
-
-int warn_char_subscripts = 0;
-
-/* Warn if a type conversion is done that might have confusing results.  */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested.  */
-
-int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed.  */
-
-int warn_missing_braces;
-
-/* Warn if main is suspicious.  */
-
-int warn_main;
-
-/* Warn about #pragma directives that are not recognised.  */
-
-int warn_unknown_pragmas = 0; /* Tri state variable.  */
-
-/* Warn about comparison of signed and unsigned values.
-   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
-
-int warn_sign_compare = -1;
-
-/* Warn about testing equality of floating point numbers.  */
-
-int warn_float_equal = 0;
-
-/* Nonzero means `$' can be in an identifier.  */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
@@ -445,271 +299,6 @@ enum deprecated_states {
 
 static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
-/* Decode the string P as a language-specific option for C.
-   Return the number of strings consumed.  Should not complain
-   if it does not recognise the option.  */
-
-int
-c_decode_option (argc, argv)
-     int argc ATTRIBUTE_UNUSED;
-     char **argv;
-{
-  int strings_processed;
-  char *p = argv[0];
-
-  static const struct {
-      /* The name of the option.  */
-      const char *option;
-      /* If non-NULL, a flag variable to set to 0 or 1.  If NULL,
-         this means that cpp handles this option.  */
-      int *flag;
-  } warn_options[] = {
-    /* This list is in alphabetical order.  Keep it like that.  */
-    { "bad-function-cast", &warn_bad_function_cast },
-    { "cast-qual", &warn_cast_qual },
-    { "char-subscripts", &warn_char_subscripts },
-    { "comment", NULL },
-    { "comments", NULL },
-    { "conversion", &warn_conversion },
-    { "div-by-zero", &warn_div_by_zero },
-    { "float-equal", &warn_float_equal },
-    { "format-extra-args", &warn_format_extra_args },
-    { "format-zero-length", &warn_format_zero_length },
-    { "format-nonliteral", &warn_format_nonliteral },
-    { "format-security", &warn_format_security },
-    { "format-y2k", &warn_format_y2k },
-    { "implicit-function-declaration", &mesg_implicit_function_declaration },
-    { "implicit-int", &warn_implicit_int },
-    { "import", NULL },
-    { "long-long", &warn_long_long },
-    { "main", &warn_main },
-    { "missing-braces", &warn_missing_braces },
-    { "missing-declarations", &warn_missing_declarations },
-    { "missing-format-attribute", &warn_missing_format_attribute },
-    { "missing-prototypes", &warn_missing_prototypes },
-    { "multichar", &warn_multichar },
-    { "nested-externs", &warn_nested_externs },
-    { "nonnull", &warn_nonnull },
-    { "parentheses", &warn_parentheses },
-    { "pointer-arith", &warn_pointer_arith },
-    { "redundant-decls", &warn_redundant_decls },
-    { "return-type", &warn_return_type },
-    { "sequence-point", &warn_sequence_point },
-    { "sign-compare", &warn_sign_compare },
-    { "strict-prototypes", &warn_strict_prototypes },
-    { "traditional", &warn_traditional },
-    { "trigraphs", NULL },
-    { "undef", NULL },
-    { "write-strings", &flag_const_strings }
-  };
-
-  strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
-
-  if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
-    {
-      flag_hosted = 1;
-      flag_no_builtin = 0;
-    }
-  else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
-    {
-      flag_hosted = 0;
-      flag_no_builtin = 1;
-      /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
-      if (warn_main == 2)
-       warn_main = 0;
-    }
-  else if (!strncmp (p, "-std=", 5))
-    {
-      /* Select the appropriate language standard.  We currently
-        recognize:
-        -std=iso9899:1990      same as -ansi
-        -std=iso9899:199409    ISO C as modified in amend. 1
-        -std=iso9899:1999      ISO C 99
-        -std=c89               same as -std=iso9899:1990
-        -std=c99               same as -std=iso9899:1999
-        -std=gnu89             default, iso9899:1990 + gnu extensions
-        -std=gnu99             iso9899:1999 + gnu extensions
-      */
-      const char *const argstart = &p[5];
-
-      if (!strcmp (argstart, "iso9899:1990")
-         || !strcmp (argstart, "c89"))
-       {
-       iso_1990:
-         flag_isoc94 = 0;
-       iso_1994:
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 0;
-         flag_iso = 1;
-       }
-      else if (!strcmp (argstart, "iso9899:199409"))
-       {
-         flag_isoc94 = 1;
-         goto iso_1994;
-       }
-      else if (!strcmp (argstart, "iso9899:199x")
-              || !strcmp (argstart, "iso9899:1999")
-              || !strcmp (argstart, "c9x")
-              || !strcmp (argstart, "c99"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 1;
-         flag_isoc94 = 1;
-         flag_iso = 1;
-       }
-      else if (!strcmp (argstart, "gnu89"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 0;
-         flag_no_nonansi_builtin = 0;
-         flag_noniso_default_format_attributes = 1;
-         flag_isoc99 = 0;
-         flag_isoc94 = 0;
-       }
-      else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 0;
-         flag_no_nonansi_builtin = 0;
-         flag_noniso_default_format_attributes = 1;
-         flag_isoc99 = 1;
-         flag_isoc94 = 1;
-       }
-      else if (!strcmp (argstart, "c++98"))
-       ; /* Handled by cpplib.  */
-      else
-       error ("unknown C standard `%s'", argstart);
-    }
-  else if (!strcmp (p, "-fdollars-in-identifiers"))
-    dollars_in_ident = 1;
-  else if (!strcmp (p, "-fno-dollars-in-identifiers"))
-    dollars_in_ident = 0;
-  else if (!strcmp (p, "-fsigned-char"))
-    flag_signed_char = 1;
-  else if (!strcmp (p, "-funsigned-char"))
-    flag_signed_char = 0;
-  else if (!strcmp (p, "-fno-signed-char"))
-    flag_signed_char = 0;
-  else if (!strcmp (p, "-fno-unsigned-char"))
-    flag_signed_char = 1;
-  else if (!strcmp (p, "-fsigned-bitfields")
-          || !strcmp (p, "-fno-unsigned-bitfields"))
-    {
-      flag_signed_bitfields = 1;
-      explicit_flag_signed_bitfields = 1;
-    }
-  else if (!strcmp (p, "-funsigned-bitfields")
-          || !strcmp (p, "-fno-signed-bitfields"))
-    {
-      flag_signed_bitfields = 0;
-      explicit_flag_signed_bitfields = 1;
-    }
-  else if (!strcmp (p, "-fshort-enums"))
-    flag_short_enums = 1;
-  else if (!strcmp (p, "-fno-short-enums"))
-    flag_short_enums = 0;
-  else if (!strcmp (p, "-fshort-wchar"))
-    flag_short_wchar = 1;
-  else if (!strcmp (p, "-fno-short-wchar"))
-    flag_short_wchar = 0;
-  else if (!strcmp (p, "-fcond-mismatch"))
-    flag_cond_mismatch = 1;
-  else if (!strcmp (p, "-fno-cond-mismatch"))
-    flag_cond_mismatch = 0;
-  else if (!strcmp (p, "-fshort-double"))
-    flag_short_double = 1;
-  else if (!strcmp (p, "-fno-short-double"))
-    flag_short_double = 0;
-  else if (!strcmp (p, "-fasm"))
-    flag_no_asm = 0;
-  else if (!strcmp (p, "-fno-asm"))
-    flag_no_asm = 1;
-  else if (!strcmp (p, "-fbuiltin"))
-    flag_no_builtin = 0;
-  else if (!strcmp (p, "-fno-builtin"))
-    flag_no_builtin = 1;
-  else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
-    disable_builtin_function (p + strlen ("-fno-builtin-"));
-  else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
-    ;
-  else if (!strcmp (p, "-ansi"))
-    goto iso_1990;
-  else if (!strcmp (p, "-undef"))
-    flag_undef = 1;
-  else if (!strcmp (p, "-Werror-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 2;
-  else if (!strncmp (p, "-Wformat=", 9))
-    set_Wformat (atoi (p + 9));
-  else if (!strcmp (p, "-Wformat"))
-    set_Wformat (1);
-  else if (!strcmp (p, "-Wno-format"))
-    set_Wformat (0);
-  else if (!strcmp (p, "-Wimplicit"))
-    {
-      warn_implicit_int = 1;
-      if (mesg_implicit_function_declaration != 2)
-       mesg_implicit_function_declaration = 1;
-    }
-  else if (!strcmp (p, "-Wno-implicit"))
-    warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
-  else if (!strcmp (p, "-Wno-main"))
-    warn_main = -1;
-  else if (!strcmp (p, "-Wunknown-pragmas"))
-    /* Set to greater than 1, so that even unknown pragmas in system
-       headers will be warned about.  */
-    warn_unknown_pragmas = 2;
-  else if (!strcmp (p, "-Wno-unknown-pragmas"))
-    warn_unknown_pragmas = 0;
-  else if (!strcmp (p, "-Wall"))
-    {
-      /* We save the value of warn_uninitialized, since if they put
-        -Wuninitialized on the command line, we need to generate a
-        warning about not using it without also specifying -O.  */
-      if (warn_uninitialized != 1)
-       warn_uninitialized = 2;
-      warn_implicit_int = 1;
-      mesg_implicit_function_declaration = 1;
-      warn_return_type = 1;
-      set_Wunused (1);
-      warn_switch = 1;
-      set_Wformat (1);
-      warn_char_subscripts = 1;
-      warn_parentheses = 1;
-      warn_sequence_point = 1;
-      warn_missing_braces = 1;
-      /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
-        it off only if it's not explicit.  */
-      warn_main = 2;
-      /* Only warn about unknown pragmas that are not in system headers.  */
-      warn_unknown_pragmas = 1;
-    }
-  else if (!strcmp (p, "-E"))
-    flag_preprocess_only = 1;
-  else
-    {
-      size_t i;
-      for (i = 0; i < sizeof (warn_options) / sizeof (warn_options[0]); i++)
-       if (strncmp (p, "-W", 2) == 0 
-           && warn_options[i].flag
-           && (strcmp (p+2, warn_options[i].option) == 0
-               || (strncmp (p+2, "no-", 3) == 0
-                   && strcmp (p+5, warn_options[i].option) == 0)))
-         {
-           *(warn_options[i].flag) = strncmp (p+2, "no-", 3) != 0;
-           return 1;
-         }
-      return strings_processed;
-    }
-
-  return 1;
-}
-
 void
 c_print_identifier (file, node, indent)
      FILE *file;
@@ -756,13 +345,33 @@ c_finish_incomplete_decl (decl)
     }
 }
 \f
-/* Create a new `struct binding_level'.  */
+/* Reuse or create a struct for this binding level.  */
 
 static struct binding_level *
 make_binding_level ()
 {
-  /* NOSTRICT */
-  return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+  if (free_binding_level)
+    {
+      struct binding_level *result = free_binding_level;
+      free_binding_level = result->level_chain;
+      return result;
+    }
+  else
+    return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
+}
+
+/* Remove a binding level from a list and add it to the level chain.  */
+
+static void
+pop_binding_level (lp)
+     struct binding_level **lp;
+{
+  struct binding_level *l = *lp;
+  *lp = l->level_chain;
+  
+  memset (l, 0, sizeof (struct binding_level));
+  l->level_chain = free_binding_level;
+  free_binding_level = l;
 }
 
 /* Nonzero if we are currently in the global binding level.  */
@@ -830,17 +439,7 @@ pushlevel (tag_transparent)
       named_labels = 0;
     }
 
-  /* Reuse or create a struct for this binding level.  */
-
-  if (free_binding_level)
-    {
-      newlevel = free_binding_level;
-      free_binding_level = free_binding_level->level_chain;
-    }
-  else
-    {
-      newlevel = make_binding_level ();
-    }
+  newlevel = make_binding_level ();
 
   /* Add this level to the front of the chain (stack) of levels that
      are active.  */
@@ -1061,13 +660,7 @@ poplevel (keep, reverse, functionbody)
 
   /* Pop the current level, and free the structure for reuse.  */
 
-  {
-    struct binding_level *level = current_binding_level;
-    current_binding_level = current_binding_level->level_chain;
-
-    level->level_chain = free_binding_level;
-    free_binding_level = level;
-  }
+  pop_binding_level (&current_binding_level);
 
   /* Dispose of the block that we just made inside some higher level.  */
   if (functionbody)
@@ -1146,17 +739,7 @@ push_label_level ()
 {
   struct binding_level *newlevel;
 
-  /* Reuse or create a struct for this binding level.  */
-
-  if (free_binding_level)
-    {
-      newlevel = free_binding_level;
-      free_binding_level = free_binding_level->level_chain;
-    }
-  else
-    {
-      newlevel = make_binding_level ();
-    }
+  newlevel = make_binding_level ();
 
   /* Add this level to the front of the chain (stack) of label levels.  */
 
@@ -1218,9 +801,7 @@ pop_label_level ()
   shadowed_labels = level->shadowed;
 
   /* Pop the current level, and free the structure for reuse.  */
-  label_level_chain = label_level_chain->level_chain;
-  level->level_chain = free_binding_level;
-  free_binding_level = level;
+  pop_binding_level (&label_level_chain);
 }
 \f
 /* Push a definition or a declaration of struct, union or enum tag "name".
@@ -1560,6 +1141,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            }
        }
       error_with_decl (olddecl, "previous declaration of `%s'");
+
+      /* This is safer because the initializer might contain references
+        to variables that were declared between olddecl and newdecl. This
+        will make the initializer invalid for olddecl in case it gets
+        assigned to olddecl below.  */
+      if (TREE_CODE (newdecl) == VAR_DECL)
+       DECL_INITIAL (newdecl) = 0;
+    }
+  /* TLS cannot follow non-TLS declaration.  */
+  else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+          && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
+    {
+      error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
+      error_with_decl (olddecl, "previous declaration of `%s'");
+    }
+  /* non-TLS declaration cannot follow TLS declaration.  */
+  else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+          && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
+    {
+      error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
+      error_with_decl (olddecl, "previous declaration of `%s'");
     }
   else
     {
@@ -1769,11 +1371,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       COPY_DECL_RTL (olddecl, newdecl);
 
       /* Merge the type qualifiers.  */
-      if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
-         && ! TREE_THIS_VOLATILE (newdecl))
-       TREE_THIS_VOLATILE (write_olddecl) = 0;
-
       if (TREE_READONLY (newdecl))
        TREE_READONLY (write_olddecl) = 1;
 
@@ -1887,9 +1484,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         inline, make sure we emit debug info for the inline before we
         throw it away, in case it was inlined into a function that hasn't
         been written out yet.  */
-      if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+      if (new_is_definition && DECL_INITIAL (olddecl))
        {
-         (*debug_hooks->outlining_inline_function) (olddecl);
+         if (TREE_USED (olddecl))
+           (*debug_hooks->outlining_inline_function) (olddecl);
 
          /* The new defn must not be inline.  */
          DECL_INLINE (newdecl) = 0;
@@ -2138,7 +1736,7 @@ pushdecl (x)
        }
 
       /* If we are processing a typedef statement, generate a whole new
-        ..._TYPE node (which will be just an variant of the existing
+        ..._TYPE node (which will be just a variant of the existing
         ..._TYPE node with identical properties) and then install the
         TYPE_DECL node generated to represent the typedef name as the
         TYPE_NAME of this brand new (duplicate) ..._TYPE node.
@@ -2393,7 +1991,7 @@ pushdecl (x)
            b->shadowed = tree_cons (name, oldlocal, b->shadowed);
        }
 
-      /* Keep count of variables in this level with incomplete type.
+      /* Keep list of variables in this level with incomplete type.
         If the input is erroneous, we can have error_mark in the type
         slot (e.g. "f(void a, ...)") - that doesn't count as an
         incomplete type.  */
@@ -2406,7 +2004,7 @@ pushdecl (x)
            element = TREE_TYPE (element);
          if (TREE_CODE (element) == RECORD_TYPE
              || TREE_CODE (element) == UNION_TYPE)
-           ++b->n_incomplete;
+           b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
        }
     }
 
@@ -2473,8 +2071,9 @@ implicitly_declare (functionid)
      So we record the decl in the standard fashion.  */
   pushdecl (decl);
 
-  /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-  maybe_objc_check_decl (decl);
+  /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+  if (flag_objc)
+    objc_check_decl (decl);
 
   rest_of_decl_compilation (decl, NULL, 0, 0);
 
@@ -2865,25 +2464,6 @@ lookup_name_current_level (name)
   return t;
 }
 \f
-/* Mark ARG for GC.  */
-
-static void
-mark_binding_level (arg)
-     void *arg;
-{
-  struct binding_level *level = *(struct binding_level **) arg;
-
-  for (; level != 0; level = level->level_chain)
-    {
-      ggc_mark_tree (level->names);
-      ggc_mark_tree (level->tags);
-      ggc_mark_tree (level->shadowed);
-      ggc_mark_tree (level->blocks);
-      ggc_mark_tree (level->this_block);
-      ggc_mark_tree (level->parm_order);
-    }
-}
-
 /* Create the predefined scalar types of C,
    and some nodes representing standard constants (0, 1, (void *) 0).
    Initialize the global binding level.
@@ -2937,20 +2517,6 @@ c_init_decl_processing ()
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
-
-  /* Record our roots.  */
-
-  ggc_add_tree_root (c_global_trees, CTI_MAX);
-  ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
-  ggc_add_tree_root (&c_scope_stmt_stack, 1);
-  ggc_add_tree_root (&named_labels, 1);
-  ggc_add_tree_root (&shadowed_labels, 1);
-  ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
-               mark_binding_level);
-  ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
-               mark_binding_level);
-  ggc_add_tree_root (&static_ctors, 1);
-  ggc_add_tree_root (&static_dtors, 1);
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -2987,6 +2553,18 @@ c_make_fname_decl (id, type_dep)
   DECL_INITIAL (decl) = init;
 
   TREE_USED (decl) = 1;
+
+  if (current_function_decl)
+    {
+      /* Add the decls to the outermost block.  */
+      struct binding_level *b = current_binding_level;
+      struct binding_level *old = b;
+      while (b->level_chain->parm_flag == 0)
+       b = b->level_chain;
+      current_binding_level = b;
+      pushdecl (decl);
+      current_binding_level = old;
+    }  
   
   finish_decl (decl, init, NULL_TREE);
 
@@ -2999,15 +2577,17 @@ c_make_fname_decl (id, type_dep)
    See tree.h for its possible values.
 
    If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
-   the name to be called if we can't opencode the function.  */
+   the name to be called if we can't opencode the function.  If
+   ATTRS is nonzero, use that for the function's attribute list.  */
 
 tree
-builtin_function (name, type, function_code, class, library_name)
+builtin_function (name, type, function_code, class, library_name, attrs)
      const char *name;
      tree type;
      int function_code;
      enum built_in_class class;
      const char *library_name;
+     tree attrs;
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -3019,17 +2599,16 @@ builtin_function (name, type, function_code, class, library_name)
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = function_code;
 
-  /* The return builtins leave the current function.  */
-  if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
-    TREE_THIS_VOLATILE (decl) = 1;
-
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
   if (name[0] != '_' || name[1] != '_')
     C_DECL_ANTICIPATED (decl) = 1;
 
   /* Possibly apply some default attributes to this built-in function.  */
-  decl_attributes (&decl, NULL_TREE, 0);
+  if (attrs)
+    decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+  else
+    decl_attributes (&decl, NULL_TREE, 0);
 
   return decl;
 }
@@ -3135,8 +2714,8 @@ shadow_tag_warned (declspecs, warned)
 /* Construct an array declarator.  EXPR is the expression inside [], or
    NULL_TREE.  QUALS are the type qualifiers inside the [] (to be applied
    to the pointer to which a parameter array is converted).  STATIC_P is
-   non-zero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
-   is non-zero is the array is [*], a VLA of unspecified length which is
+   nonzero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
+   is nonzero is the array is [*], a VLA of unspecified length which is
    nevertheless a complete type (not currently implemented by GCC),
    zero otherwise.  The declarator is constructed as an ARRAY_REF
    (to be decoded by grokdeclarator), whose operand 0 is what's on the
@@ -3158,9 +2737,9 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
   if (pedantic && !flag_isoc99)
     {
       if (static_p || quals != NULL_TREE)
-       pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+       pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
       if (vla_unspec_p)
-       pedwarn ("ISO C89 does not support `[*]' array declarators");
+       pedwarn ("ISO C90 does not support `[*]' array declarators");
     }
   if (vla_unspec_p)
     warning ("GCC does not yet properly implement `[*]' array declarators");
@@ -3169,7 +2748,7 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
 
 /* Set the type of an array declarator.  DECL is the declarator, as
    constructed by build_array_declarator; TYPE is what appears on the left
-   of the [] and goes in operand 0.  ABSTRACT_P is non-zero if it is an
+   of the [] and goes in operand 0.  ABSTRACT_P is nonzero if it is an
    abstract declarator, zero otherwise; this is used to reject static and
    type qualifiers in abstract declarators, where they are not in the
    C99 grammar.  */
@@ -3265,15 +2844,9 @@ start_decl (declarator, declspecs, initialized, attributes)
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       /* typedef foo = bar  means give foo the same type as bar.
-          We haven't parsed bar yet, so `finish_decl' will fix that up.
-          Any other case of an initialization in a TYPE_DECL is an error.  */
-       if (pedantic || list_length (declspecs) > 1)
-         {
-           error ("typedef `%s' is initialized",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
-           initialized = 0;
-         }
+       error ("typedef `%s' is initialized (use __typeof__ instead)",
+              IDENTIFIER_POINTER (DECL_NAME (decl)));
+       initialized = 0;
        break;
 
       case FUNCTION_DECL:
@@ -3357,7 +2930,7 @@ start_decl (declarator, declspecs, initialized, attributes)
 
      Thread-local variables are never common, since there's no entrenched
      body of code to break, and it allows more efficient variable references
-     in the presense of dynamic linking.  */
+     in the presence of dynamic linking.  */
 
   if (TREE_CODE (decl) == VAR_DECL
       && !initialized
@@ -3432,16 +3005,7 @@ finish_decl (decl, init, asmspec_tree)
     init = 0;
 
   if (init)
-    {
-      if (TREE_CODE (decl) != TYPE_DECL)
-       store_init_value (decl, init);
-      else
-       {
-         /* typedef foo = bar; store the type of bar as the type of foo.  */
-         TREE_TYPE (decl) = TREE_TYPE (init);
-         DECL_INITIAL (decl) = init = 0;
-       }
-    }
+    store_init_value (decl, init);
 
   /* Deduce size of array from initialization, if not already known */
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -3543,8 +3107,9 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
     {
-      /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-      maybe_objc_check_decl (decl);
+      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+      if (flag_objc)
+       objc_check_decl (decl);
 
       if (!DECL_CONTEXT (decl))
        {
@@ -3606,8 +3171,9 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == TYPE_DECL)
     {
-      /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-      maybe_objc_check_decl (decl);
+      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+      if (flag_objc)
+       objc_check_decl (decl);
       rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
     }
 
@@ -3668,6 +3234,8 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+static GTY(()) int compound_literal_number;
+
 /* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
    literal, which may be an incomplete array type completed by the
    initializer; INIT is a CONSTRUCTOR that initializes the compound
@@ -3690,6 +3258,7 @@ build_compound_literal (type, init)
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
+  TREE_READONLY (decl) = TREE_READONLY (type);
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
@@ -3712,12 +3281,18 @@ build_compound_literal (type, init)
   if (TREE_STATIC (decl))
     {
       /* This decl needs a name for the assembler output.  We also need
-        a unique suffix to be added to the name, for which DECL_CONTEXT
-        must be set.  */
-      DECL_NAME (decl) = get_identifier ("__compound_literal");
-      DECL_CONTEXT (decl) = complit;
+        a unique suffix to be added to the name.  */
+      char *name;
+
+      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", 
+                              compound_literal_number);
+      compound_literal_number++;
+      DECL_NAME (decl) = get_identifier (name);
+      DECL_DEFER_OUTPUT (decl) = 1;
+      DECL_COMDAT (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      pushdecl (decl);
       rest_of_decl_compilation (decl, NULL, 1, 0);
-      DECL_CONTEXT (decl) = NULL_TREE;
     }
 
   return complit;
@@ -3793,6 +3368,40 @@ complete_array_type (type, initial_value, do_default)
   return value;
 }
 \f
+/* Determine whether TYPE is a structure with a flexible array member,
+   or a union containing such a structure (possibly recursively).  */
+
+static bool
+flexible_array_type_p (type)
+     tree type;
+{
+  tree x;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      x = TYPE_FIELDS (type);
+      if (x == NULL_TREE)
+       return false;
+      while (TREE_CHAIN (x) != NULL_TREE)
+       x = TREE_CHAIN (x);
+      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)
+       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;
+       }
+      return false;
+    default:
+    return false;
+  }
+}
+\f
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -3952,12 +3561,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                    {
                      if (pedantic && !flag_isoc99 && ! in_system_header
                          && warn_long_long)
-                       pedwarn ("ISO C89 does not support `long long'");
+                       pedwarn ("ISO C90 does not support `long long'");
                      longlong = 1;
                    }
                }
              else if (specbits & (1 << (int) i))
-               pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+               {
+                 if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
+                   {
+                     if (!flag_isoc99)
+                       pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+                   }
+                 else
+                   error ("duplicate `%s'", IDENTIFIER_POINTER (id));
+               }
 
              /* Diagnose "__thread extern".  Recall that this list
                 is in the reverse order seen in the text.  */
@@ -4090,12 +3707,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else
        {
          ok = 1;
-         if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+         if (!explicit_int && !defaulted_int && !explicit_char)
            {
-             pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
-                      name);
-             if (flag_pedantic_errors)
-               ok = 0;
+             error ("long, short, signed or unsigned used invalidly for `%s'",
+                    name);
+             ok = 0;
            }
        }
 
@@ -4153,7 +3769,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if (specbits & 1 << (int) RID_COMPLEX)
     {
       if (pedantic && !flag_isoc99)
-       pedwarn ("ISO C89 does not support complex types");
+       pedwarn ("ISO C90 does not support complex types");
       /* If we just have "complex", it is equivalent to
         "complex double", but if any modifiers at all are specified it is
         the complex form of TYPE.  E.g, "complex short" is
@@ -4389,6 +4005,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = error_mark_node;
            }
 
+         if (pedantic && flexible_array_type_p (type))
+           pedwarn ("invalid use of structure with flexible array member");
+
          if (size == error_mark_node)
            type = error_mark_node;
 
@@ -4431,10 +4050,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                  if (!flag_isoc99 && pedantic)
                    {
                      if (TREE_CONSTANT (size))
-                       pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+                       pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
                                 name);
                      else
-                       pedwarn ("ISO C89 forbids variable-size array `%s'",
+                       pedwarn ("ISO C90 forbids variable-size array `%s'",
                                 name);
                    }
                }
@@ -4477,7 +4096,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          else if (decl_context == FIELD)
            {
              if (pedantic && !flag_isoc99 && !in_system_header)
-               pedwarn ("ISO C89 does not support flexible array members");
+               pedwarn ("ISO C90 does not support flexible array members");
 
              /* ISO C99 Flexible array members are effectively identical
                 to GCC's zero-length array extension.  */
@@ -4564,7 +4183,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            {
              /* Type qualifiers on a function return type are normally
                 permitted by the standard but have no effect, so give a
-                warning at -W.  Qualifiers on a void return type have
+                warning at -Wextra.  Qualifiers on a void return type have
                 meaning as a GNU extension, and are banned on function
                 definitions in ISO C.  FIXME: strictly we shouldn't
                 pedwarn for qualified void return types except on function
@@ -4949,6 +4568,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
           needed, and let dwarf2 know that the function is inlinable.  */
        else if (flag_inline_trees == 2 && initialized)
          {
+           if (!DECL_INLINE (decl))
+               DID_INLINE_FUNC (decl) = 1;
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
          }
@@ -5359,25 +4980,22 @@ start_struct (code, name)
     ref = lookup_tag (code, name, current_binding_level, 1);
   if (ref && TREE_CODE (ref) == code)
     {
-      C_TYPE_BEING_DEFINED (ref) = 1;
-      TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
         {
          if (code == UNION_TYPE)
-           error ("redefinition of `union %s'",
-                  IDENTIFIER_POINTER (name));
+           error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
           else
-           error ("redefinition of `struct %s'",
-                  IDENTIFIER_POINTER (name));
+           error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
        }  
-
-      return ref;
     }
+  else
+    {
+      /* Otherwise create a forward-reference just so the tag is in scope.  */
 
-  /* Otherwise create a forward-reference just so the tag is in scope.  */
-
-  ref = make_node (code);
-  pushtag (name, ref);
+      ref = make_node (code);
+      pushtag (name, ref);
+    }
+  
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
   return ref;
@@ -5401,12 +5019,44 @@ grokfield (filename, line, declarator, declspecs, width)
 
   if (declarator == NULL_TREE && width == NULL_TREE)
     {
-      /* This is an unnamed decl.  We only support unnamed
-        structs/unions, so check for other things and refuse them.  */
-      if (TREE_CODE (TREE_VALUE (declspecs)) != RECORD_TYPE
-         && TREE_CODE (TREE_VALUE (declspecs)) != UNION_TYPE)
+      /* 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...  */
+
+      tree type = TREE_VALUE (declspecs);
+
+      if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
+       type = TREE_TYPE (type);
+      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
        {
-         error ("unnamed fields of type other than struct or union are not allowed");
+         if (flag_ms_extensions)
+           ; /* ok */
+         else if (flag_iso)
+           goto warn_unnamed_field;
+         else if (TYPE_NAME (type) == NULL)
+           ; /* ok */
+         else
+           goto warn_unnamed_field;
+       }
+      else
+       {
+       warn_unnamed_field:
+         warning ("declaration does not declare anything");
          return NULL_TREE;
        }
     }
@@ -5416,7 +5066,8 @@ grokfield (filename, line, declarator, declspecs, width)
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
-  maybe_objc_check_decl (value);
+  if (flag_objc)
+    objc_check_decl (value);
   return value;
 }
 \f
@@ -5619,6 +5270,11 @@ finish_struct (t, fieldlist, attributes)
          else if (! saw_named_field)
            error_with_decl (x, "flexible array member in otherwise empty struct");
        }
+
+      if (pedantic && TREE_CODE (t) == RECORD_TYPE
+         && flexible_array_type_p (TREE_TYPE (x)))
+       pedwarn_with_decl (x, "invalid use of structure with flexible array member");
+
       if (DECL_NAME (x))
        saw_named_field = 1;
     }
@@ -5692,22 +5348,29 @@ finish_struct (t, fieldlist, attributes)
   /* If this structure or union completes the type of any previous
      variable declaration, lay it out and output its rtl.  */
 
-  if (current_binding_level->n_incomplete != 0)
+  if (current_binding_level->incomplete_list != NULL_TREE)
     {
-      tree decl;
-      for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
-       {
+      tree prev = NULL_TREE;
+
+      for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
+        {
+         tree decl = TREE_VALUE (x);
+
          if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
              && TREE_CODE (decl) != TYPE_DECL)
            {
              layout_decl (decl, 0);
-             /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-             maybe_objc_check_decl (decl);
+             /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+             if (flag_objc)
+               objc_check_decl (decl);
              rest_of_decl_compilation (decl, NULL, toplevel, 0);
              if (! toplevel)
                expand_decl (decl);
-             if (--current_binding_level->n_incomplete == 0)
-               break;
+             /* Unlink X from the incomplete list.  */
+             if (prev)
+               TREE_CHAIN (prev) = TREE_CHAIN (x);
+             else
+               current_binding_level->incomplete_list = TREE_CHAIN (x);
            }
          else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -5721,13 +5384,17 @@ finish_struct (t, fieldlist, attributes)
                  if (TREE_CODE (decl) != TYPE_DECL)
                    {
                      layout_decl (decl, 0);
-                     maybe_objc_check_decl (decl);
+                     if (flag_objc)
+                       objc_check_decl (decl);
                      rest_of_decl_compilation (decl, NULL, toplevel, 0);
                      if (! toplevel)
                        expand_decl (decl);
                    }
-                 if (--current_binding_level->n_incomplete == 0)
-                   break;
+                 /* Unlink X from the incomplete list.  */
+                 if (prev)
+                   TREE_CHAIN (prev) = TREE_CHAIN (x);
+                 else
+                   current_binding_level->incomplete_list = TREE_CHAIN (x);
                }
            }
        }
@@ -6024,7 +5691,6 @@ start_function (declspecs, declarator, attributes)
   current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
-  c_function_varargs = 0;
   named_labels = 0;
   shadowed_labels = 0;
 
@@ -6243,16 +5909,6 @@ start_function (declspecs, declarator, attributes)
   
   return 1;
 }
-
-/* Record that this function is going to be a varargs function.
-   This is called before store_parm_decls, which is too early
-   to call mark_varargs directly.  */
-
-void
-c_mark_varargs ()
-{
-  c_function_varargs = 1;
-}
 \f
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
@@ -6760,10 +6416,62 @@ finish_function (nested, can_defer_p)
   free_after_compilation (cfun);
   cfun = NULL;
 
+  if (flag_unit_at_a_time && can_defer_p)
+    {
+      cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+      current_function_decl = NULL;
+      return;
+    }
+
   if (! nested)
     {
-      /* Generate RTL for the body of this function.  */
-      c_expand_body (fndecl, nested, can_defer_p);
+      /* Function is parsed.
+        Generate RTL for the body of this function or defer
+        it for later expansion.  */
+      int uninlinable = 1;
+
+      /* There's no reason to do any of the work here if we're only doing
+        semantic analysis; this code just generates RTL.  */
+      if (flag_syntax_only)
+       {
+         current_function_decl = NULL;
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+         return;
+       }
+
+      if (flag_inline_trees)
+       {
+         /* First, cache whether the current function is inlinable.  Some
+            predicates depend on cfun and current_function_decl to
+            function completely.  */
+         timevar_push (TV_INTEGRATION);
+         uninlinable = ! tree_inlinable_function_p (fndecl, 0);
+         
+         if (! uninlinable && can_defer_p
+             /* Save function tree for inlining.  Should return 0 if the
+                language does not support function deferring or the
+                function could not be deferred.  */
+             && defer_fn (fndecl))
+           {
+             /* Let the back-end know that this function exists.  */
+             (*debug_hooks->deferred_inline_function) (fndecl);
+             timevar_pop (TV_INTEGRATION);
+             current_function_decl = NULL;
+             return;
+           }
+         
+         /* Then, inline any functions called in it.  */
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+
+      c_expand_body (fndecl);
+
+      if (uninlinable)
+       {
+         /* Allow the body of the function to be garbage collected.  */
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+       }
 
       /* Let the error reporting routines know that we're outside a
         function.  For a nested function, this value is used in
@@ -6782,53 +6490,27 @@ c_expand_deferred_function (fndecl)
      function was deferred, e.g. in duplicate_decls.  */
   if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
     {
-      c_expand_body (fndecl, 0, 0);
+      if (flag_inline_trees)
+       {
+         timevar_push (TV_INTEGRATION);
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+      c_expand_body (fndecl);
       current_function_decl = NULL;
     }
 }
 
-/* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
+/* Generate the RTL for the body of FNDECL.  If NESTED_P is nonzero,
    then we are already in the process of generating RTL for another
    function.  If can_defer_p is zero, we won't attempt to defer the
    generation of RTL.  */
 
 static void
-c_expand_body (fndecl, nested_p, can_defer_p)
+c_expand_body_1 (fndecl, nested_p)
      tree fndecl;
-     int nested_p, can_defer_p;
+     int nested_p;
 {
-  int uninlinable = 1;
-
-  /* There's no reason to do any of the work here if we're only doing
-     semantic analysis; this code just generates RTL.  */
-  if (flag_syntax_only)
-    return;
-
-  if (flag_inline_trees)
-    {
-      /* First, cache whether the current function is inlinable.  Some
-         predicates depend on cfun and current_function_decl to
-         function completely.  */
-      timevar_push (TV_INTEGRATION);
-      uninlinable = ! tree_inlinable_function_p (fndecl);
-      
-      if (! uninlinable && can_defer_p
-         /* Save function tree for inlining.  Should return 0 if the
-             language does not support function deferring or the
-             function could not be deferred.  */
-         && defer_fn (fndecl))
-       {
-         /* Let the back-end know that this function exists.  */
-         (*debug_hooks->deferred_inline_function) (fndecl);
-          timevar_pop (TV_INTEGRATION);
-         return;
-       }
-      
-      /* Then, inline any functions called in it.  */
-      optimize_inline_calls (fndecl);
-      timevar_pop (TV_INTEGRATION);
-    }
-
   timevar_push (TV_EXPAND);
 
   if (nested_p)
@@ -6844,6 +6526,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   current_function_decl = fndecl;
   input_filename = DECL_SOURCE_FILE (fndecl);
   init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+  lineno = DECL_SOURCE_LINE (fndecl);
 
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
@@ -6855,10 +6538,6 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
 
-  /* If this is a varargs function, inform function.c.  */
-  if (c_function_varargs)
-    mark_varargs ();
-
   /* Set up parameters and prepare for return, for the function.  */
   expand_function_start (fndecl, 0);
 
@@ -6871,11 +6550,6 @@ c_expand_body (fndecl, nested_p, can_defer_p)
 
   /* Generate the RTL for this function.  */
   expand_stmt (DECL_SAVED_TREE (fndecl));
-  if (uninlinable)
-    {
-      /* Allow the body of the function to be garbage collected.  */
-      DECL_SAVED_TREE (fndecl) = NULL_TREE;
-    }
 
   /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
@@ -6902,7 +6576,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   if (nested_p)
     ggc_pop_context ();
 
-  /* With just -W, complain only if function returns both with
+  /* With just -Wextra, complain only if function returns both with
      and without a value.  */
   if (extra_warnings
       && current_function_returns_value
@@ -6973,6 +6647,15 @@ c_expand_body (fndecl, nested_p, can_defer_p)
     pop_function_context ();
   timevar_pop (TV_EXPAND);
 }
+
+/* Like c_expand_body_1 but only for unnested functions.  */
+
+void
+c_expand_body (fndecl)
+     tree fndecl;
+{
+  c_expand_body_1 (fndecl, 0);
+}
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  */
@@ -7036,9 +6719,9 @@ check_for_loop_decls ()
    that keep track of the progress of compilation of the current function.
    Used for nested functions.  */
 
-struct c_language_function
+struct language_function GTY(())
 {
-  struct language_function base;
+  struct c_language_function base;
   tree named_labels;
   tree shadowed_labels;
   int returns_value;
@@ -7056,10 +6739,10 @@ void
 c_push_function_context (f)
      struct function *f;
 {
-  struct c_language_function *p;
-  p = ((struct c_language_function *)
-       xmalloc (sizeof (struct c_language_function)));
-  f->language = (struct language_function *) p;
+  struct language_function *p;
+  p = ((struct language_function *)
+       ggc_alloc (sizeof (struct language_function)));
+  f->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
   p->base.x_scope_stmt_stack = c_scope_stmt_stack;
@@ -7079,8 +6762,7 @@ void
 c_pop_function_context (f)
      struct function *f;
 {
-  struct c_language_function *p
-    = (struct c_language_function *) f->language;
+  struct language_function *p = f->language;
   tree link;
 
   /* Bring back all the labels that were shadowed.  */
@@ -7110,26 +6792,7 @@ c_pop_function_context (f)
   current_extern_inline = p->extern_inline;
   current_binding_level = p->binding_level;
 
-  free (p);
-  f->language = 0;
-}
-
-/* Mark the language specific parts of F for GC.  */
-
-void
-c_mark_function_context (f)
-     struct function *f;
-{
-  struct c_language_function *p
-    = (struct c_language_function *) f->language;
-
-  if (p == 0)
-    return;
-
-  mark_c_language_function (&p->base);
-  ggc_mark_tree (p->shadowed_labels);
-  ggc_mark_tree (p->named_labels);
-  mark_binding_level (&p->binding_level);
+  f->language = NULL;
 }
 
 /* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
@@ -7149,38 +6812,12 @@ c_dup_lang_specific_decl (decl)
   DECL_LANG_SPECIFIC (decl) = ld;
 }
 
-/* Mark the language specific bits in T for GC.  */
-
-void
-c_mark_tree (t)
-     tree t;
-{
-  if (TREE_CODE (t) == IDENTIFIER_NODE)
-    {
-      struct lang_identifier *i = (struct lang_identifier *) t;
-      ggc_mark_tree (i->global_value);
-      ggc_mark_tree (i->local_value);
-      ggc_mark_tree (i->label_value);
-      ggc_mark_tree (i->implicit_decl);
-      ggc_mark_tree (i->error_locus);
-      ggc_mark_tree (i->limbo_value);
-    }
-  else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
-    ggc_mark (TYPE_LANG_SPECIFIC (t));
-  else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
-    {
-      ggc_mark (DECL_LANG_SPECIFIC (t));
-      c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
-      ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
-    }
-}
-
 /* The functions below are required for functionality of doing
    function at once processing in the C front end. Currently these
    functions are not called from anywhere in the C front end, but as
    these changes continue, that will change.  */
 
-/* Returns non-zero if the current statement is a full expression,
+/* Returns nonzero if the current statement is a full expression,
    i.e. temporaries created during that statement should be destroyed
    at the end of the statement.  */
 
@@ -7252,7 +6889,7 @@ c_expand_decl_stmt (t)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_CONTEXT (decl) == current_function_decl
       && DECL_SAVED_TREE (decl))
-    c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
+    c_expand_body_1 (decl, 1);
 }
 
 /* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
@@ -7289,3 +6926,26 @@ build_void_list_node ()
   tree t = build_tree_list (NULL_TREE, void_type_node);
   return t;
 }
+
+/* Return something to represent absolute declarators containing a *.
+   TARGET is the absolute declarator that the * contains.
+   TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
+   to apply to the pointer type, represented as identifiers, possible mixed
+   with attributes.
+
+   We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
+   if attributes are present) and whose type is the modifier list.  */
+
+tree
+make_pointer_declarator (type_quals_attrs, target)
+     tree type_quals_attrs, target;
+{
+  tree quals, attrs;
+  tree itarget = target;
+  split_specs_attrs (type_quals_attrs, &quals, &attrs);
+  if (attrs != NULL_TREE)
+    itarget = tree_cons (attrs, target, NULL_TREE);
+  return build1 (INDIRECT_REF, quals, itarget);
+}
+
+#include "gt-c-decl.h"