OSDN Git Service

* c-decl.c (grokdeclarator): Make error for duplicate type
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index ee45b8f..9c3b58f 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001 Free Software Foundation, Inc.
+   2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -37,13 +37,15 @@ 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"
 #include "cpplib.h"
 #include "target.h"
 #include "debug.h"
+#include "timevar.h"
+#include "c-common.h"
+#include "c-pragma.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -101,26 +103,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.  */
@@ -132,6 +129,11 @@ int current_function_returns_value;
 
 int current_function_returns_null;
 
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a call to a noreturn function is seen.  */
+
+int current_function_returns_abnormally;
+
 /* Set to nonzero by `grokdeclarator' for a function
    whose return type is defaulted, if warnings for this are desired.  */
 
@@ -157,7 +159,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.
@@ -208,9 +210,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.
@@ -222,22 +224,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.  */
@@ -255,7 +257,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.  */
 
@@ -264,7 +266,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));
@@ -278,532 +280,24 @@ 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));
+static void c_expand_body               PARAMS ((tree, int, 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 do some things the same way PCC does.  */
-
-int flag_traditional;
-
-/* 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 allow single precision math even if we're generally
-   being traditional.  */
-int flag_allow_single_precision = 0;
-
-/* 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 warn about use of multicharacter literals.  */
-
-int warn_multichar = 1;
-
-/* The variant of the C language being processed.  */
-
-c_language_kind c_language = clk_c;
-
-/* Nonzero means `$' can be in an identifier.  */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
-/* 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];
-
-  strings_processed = cpp_handle_option (parse_in, argc, argv);
-
-  if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
-    {
-      flag_traditional = 1;
-      flag_writable_strings = 1;
-    }
-  else if (!strcmp (p, "-fallow-single-precision"))
-    flag_allow_single_precision = 1;
-  else 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 (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
-    {
-      flag_traditional = 0;
-      flag_writable_strings = 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_traditional = 0;
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 0;
-       }
-      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_traditional = 0;
-         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;
-       }
-      else if (!strcmp (argstart, "gnu89"))
-       {
-         flag_traditional = 0;
-         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_traditional = 0;
-         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
-       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 (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
-    ;
-  else if (!strcmp (p, "-ansi"))
-    goto iso_1990;
-  else if (!strcmp (p, "-Werror-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 2;
-  else if (!strcmp (p, "-Wimplicit-function-declaration"))
-    mesg_implicit_function_declaration = 1;
-  else if (!strcmp (p, "-Wno-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 0;
-  else if (!strcmp (p, "-Wimplicit-int"))
-    warn_implicit_int = 1;
-  else if (!strcmp (p, "-Wno-implicit-int"))
-    warn_implicit_int = 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, "-Wlong-long"))
-    warn_long_long = 1;
-  else if (!strcmp (p, "-Wno-long-long"))
-    warn_long_long = 0;
-  else if (!strcmp (p, "-Wwrite-strings"))
-    flag_const_strings = 1;
-  else if (!strcmp (p, "-Wno-write-strings"))
-    flag_const_strings = 0;
-  else if (!strcmp (p, "-Wcast-qual"))
-    warn_cast_qual = 1;
-  else if (!strcmp (p, "-Wno-cast-qual"))
-    warn_cast_qual = 0;
-  else if (!strcmp (p, "-Wbad-function-cast"))
-    warn_bad_function_cast = 1;
-  else if (!strcmp (p, "-Wno-bad-function-cast"))
-    warn_bad_function_cast = 0;
-  else if (!strcmp (p, "-Wno-missing-noreturn"))
-    warn_missing_noreturn = 0;
-  else if (!strcmp (p, "-Wmissing-format-attribute"))
-    warn_missing_format_attribute = 1;
-  else if (!strcmp (p, "-Wno-missing-format-attribute"))
-    warn_missing_format_attribute = 0;
-  else if (!strcmp (p, "-Wpointer-arith"))
-    warn_pointer_arith = 1;
-  else if (!strcmp (p, "-Wno-pointer-arith"))
-    warn_pointer_arith = 0;
-  else if (!strcmp (p, "-Wstrict-prototypes"))
-    warn_strict_prototypes = 1;
-  else if (!strcmp (p, "-Wno-strict-prototypes"))
-    warn_strict_prototypes = 0;
-  else if (!strcmp (p, "-Wmissing-prototypes"))
-    warn_missing_prototypes = 1;
-  else if (!strcmp (p, "-Wno-missing-prototypes"))
-    warn_missing_prototypes = 0;
-  else if (!strcmp (p, "-Wmissing-declarations"))
-    warn_missing_declarations = 1;
-  else if (!strcmp (p, "-Wno-missing-declarations"))
-    warn_missing_declarations = 0;
-  else if (!strcmp (p, "-Wredundant-decls"))
-    warn_redundant_decls = 1;
-  else if (!strcmp (p, "-Wno-redundant-decls"))
-    warn_redundant_decls = 0;
-  else if (!strcmp (p, "-Wnested-externs"))
-    warn_nested_externs = 1;
-  else if (!strcmp (p, "-Wno-nested-externs"))
-    warn_nested_externs = 0;
-  else if (!strcmp (p, "-Wtraditional"))
-    warn_traditional = 1;
-  else if (!strcmp (p, "-Wno-traditional"))
-    warn_traditional = 0;
-  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, "-Wformat-y2k"))
-    warn_format_y2k = 1;
-  else if (!strcmp (p, "-Wno-format-y2k"))
-    warn_format_y2k = 0;
-  else if (!strcmp (p, "-Wformat-extra-args"))
-    warn_format_extra_args = 1;
-  else if (!strcmp (p, "-Wno-format-extra-args"))
-    warn_format_extra_args = 0;
-  else if (!strcmp (p, "-Wformat-nonliteral"))
-    warn_format_nonliteral = 1;
-  else if (!strcmp (p, "-Wno-format-nonliteral"))
-    warn_format_nonliteral = 0;
-  else if (!strcmp (p, "-Wformat-security"))
-    warn_format_security = 1;
-  else if (!strcmp (p, "-Wno-format-security"))
-    warn_format_security = 0;
-  else if (!strcmp (p, "-Wchar-subscripts"))
-    warn_char_subscripts = 1;
-  else if (!strcmp (p, "-Wno-char-subscripts"))
-    warn_char_subscripts = 0;
-  else if (!strcmp (p, "-Wconversion"))
-    warn_conversion = 1;
-  else if (!strcmp (p, "-Wno-conversion"))
-    warn_conversion = 0;
-  else if (!strcmp (p, "-Wparentheses"))
-    warn_parentheses = 1;
-  else if (!strcmp (p, "-Wno-parentheses"))
-    warn_parentheses = 0;
-  else if (!strcmp (p, "-Wreturn-type"))
-    warn_return_type = 1;
-  else if (!strcmp (p, "-Wno-return-type"))
-    warn_return_type = 0;
-  else if (!strcmp (p, "-Wsequence-point"))
-    warn_sequence_point = 1;
-  else if (!strcmp (p, "-Wno-sequence-point"))
-    warn_sequence_point = 0;
-  else if (!strcmp (p, "-Wcomment"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-comment"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wcomments"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-comments"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wtrigraphs"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-trigraphs"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wundef"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-undef"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wimport"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-import"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wmissing-braces"))
-    warn_missing_braces = 1;
-  else if (!strcmp (p, "-Wno-missing-braces"))
-    warn_missing_braces = 0;
-  else if (!strcmp (p, "-Wmain"))
-    warn_main = 1;
-  else if (!strcmp (p, "-Wno-main"))
-    warn_main = -1;
-  else if (!strcmp (p, "-Wsign-compare"))
-    warn_sign_compare = 1;
-  else if (!strcmp (p, "-Wno-sign-compare"))
-    warn_sign_compare = 0;
-  else if (!strcmp (p, "-Wfloat-equal"))
-    warn_float_equal = 1;
-  else if (!strcmp (p, "-Wno-float-equal"))
-    warn_float_equal = 0;
-  else if (!strcmp (p, "-Wmultichar"))
-    warn_multichar = 1;
-  else if (!strcmp (p, "-Wno-multichar"))
-    warn_multichar = 0;
-  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
-    return strings_processed;
-
-  return 1;
-}
-
-/* Hooks for print_node.  */
-
-void
-print_lang_decl (file, node, indent)
-     FILE *file ATTRIBUTE_UNUSED;
-     tree node ATTRIBUTE_UNUSED;
-     int indent ATTRIBUTE_UNUSED;
-{
-}
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+   
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
 
-void
-print_lang_type (file, node, indent)
-     FILE *file ATTRIBUTE_UNUSED;
-     tree node ATTRIBUTE_UNUSED;
-     int indent ATTRIBUTE_UNUSED;
-{
-}
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
 void
-print_lang_identifier (file, node, indent)
+c_print_identifier (file, node, indent)
      FILE *file;
      tree node;
      int indent;
@@ -828,7 +322,7 @@ print_lang_identifier (file, node, indent)
    for a top-level tentative array defn that wasn't complete before.  */
 
 void
-finish_incomplete_decl (decl)
+c_finish_incomplete_decl (decl)
      tree decl;
 {
   if (TREE_CODE (decl) == VAR_DECL)
@@ -848,13 +342,33 @@ 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.  */
@@ -922,17 +436,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.  */
@@ -1153,13 +657,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)
@@ -1206,30 +704,6 @@ poplevel (keep, reverse, functionbody)
   return block;
 }
 
-/* Delete the node BLOCK from the current binding level.
-   This is used for the block inside a stmt expr ({...})
-   so that the block can be reinserted where appropriate.  */
-
-void
-delete_block (block)
-     tree block;
-{
-  tree t;
-  if (current_binding_level->blocks == block)
-    current_binding_level->blocks = TREE_CHAIN (block);
-  for (t = current_binding_level->blocks; t;)
-    {
-      if (TREE_CHAIN (t) == block)
-       TREE_CHAIN (t) = TREE_CHAIN (block);
-      else
-       t = TREE_CHAIN (t);
-    }
-  TREE_CHAIN (block) = NULL;
-  /* Clear TREE_USED which is always set by poplevel.
-     The flag is set again if insert_block is called.  */
-  TREE_USED (block) = 0;
-}
-
 /* Insert BLOCK at the end of the list of subblocks of the
    current binding level.  This is used when a BIND_EXPR is expanded,
    to handle the BLOCK node inside the BIND_EXPR.  */
@@ -1262,17 +736,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.  */
 
@@ -1334,9 +798,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".
@@ -1405,8 +867,43 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   int errmsg = 0;
 
   if (DECL_P (olddecl))
-    DECL_ATTRIBUTES (newdecl)
-      = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+    {
+      if (TREE_CODE (newdecl) == FUNCTION_DECL
+         && TREE_CODE (olddecl) == FUNCTION_DECL
+         && (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
+       {
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && DECL_UNINLINABLE (newdecl)
+             && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+           /* Already warned elsewhere.  */;
+         else if (DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (olddecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+           /* Already warned.  */;
+         else if (DECL_DECLARED_INLINE_P (newdecl)
+                  && ! DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (olddecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+           {
+             warning_with_decl (newdecl,
+                                "function `%s' redeclared as inline");
+             warning_with_decl (olddecl,
+                                "previous declaration of function `%s' with attribute noinline");
+           }
+         else if (DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (newdecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+           {
+             warning_with_decl (newdecl,
+                                "function `%s' redeclared with attribute noinline");
+             warning_with_decl (olddecl,
+                                "previous declaration of function `%s' was inline");
+           }
+       }
+
+      DECL_ATTRIBUTES (newdecl)
+       = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+    }
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1466,14 +963,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
      match enough.  Ultimately, copy most of the information from the new
      decl to the old one, and keep using the old one.  */
 
-  if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
-      && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
-      && DECL_INITIAL (olddecl) == 0)
-    /* If -traditional, avoid error for redeclaring fcn
-       after implicit decl.  */
-    ;
-  else if (TREE_CODE (olddecl) == FUNCTION_DECL
-          && DECL_BUILT_IN (olddecl))
+  if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
     {
       /* A function declaration for a built-in function.  */
       if (!TREE_PUBLIC (newdecl))
@@ -1532,6 +1022,22 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          if (! different_binding_level)
            TREE_TYPE (olddecl) = oldtype;
        }
+      else if (TYPE_ARG_TYPES (oldtype) == NULL
+              && TYPE_ARG_TYPES (newtype) != NULL)
+       {
+         /* For bcmp, bzero, fputs the builtin type has arguments not
+            specified.  Use the ones from the prototype so that type checking
+            is done for them.  */
+         tree trytype
+           = build_function_type (TREE_TYPE (oldtype),
+                                  TYPE_ARG_TYPES (newtype));
+         trytype = build_type_attribute_variant (trytype,
+                                                 TYPE_ATTRIBUTES (oldtype));
+
+         oldtype = trytype;
+         if (! different_binding_level)
+           TREE_TYPE (olddecl) = oldtype;
+       }
       if (!types_match)
        {
          /* If types don't match for a built-in, throw away the built-in.  */
@@ -1620,19 +1126,33 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              if (TREE_CHAIN (t) == 0
                  && TYPE_MAIN_VARIANT (type) != void_type_node)
                {
-                 error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
+                 error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
                  break;
                }
 
-             if (simple_type_promotes_to (type) != NULL_TREE)
+             if (c_type_promotes_to (type) != type)
                {
-                 error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
+                 error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
                  break;
                }
            }
        }
       error_with_decl (olddecl, "previous declaration of `%s'");
     }
+  /* 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
     {
       errmsg = redeclaration_error_message (newdecl, olddecl);
@@ -1658,6 +1178,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                             && current_binding_level == global_binding_level)
                            ? "`%s' previously defined here"
                            : "`%s' previously declared here"));
+         return 0;
        }
       else if (TREE_CODE (newdecl) == TYPE_DECL
                && (DECL_IN_SYSTEM_HEADER (olddecl)
@@ -1705,12 +1226,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                }
              /* Type for passing arg must be consistent
                 with that declared for the arg.  */
-             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
-                 /* If -traditional, allow `unsigned int' instead of `int'
-                    in the prototype.  */
-                 && (! (flag_traditional
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
+             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
                {
                  error_with_decl (newdecl,
                                   "prototype for `%s' follows and argument %d doesn't match",
@@ -1845,11 +1361,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;
 
@@ -1905,13 +1416,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        {
          DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
          DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
-
+         DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
-         DECL_NO_CHECK_MEMORY_USAGE (newdecl)
-           |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
-         DECL_NO_LIMIT_STACK (newdecl)
-           |= DECL_NO_LIMIT_STACK (olddecl);
        }
     }
   /* If cannot merge, then use the new type and qualifiers,
@@ -1925,7 +1432,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     }
 
   /* Merge the storage class information.  */
-  DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+  merge_weak (newdecl, olddecl);
+
   /* For functions, static overrides non-static.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -1979,10 +1487,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          /* If either decl says `inline', this fn is inline,
             unless its definition was passed already.  */
          if (DECL_DECLARED_INLINE_P (newdecl)
-             && DECL_DECLARED_INLINE_P (olddecl) == 0)
-           DECL_DECLARED_INLINE_P (olddecl) = 1;
+             || DECL_DECLARED_INLINE_P (olddecl))
+           DECL_DECLARED_INLINE_P (newdecl) = 1;
 
-         DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
+         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
        }
 
       if (DECL_BUILT_IN (olddecl))
@@ -2005,9 +1514,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
            }
        }
+
       /* Also preserve various other info from the definition.  */
-      else if (! new_is_definition)
-       DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
       if (! new_is_definition)
        {
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2017,9 +1525,28 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          if (! different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
+         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+         DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-         if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
+
+         /* Set DECL_INLINE on the declaration if we've got a body
+            from which to instantiate.  */
+         if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+           {
+             DECL_INLINE (newdecl) = 1;
+             DECL_ABSTRACT_ORIGIN (newdecl)
+               = (different_binding_level
+                  ? DECL_ORIGIN (olddecl)
+                  : DECL_ABSTRACT_ORIGIN (olddecl));
+           }
+       }
+      else
+       {
+         /* If a previous declaration said inline, mark the
+            definition as inlinable.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && ! DECL_UNINLINABLE (newdecl))
+           DECL_INLINE (newdecl) = 1;
        }
     }
   if (different_binding_level)
@@ -2043,6 +1570,66 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   return 1;
 }
 
+/* Check whether decl-node X shadows an existing declaration.
+   OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X,
+   which might be a NULL_TREE.  */
+static void
+warn_if_shadowing (x, oldlocal)
+     tree x, oldlocal;
+{
+  tree name;
+
+  if (DECL_EXTERNAL (x))
+    return;
+
+  name = DECL_NAME (x);
+
+  /* Warn if shadowing an argument at the top level of the body.  */
+  if (oldlocal != 0
+      /* This warning doesn't apply to the parms of a nested fcn.  */
+      && ! current_binding_level->parm_flag
+      /* Check that this is one level down from the parms.  */
+      && current_binding_level->level_chain->parm_flag
+      /* Check that the decl being shadowed
+        comes from the parm level, one level up.  */
+      && chain_member (oldlocal, current_binding_level->level_chain->names))
+    {
+      if (TREE_CODE (oldlocal) == PARM_DECL)
+       pedwarn ("declaration of `%s' shadows a parameter",
+                IDENTIFIER_POINTER (name));
+      else
+       pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+                IDENTIFIER_POINTER (name));
+    }
+  /* Maybe warn if shadowing something else.  */
+  else if (warn_shadow
+          /* No shadow warnings for internally generated vars.  */
+          && DECL_SOURCE_LINE (x) != 0
+          /* No shadow warnings for vars made for inlining.  */
+          && ! DECL_FROM_INLINE (x))
+    {
+      if (TREE_CODE (x) == PARM_DECL
+         && current_binding_level->level_chain->parm_flag)
+       /* Don't warn about the parm names in function declarator
+          within a function declarator.
+          It would be nice to avoid warning in any function
+          declarator in a declaration, as opposed to a definition,
+          but there is no way to tell it's not a definition.  */
+       ;
+      else if (oldlocal)
+       {
+         if (TREE_CODE (oldlocal) == PARM_DECL)
+           shadow_warning ("a parameter", name, oldlocal);
+         else
+           shadow_warning ("a previous local", name, oldlocal);
+       }
+      else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
+              && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
+       shadow_warning ("a global declaration", name,
+                       IDENTIFIER_GLOBAL_VALUE (name));
+    }
+}
+
 /* Record a decl-node X as belonging to the current lexical scope.
    Check for errors (such as an incompatible declaration for the same
    name already seen in the same scope).
@@ -2072,29 +1659,29 @@ pushdecl (x)
       && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
     DECL_CONTEXT (x) = 0;
 
-  if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
-      && x != IDENTIFIER_IMPLICIT_DECL (name)
-      /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */
-      && !DECL_IN_SYSTEM_HEADER (x))
-    warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name));
-
   if (name)
     {
-      const char *file;
-      int line;
       int different_binding_level = 0;
 
+      if (warn_nested_externs
+         && DECL_EXTERNAL (x)
+         && b != global_binding_level
+         && x != IDENTIFIER_IMPLICIT_DECL (name)
+         /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+         && !DECL_IN_SYSTEM_HEADER (x))
+       warning ("nested extern declaration of `%s'",
+                IDENTIFIER_POINTER (name));
+
       t = lookup_name_current_level (name);
-      /* Don't type check externs here when -traditional.  This is so that
-        code with conflicting declarations inside blocks will get warnings
-        not errors.  X11 for instance depends on this.  */
-      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
+      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
        {
          t = IDENTIFIER_GLOBAL_VALUE (name);
          /* Type decls at global scope don't conflict with externs declared
             inside lexical blocks.  */
-         if (t && TREE_CODE (t) == TYPE_DECL)
-           t = 0;
+         if (! t || TREE_CODE (t) == TYPE_DECL)
+           /* If there's no visible global declaration, try for an
+               invisible one.  */
+           t = IDENTIFIER_LIMBO_VALUE (name);
          different_binding_level = 1;
        }
       if (t != 0 && t == error_mark_node)
@@ -2104,16 +1691,9 @@ pushdecl (x)
          error_with_decl (x, "`%s' used prior to declaration");
        }
 
-      if (t != 0)
-       {
-         file = DECL_SOURCE_FILE (t);
-         line = DECL_SOURCE_LINE (t);
-       }
-
       /* If this decl is `static' and an implicit decl was seen previously,
-        warn.  But don't complain if -traditional,
-        since traditional compilers don't complain.  */
-      if (! flag_traditional && TREE_PUBLIC (name)
+        warn.  */
+      if (TREE_PUBLIC (name)
          /* Don't test for DECL_EXTERNAL, because grokdeclarator
             sets this for all functions.  */
          && ! TREE_PUBLIC (x)
@@ -2207,9 +1787,6 @@ pushdecl (x)
        }
 
       /* Multiple external decls of the same identifier ought to match.
-        Check against both global declarations (when traditional) and out of
-        scope (limbo) block level declarations.
-
         We get warnings about inline functions where they are defined.
         Avoid duplicate warnings where they are used.  */
       if (TREE_PUBLIC (x)
@@ -2217,11 +1794,7 @@ pushdecl (x)
        {
          tree decl;
 
-         if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0
-             && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
-                 || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
-           decl = IDENTIFIER_GLOBAL_VALUE (name);
-         else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
+         if (IDENTIFIER_LIMBO_VALUE (name) != 0)
            /* Decls in limbo are always extern, so no need to check that.  */
            decl = IDENTIFIER_LIMBO_VALUE (name);
          else
@@ -2251,39 +1824,6 @@ pushdecl (x)
                             "previous implicit declaration of `%s'");
        }
 
-      /* In PCC-compatibility mode, extern decls of vars with no current decl
-        take effect at top level no matter where they are.  */
-      if (flag_traditional && DECL_EXTERNAL (x)
-         && lookup_name (name) == 0)
-       {
-         tree type = TREE_TYPE (x);
-
-         /* But don't do this if the type contains temporary nodes.  */
-         while (type)
-           {
-             if (type == error_mark_node)
-               break;
-             if (TYPE_CONTEXT (type))
-               {
-                 warning_with_decl (x, "type of external `%s' is not global");
-                 /* By exiting the loop early, we leave TYPE nonzero,
-                    and thus prevent globalization of the decl.  */
-                 break;
-               }
-             else if (TREE_CODE (type) == FUNCTION_TYPE
-                      && TYPE_ARG_TYPES (type) != 0)
-               /* The types might not be truly local,
-                  but the list of arg types certainly is temporary.
-                  Since prototypes are nontraditional,
-                  ok not to do the traditional thing.  */
-               break;
-             type = TREE_TYPE (type);
-           }
-
-         if (type == 0)
-           b = global_binding_level;
-       }
-
       /* This name is new in its binding level.
         Install the new declaration and return it.  */
       if (b == global_binding_level)
@@ -2432,49 +1972,7 @@ pushdecl (x)
                IDENTIFIER_LIMBO_VALUE (name) = x;
            }
 
-         /* Warn if shadowing an argument at the top level of the body.  */
-         if (oldlocal != 0 && !DECL_EXTERNAL (x)
-             /* This warning doesn't apply to the parms of a nested fcn.  */
-             && ! current_binding_level->parm_flag
-             /* Check that this is one level down from the parms.  */
-             && current_binding_level->level_chain->parm_flag
-             /* Check that the decl being shadowed
-                comes from the parm level, one level up.  */
-             && chain_member (oldlocal, current_binding_level->level_chain->names))
-           {
-             if (TREE_CODE (oldlocal) == PARM_DECL)
-               pedwarn ("declaration of `%s' shadows a parameter",
-                        IDENTIFIER_POINTER (name));
-             else
-               pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
-                        IDENTIFIER_POINTER (name));
-           }
-
-         /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-                  /* No shadow warnings for internally generated vars.  */
-                  && DECL_SOURCE_LINE (x) != 0
-                  /* No shadow warnings for vars made for inlining.  */
-                  && ! DECL_FROM_INLINE (x))
-           {
-             const char *id = IDENTIFIER_POINTER (name);
-
-             if (TREE_CODE (x) == PARM_DECL
-                 && current_binding_level->level_chain->parm_flag)
-               /* Don't warn about the parm names in function declarator
-                  within a function declarator.
-                  It would be nice to avoid warning in any function
-                  declarator in a declaration, as opposed to a definition,
-                  but there is no way to tell it's not a definition.  */
-               ;
-             else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
-               warning ("declaration of `%s' shadows a parameter", id);
-             else if (oldlocal != 0)
-               warning ("declaration of `%s' shadows previous local", id);
-             else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-                      && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warning ("declaration of `%s' shadows global declaration", id);
-           }
+         warn_if_shadowing (x, oldlocal);
 
          /* If storing a local value, there may already be one (inherited).
             If so, record it for restoration when this binding level ends.  */
@@ -2482,13 +1980,21 @@ 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.  */
       if (TREE_TYPE (x) != error_mark_node
          && !COMPLETE_TYPE_P (TREE_TYPE (x)))
-       ++b->n_incomplete;
+       {
+         tree element = TREE_TYPE (x);
+
+         while (TREE_CODE (element) == ARRAY_TYPE)
+           element = TREE_TYPE (element);
+         if (TREE_CODE (element) == RECORD_TYPE
+             || TREE_CODE (element) == UNION_TYPE)
+           b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
+       }
     }
 
   /* Put decls on list in reverse order.
@@ -2551,12 +2057,12 @@ implicitly_declare (functionid)
   IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
 
   /* ANSI standard says implicit declarations are in the innermost block.
-     So we record the decl in the standard fashion.
-     If flag_traditional is set, pushdecl does it top-level.  */
+     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);
 
@@ -2600,17 +2106,8 @@ redeclaration_error_message (newdecl, olddecl)
 {
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
-      if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl))
-       return 0;
-      /* pushdecl creates distinct types for TYPE_DECLs by calling
-        build_type_copy, so the above comparison generally fails.  We do
-        another test against the TYPE_MAIN_VARIANT of the olddecl, which
-        is equivalent to what this code used to do before the build_type_copy
-        call.  The variant type distinction should not matter for traditional
-        code, because it doesn't have type qualifiers.  */
-      if (flag_traditional
-         && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
-       return 0;
+      /* Do not complain about type redeclarations where at least one
+        declaration was in a system header.  */
       if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
        return 0;
       return 1;
@@ -2956,36 +2453,20 @@ 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.
    Make definitions for built-in primitive functions.  */
 
 void
-init_decl_processing ()
+c_init_decl_processing ()
 {
   tree endlink;
   tree ptr_ftype_void, ptr_ftype_ptr;
 
+  /* Adds some ggc roots, and reserved words for c-parse.in.  */
+  c_parse_init ();
+
   current_function_decl = NULL;
   named_labels = NULL;
   current_binding_level = NULL_BINDING_LEVEL;
@@ -3003,8 +2484,7 @@ init_decl_processing ()
   boolean_true_node = integer_one_node;
   boolean_false_node = integer_zero_node;
 
-  /* With GCC, C99's _Bool is always of size 1.  */
-  c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+  c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
   TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
   TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
@@ -3022,75 +2502,10 @@ init_decl_processing ()
     = build_function_type (ptr_type_node,
                           tree_cons (NULL_TREE, ptr_type_node, endlink));
 
-  /* Types which are common to the fortran compiler and libf2c.  When
-     changing these, you also need to be concerned with f/com.h.  */
-
-  if (TYPE_PRECISION (float_type_node)
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_integer_type_node = long_integer_type_node;
-      g77_uinteger_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node)
-          == TYPE_PRECISION (integer_type_node))
-    {
-      g77_integer_type_node = integer_type_node;
-      g77_uinteger_type_node = unsigned_type_node;
-    }
-  else
-    g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
-  if (g77_integer_type_node != NULL_TREE)
-    {
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
-                           g77_integer_type_node));
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
-                           g77_uinteger_type_node));
-    }
-
-  if (TYPE_PRECISION (float_type_node) * 2
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_longint_type_node = long_integer_type_node;
-      g77_ulongint_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node) * 2
-          == TYPE_PRECISION (long_long_integer_type_node))
-    {
-      g77_longint_type_node = long_long_integer_type_node;
-      g77_ulongint_type_node = long_long_unsigned_type_node;
-    }
-  else
-    g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
-  if (g77_longint_type_node != NULL_TREE)
-    {
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
-                           g77_longint_type_node));
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
-                           g77_ulongint_type_node));
-    }
-
   pedantic_lvalues = pedantic;
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
-
-  incomplete_decl_finalize_hook = finish_incomplete_decl;
-
-  /* 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
@@ -3139,24 +2554,21 @@ 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;
   TREE_PUBLIC (decl) = 1;
-  /* If -traditional, permit redefining a builtin function any way you like.
-     (Though really, if the program redefines these functions,
-     it probably won't work right unless compiled with -fno-builtin.)  */
-  if (flag_traditional && name[0] != '_')
-    DECL_BUILT_IN_NONANSI (decl) = 1;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
   make_decl_rtl (decl, NULL);
@@ -3170,7 +2582,10 @@ builtin_function (name, type, function_code, class, library_name)
     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;
 }
@@ -3179,7 +2594,7 @@ builtin_function (name, type, function_code, class, library_name)
    attributes.  */
 
 void
-insert_default_attributes (decl)
+c_insert_default_attributes (decl)
      tree decl;
 {
   if (!TREE_PUBLIC (decl))
@@ -3276,8 +2691,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
@@ -3299,9 +2714,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");
@@ -3310,7 +2725,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.  */
@@ -3333,11 +2748,19 @@ tree
 groktypename (typename)
      tree typename;
 {
+  tree specs, attrs;
+
   if (TREE_CODE (typename) != TREE_LIST)
     return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
-                        TYPENAME, 0);
+
+  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+
+  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
+
+  /* Apply attributes.  */
+  decl_attributes (&typename, attrs, 0);
+
+  return typename;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
@@ -3374,9 +2797,18 @@ start_decl (declarator, declspecs, initialized, attributes)
      int initialized;
      tree attributes;
 {
-  tree decl = grokdeclarator (declarator, declspecs,
-                             NORMAL, initialized);
+  tree decl;
   tree tem;
+  
+  /* An object declared as __attribute__((deprecated)) suppresses
+     warnings of uses of other deprecated items.  */
+  if (lookup_attribute ("deprecated", attributes))
+    deprecated_state = DEPRECATED_SUPPRESS;
+
+  decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized);
+  
+  deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
@@ -3389,15 +2821,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:
@@ -3475,14 +2901,35 @@ start_decl (declarator, declspecs, initialized, attributes)
   /* ANSI specifies that a tentative definition which is not merged with
      a non-tentative definition behaves exactly like a definition with an
      initializer equal to zero.  (Section 3.7.2)
-     -fno-common gives strict ANSI behavior.  Usually you don't want it.
-     This matters only for variables with external linkage.  */
-  if (! flag_no_common || ! TREE_PUBLIC (decl))
+
+     -fno-common gives strict ANSI behavior, though this tends to break
+     a large body of code that grew up without this rule.
+
+     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.  */
+
+  if (TREE_CODE (decl) == VAR_DECL
+      && !initialized
+      && TREE_PUBLIC (decl)
+      && !DECL_THREAD_LOCAL (decl)
+      && !flag_no_common)
     DECL_COMMON (decl) = 1;
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (&decl, attributes, 0);
 
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_binding_level == global_binding_level)
+    maybe_apply_pragma_weak (decl);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && DECL_UNINLINABLE (decl)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
+    warning_with_decl (decl,
+                      "inline function `%s' given attribute noinline");
+
   /* Add this decl to the current binding level.
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
@@ -3521,6 +2968,8 @@ finish_decl (decl, init, asmspec_tree)
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
+  if (current_binding_level == global_binding_level)
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
@@ -3533,16 +2982,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
@@ -3644,8 +3084,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))
        {
@@ -3685,7 +3126,8 @@ finish_decl (decl, init, asmspec_tree)
                SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
            }
 
-         add_decl_stmt (decl);
+         if (TREE_CODE (decl) != FUNCTION_DECL)
+           add_decl_stmt (decl);
        }
 
       if (DECL_CONTEXT (decl) != 0)
@@ -3706,8 +3148,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);
     }
 
@@ -3718,17 +3161,6 @@ finish_decl (decl, init, asmspec_tree)
     get_pending_sizes ();
 }
 
-/* If DECL has a cleanup, build and return that cleanup here.
-   This is a callback called by expand_expr.  */
-
-tree
-maybe_build_cleanup (decl)
-     tree decl ATTRIBUTE_UNUSED;
-{
-  /* There are no cleanups in C.  */
-  return NULL_TREE;
-}
-
 /* Given a parsed parameter declaration,
    decode it into a PARM_DECL and push that on the current binding level.
    Also, for the sake of forward parm decls,
@@ -3754,7 +3186,7 @@ push_parm_decl (parm)
       olddecl = lookup_name (DECL_NAME (decl));
       if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
        pedwarn_with_decl (decl,
-                          "ANSI C forbids parameter `%s' shadowing typedef");
+                          "ISO C forbids parameter `%s' shadowing typedef");
     }
 #endif
 
@@ -3779,6 +3211,68 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+/* 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
+   literal.  */
+
+tree
+build_compound_literal (type, init)
+     tree type;
+     tree init;
+{
+  /* We do not use start_decl here because we have a type, not a declarator;
+     and do not use finish_decl because the decl should be stored inside
+     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT.  */
+  tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+  tree complit;
+  tree stmt;
+  DECL_EXTERNAL (decl) = 0;
+  TREE_PUBLIC (decl) = 0;
+  TREE_STATIC (decl) = (current_binding_level == global_binding_level);
+  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))
+    {
+      int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
+      if (failure)
+       abort ();
+    }
+
+  type = TREE_TYPE (decl);
+  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+    return error_mark_node;
+
+  stmt = build_stmt (DECL_STMT, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+  TREE_SIDE_EFFECTS (complit) = 1;
+
+  layout_decl (decl, 0);
+
+  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.  */
+      char *name;
+      extern int var_labelno;
+
+      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", var_labelno);
+      var_labelno++;
+      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);
+    }
+
+  return complit;
+}
+\f
 /* Make TYPE a complete type based on INITIAL_VALUE.
    Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
    2 if there was no information (in which case assume 1 if DO_DEFAULT).  */
@@ -3849,6 +3343,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.
@@ -3982,6 +3510,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       tree id = TREE_VALUE (spec);
 
+      /* If the entire declaration is itself tagged as deprecated then
+         suppress reports of deprecated items.  */
+      if (id && TREE_DEPRECATED (id))
+        {
+         if (deprecated_state != DEPRECATED_SUPPRESS)
+           warn_deprecated_use (id);
+        }
+
       if (id == ridpointers[(int) RID_INT])
        explicit_int = 1;
       if (id == ridpointers[(int) RID_CHAR])
@@ -3992,7 +3528,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          enum rid i = C_RID_CODE (id);
          if ((int) i <= (int) RID_LAST_MODIFIER)
            {
-             if (i == RID_LONG && (specbits & (1 << (int) i)))
+             if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
                {
                  if (longlong)
                    error ("`long long long' is too long for GCC");
@@ -4000,12 +3536,33 @@ 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.  */
+             if (i == RID_THREAD
+                 && (specbits & (1 << (int) RID_EXTERN
+                                 | 1 << (int) RID_STATIC)))
+               {
+                 if (specbits & 1 << (int) RID_EXTERN)
+                   error ("`__thread' before `extern'");
+                 else
+                   error ("`__thread' before `static'");
+               }
+
              specbits |= 1 << (int) i;
              goto found;
            }
@@ -4015,9 +3572,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Actual typedefs come to us as TYPE_DECL nodes.  */
       else if (TREE_CODE (id) == TYPE_DECL)
        {
-         type = TREE_TYPE (id);
-         decl_attr = DECL_ATTRIBUTES (id);
-         typedef_decl = id;
+         if (TREE_TYPE (id) == error_mark_node)
+           ; /* Allow the type to default to int to avoid cascading errors.  */
+         else
+           {
+             type = TREE_TYPE (id);
+             decl_attr = DECL_ATTRIBUTES (id);
+             typedef_decl = id;
+           }
        }
       /* Built-in types come as identifiers.  */
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -4120,12 +3682,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;
            }
        }
 
@@ -4148,9 +3709,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
   if (specbits & 1 << (int) RID_UNSIGNED
-      /* Traditionally, all bitfields are unsigned.  */
-      || (bitfield && flag_traditional
-         && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
       || (bitfield && ! flag_signed_bitfields
          && (explicit_int || defaulted_int || explicit_char
              /* A typedef for plain `int' without `signed'
@@ -4169,7 +3727,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (type == char_type_node)
        type = unsigned_char_type_node;
       else if (typedef_decl)
-       type = unsigned_type (type);
+       type = c_common_unsigned_type (type);
       else
        type = unsigned_type_node;
     }
@@ -4186,7 +3744,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
@@ -4253,6 +3811,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (specbits & 1 << (int) RID_REGISTER) nclasses++;
     if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
 
+    /* "static __thread" and "extern __thread" are allowed.  */
+    if ((specbits & (1 << (int) RID_THREAD
+                    | 1 << (int) RID_STATIC
+                    | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
+      nclasses++;
+
     /* Warn about storage classes that are invalid for certain
        kinds of declarations (parameters, typenames, etc.).  */
 
@@ -4262,7 +3826,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             && (specbits
                 & ((1 << (int) RID_REGISTER)
                    | (1 << (int) RID_AUTO)
-                   | (1 << (int) RID_TYPEDEF))))
+                   | (1 << (int) RID_TYPEDEF)
+                   | (1 << (int) RID_THREAD))))
       {
        if (specbits & 1 << (int) RID_AUTO
            && (pedantic || current_binding_level == global_binding_level))
@@ -4271,8 +3836,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          error ("function definition declared `register'");
        if (specbits & 1 << (int) RID_TYPEDEF)
          error ("function definition declared `typedef'");
+       if (specbits & 1 << (int) RID_THREAD)
+         error ("function definition declared `__thread'");
        specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                     | (1 << (int) RID_AUTO));
+                     | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
       }
     else if (decl_context != NORMAL && nclasses > 0)
       {
@@ -4295,7 +3862,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              }
            specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
                          | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
-                         | (1 << (int) RID_EXTERN));
+                         | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
          }
       }
     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
@@ -4306,12 +3873,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else
          error ("`%s' has both `extern' and initializer", name);
       }
-    else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
-            && current_binding_level != global_binding_level)
-      error ("nested function `%s' declared `extern'", name);
-    else if (current_binding_level == global_binding_level
-            && specbits & (1 << (int) RID_AUTO))
-      error ("top-level declaration of `%s' specifies `auto'", name);
+    else if (current_binding_level == global_binding_level)
+      {
+       if (specbits & 1 << (int) RID_AUTO)
+         error ("top-level declaration of `%s' specifies `auto'", name);
+      }
+    else
+      {
+       if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
+         error ("nested function `%s' declared `extern'", name);
+       else if ((specbits & (1 << (int) RID_THREAD
+                              | 1 << (int) RID_EXTERN
+                              | 1 << (int) RID_STATIC))
+                == (1 << (int) RID_THREAD))
+         {
+           error ("function-scope `%s' implicitly auto and declared `__thread'",
+                  name);
+           specbits &= ~(1 << (int) RID_THREAD);
+         }
+      }
   }
 
   /* Now figure out the structure of the declarator proper.
@@ -4366,9 +3946,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          if (inner_decl == NULL_TREE
              || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
            attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-         if (TREE_CODE (inner_decl) == CALL_EXPR)
+         else if (TREE_CODE (inner_decl) == CALL_EXPR)
            attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-         if (TREE_CODE (inner_decl) == ARRAY_REF)
+         else if (TREE_CODE (inner_decl) == ARRAY_REF)
            attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
          returned_attrs = decl_attributes (&type,
                                            chainon (returned_attrs, attrs),
@@ -4379,7 +3959,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          tree itype = NULL_TREE;
          tree size = TREE_OPERAND (declarator, 1);
          /* The index is a signed object `sizetype' bits wide.  */
-         tree index_type = signed_type (sizetype);
+         tree index_type = c_common_signed_type (sizetype);
 
          array_ptr_quals = TREE_TYPE (declarator);
          array_parm_static = TREE_STATIC (declarator);
@@ -4400,6 +3980,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;
 
@@ -4439,13 +4022,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                     even if it is (eg) a const variable with known value.  */
                  size_varies = 1;
 
-                 if (pedantic)
+                 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);
                    }
                }
@@ -4487,12 +4070,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            }
          else if (decl_context == FIELD)
            {
-             /* ??? Need to check somewhere that this is a structure
-                and not a union, that this field is last, and that
-                this structure has at least one other named member.  */
-
              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.  */
@@ -4509,7 +4088,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             Functions aren't allowed as array elements.  */
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
              && (constp || volatilep))
-           pedwarn ("ANSI C forbids const or volatile function types");
+           pedwarn ("ISO C forbids const or volatile function types");
 #endif
 
          /* Build the array type itself, then merge any constancy or
@@ -4564,13 +4143,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = integer_type_node;
            }
 
-#ifndef TRADITIONAL_RETURN_FLOAT
-         /* Traditionally, declaring return type float means double.  */
-
-         if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
-           type = double_type_node;
-#endif /* TRADITIONAL_RETURN_FLOAT */
-
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
@@ -4697,7 +4269,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     {
       error ("size of array `%s' is too large", name);
-      /* If we proceed with the array type as it is, we'll eventully
+      /* If we proceed with the array type as it is, we'll eventually
         crash in tree_low_cst().  */
       type = error_mark_node;
     }
@@ -4858,11 +4430,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        if (type == error_mark_node)
          promoted_type = type;
        else
-         {
-           promoted_type = simple_type_promotes_to (type);
-           if (! promoted_type)
-             promoted_type = type;
-         }
+         promoted_type = c_type_promotes_to (type);
 
        DECL_ARG_TYPE (decl) = promoted_type;
        DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
@@ -4914,6 +4482,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn ("invalid storage class for function `%s'", name);
        if (specbits & (1 << (int) RID_REGISTER))
          error ("invalid storage class for function `%s'", name);
+       if (specbits & (1 << (int) RID_THREAD))
+         error ("invalid storage class for function `%s'", name);
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
@@ -4943,6 +4513,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        TREE_PUBLIC (decl)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
 
+       if (defaulted_int)
+         C_FUNCTION_IMPLICIT_INT (decl) = 1;
+
        /* Record presence of `inline', if it is reasonable.  */
        if (MAIN_NAME_P (declarator))
          {
@@ -4952,16 +4525,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else if (inlinep)
          {
            /* Assume that otherwise the function can be inlined.  */
-           DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 1;
 
-           if (specbits & (1 << (int) RID_EXTERN))
-             current_extern_inline = 1;
+           /* Do not mark bare declarations as DECL_INLINE.  Doing so
+              in the presence of multiple declarations can result in
+              the abstract origin pointing between the declarations,
+              which will confuse dwarf2out.  */
+           if (initialized)
+             {
+               DECL_INLINE (decl) = 1;
+               if (specbits & (1 << (int) RID_EXTERN))
+                 current_extern_inline = 1;
+             }
          }
        /* If -finline-functions, assume it can be inlined.  This does
           two things: let the function be deferred until it is actually
           needed, and let dwarf2 know that the function is inlinable.  */
-       else if (flag_inline_trees == 2)
+       else if (flag_inline_trees == 2 && initialized)
          {
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
@@ -4996,22 +4576,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn_with_decl (decl, "variable `%s' declared `inline'");
 
        DECL_EXTERNAL (decl) = extern_ref;
+
        /* At top level, the presence of a `static' or `register' storage
           class specifier, or the absence of all storage class specifiers
           makes this declaration a definition (perhaps tentative).  Also,
           the absence of both `static' and `register' makes it public.  */
        if (current_binding_level == global_binding_level)
          {
-           TREE_PUBLIC (decl)
-             = !(specbits
-                 & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
-           TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
+           TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
+                                              | (1 << (int) RID_REGISTER)));
+           TREE_STATIC (decl) = !extern_ref;
          }
        /* Not at top level, only `static' makes a static definition.  */
        else
          {
            TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
-           TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
+           TREE_PUBLIC (decl) = extern_ref;
+         }
+
+       if (specbits & 1 << (int) RID_THREAD)
+         {
+           if (targetm.have_tls)
+             DECL_THREAD_LOCAL (decl) = 1;
+           else
+             /* A mere warning is sure to result in improper semantics
+                at runtime.  Don't bother to allow this to compile.  */
+             error ("thread-local storage not supported for this target");
          }
       }
 
@@ -5028,7 +4618,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        Otherwise, the fact that those components are volatile
        will be ignored, and would even crash the compiler.  */
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
-      mark_addressable (decl);
+      c_mark_addressable (decl);
 
     decl_attributes (&decl, returned_attrs, 0);
 
@@ -5266,11 +4856,17 @@ parmlist_tags_warning ()
       if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
        continue;
       if (TREE_PURPOSE (elt) != 0)
-       warning ("`%s %s' declared inside parameter list",
-                (code == RECORD_TYPE ? "struct"
-                 : code == UNION_TYPE ? "union"
-                 : "enum"),
-                IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+        {
+          if (code == RECORD_TYPE)
+            warning ("`struct %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+          else if (code == UNION_TYPE)
+            warning ("`union %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+          else
+            warning ("`enum %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+        }
       else
        {
          /* For translation these need to be separate warnings */
@@ -5283,7 +4879,7 @@ parmlist_tags_warning ()
        }
       if (! already)
        {
-         warning ("its scope is only this definition or declaration, which is probably not what you want.");
+         warning ("its scope is only this definition or declaration, which is probably not what you want");
          already = 1;
        }
     }
@@ -5360,9 +4956,14 @@ start_struct (code, name)
       C_TYPE_BEING_DEFINED (ref) = 1;
       TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
-       error ("redefinition of `%s %s'",
-              code == UNION_TYPE ? "union" : "struct",
-              IDENTIFIER_POINTER (name));
+        {
+         if (code == UNION_TYPE)
+           error ("redefinition of `union %s'",
+                  IDENTIFIER_POINTER (name));
+          else
+           error ("redefinition of `struct %s'",
+                  IDENTIFIER_POINTER (name));
+       }  
 
       return ref;
     }
@@ -5394,12 +4995,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 consiously
+        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;
        }
     }
@@ -5409,7 +5042,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
@@ -5442,7 +5076,7 @@ finish_struct (t, fieldlist, attributes)
        if (pedantic)
          pedwarn ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
-       else if (! flag_traditional)
+       else
          warning ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
       }
@@ -5537,11 +5171,10 @@ finish_struct (t, fieldlist, attributes)
         field widths.  */
       if (DECL_INITIAL (x))
        {
-         int max_width;
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
-           max_width = CHAR_TYPE_SIZE;
-         else
-           max_width = TYPE_PRECISION (TREE_TYPE (x));
+         int max_width
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+              ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
+
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            error_with_decl (x, "negative width in bit-field `%s'");
          else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
@@ -5552,7 +5185,7 @@ finish_struct (t, fieldlist, attributes)
            {
              /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
              unsigned HOST_WIDE_INT width
-               = TREE_INT_CST_LOW (DECL_INITIAL (x));
+               = tree_low_cst (DECL_INITIAL (x), 1);
 
              if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
                  && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
@@ -5567,7 +5200,8 @@ finish_struct (t, fieldlist, attributes)
              DECL_BIT_FIELD (x) = 1;
              SET_DECL_C_BIT_FIELD (x);
 
-             if (width == 0)
+             if (width == 0
+                 && ! (* targetm.ms_bitfield_layout_p) (t))
                {
                  /* field size 0 => force desired amount of alignment.  */
 #ifdef EMPTY_FIELD_BOUNDARY
@@ -5612,6 +5246,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;
     }
@@ -5685,21 +5324,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);
-             --current_binding_level->n_incomplete;
+             /* 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)
@@ -5708,7 +5355,23 @@ finish_struct (t, fieldlist, attributes)
              while (TREE_CODE (element) == ARRAY_TYPE)
                element = TREE_TYPE (element);
              if (element == t)
-               layout_array_type (TREE_TYPE (decl));
+               {
+                 layout_array_type (TREE_TYPE (decl));
+                 if (TREE_CODE (decl) != TYPE_DECL)
+                   {
+                     layout_decl (decl, 0);
+                     if (flag_objc)
+                       objc_check_decl (decl);
+                     rest_of_decl_compilation (decl, NULL, toplevel, 0);
+                     if (! toplevel)
+                       expand_decl (decl);
+                   }
+                 /* Unlink X from the incomplete list.  */
+                 if (prev)
+                   TREE_CHAIN (prev) = TREE_CHAIN (x);
+                 else
+                   current_binding_level->incomplete_list = TREE_CHAIN (x);
+               }
            }
        }
     }
@@ -5824,7 +5487,7 @@ finish_enum (enumtype, values, attributes)
                   min_precision (maxnode, unsign));
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      tree narrowest = type_for_size (precision, unsign);
+      tree narrowest = c_common_type_for_size (precision, unsign);
       if (narrowest == 0)
        {
          warning ("enumeration values exceed range of largest integer");
@@ -5837,7 +5500,7 @@ finish_enum (enumtype, values, attributes)
     precision = TYPE_PRECISION (integer_type_node);
 
   if (precision == TYPE_PRECISION (integer_type_node))
-    enum_value_type = type_for_size (precision, 0);
+    enum_value_type = c_common_type_for_size (precision, 0);
   else
     enum_value_type = enumtype;
 
@@ -5965,11 +5628,11 @@ build_enumerator (name, value)
   /* Now create a declaration for the enum value name.  */
 
   type = TREE_TYPE (value);
-  type = type_for_size (MAX (TYPE_PRECISION (type),
-                            TYPE_PRECISION (integer_type_node)),
-                       ((flag_traditional
-                         || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
-                        && TREE_UNSIGNED (type)));
+  type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+                                     TYPE_PRECISION (integer_type_node)),
+                                (TYPE_PRECISION (type)
+                                 >= TYPE_PRECISION (integer_type_node)
+                                 && TREE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
@@ -6001,9 +5664,9 @@ start_function (declspecs, declarator, attributes)
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
+  current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
-  c_function_varargs = 0;
   named_labels = 0;
   shadowed_labels = 0;
 
@@ -6022,6 +5685,16 @@ start_function (declspecs, declarator, attributes)
 
   decl_attributes (&decl1, attributes, 0);
 
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_binding_level == global_binding_level)
+    maybe_apply_pragma_weak (decl1);
+
+  if (DECL_DECLARED_INLINE_P (decl1)
+      && DECL_UNINLINABLE (decl1)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
+    warning_with_decl (decl1,
+                      "inline function `%s' given attribute noinline");
+
   announce_function (decl1);
 
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
@@ -6190,12 +5863,10 @@ start_function (declspecs, declarator, attributes)
   /* Promote the value to int before returning it.  */
   if (c_promoting_integer_type_p (restype))
     {
-      /* It retains unsignedness if traditional
-        or if not really getting wider.  */
+      /* It retains unsignedness if not really getting wider.  */
       if (TREE_UNSIGNED (restype)
-         && (flag_traditional
-             || (TYPE_PRECISION (restype)
-                 == TYPE_PRECISION (integer_type_node))))
+         && (TYPE_PRECISION (restype)
+                 == TYPE_PRECISION (integer_type_node)))
        restype = unsigned_type_node;
       else
        restype = integer_type_node;
@@ -6214,16 +5885,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
@@ -6253,11 +5914,16 @@ store_parm_decls ()
      then CONST_DECLs for foo and bar are put here.  */
   tree nonparms = 0;
 
+  /* The function containing FNDECL, if any.  */
+  tree context = decl_function_context (fndecl);
+
   /* Nonzero if this definition is written with a prototype.  */
   int prototype = 0;
 
-  /* The function containing FNDECL, if any.  */
-  tree context = decl_function_context (fndecl);
+  int saved_warn_shadow = warn_shadow;
+
+  /* Don't re-emit shadow warnings.  */
+  warn_shadow = 0;
 
   if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
     {
@@ -6409,15 +6075,6 @@ store_parm_decls ()
              layout_decl (found, 0);
            }
 
-         /* Traditionally, a parm declared float is actually a double.  */
-         if (found && flag_traditional
-             && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
-           {
-             TREE_TYPE (found) = double_type_node;
-             DECL_ARG_TYPE (found) = double_type_node;
-             layout_decl (found, 0);
-           }
-
          /* If no declaration found, default to int.  */
          if (!found)
            {
@@ -6551,11 +6208,7 @@ store_parm_decls ()
                             "prototype declaration");
                        }
                    }
-                 /* If -traditional, allow `int' argument to match
-                    `unsigned' prototype.  */
-                 else if (! (flag_traditional
-                             && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
-                             && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
+                 else
                    {
                      error ("argument `%s' doesn't match prototype",
                             IDENTIFIER_POINTER (DECL_NAME (parm)));
@@ -6657,6 +6310,8 @@ store_parm_decls ()
      not safe to try to expand expressions involving them.  */
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
+
+  warn_shadow = saved_warn_shadow;
 }
 \f
 /* Finish up a function declaration and compile that function
@@ -6665,17 +6320,21 @@ store_parm_decls ()
 
    This is called after parsing the body of the function definition.
 
-   NESTED is nonzero if the function being finished is nested in another.  */
+   NESTED is nonzero if the function being finished is nested in another.
+   CAN_DEFER_P is nonzero if the function may be deferred.  */
 
 void
-finish_function (nested)
+finish_function (nested, can_defer_p)
      int nested;
+     int can_defer_p;
 {
   tree fndecl = current_function_decl;
 
-/*  TREE_READONLY (fndecl) = 1;
-    This caused &foo to be of type ptr-to-const-function
-    which then got a warning when stored in a ptr-to-function variable.  */
+#if 0
+  /* This caused &foo to be of type ptr-to-const-function which then
+     got a warning when stored in a ptr-to-function variable.  */
+  TREE_READONLY (fndecl) = 1;
+#endif
 
   poplevel (1, 0, 1);
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
@@ -6684,13 +6343,6 @@ finish_function (nested)
 
   DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
 
-  /* Obey `register' declarations if `setjmp' is called in this fn.  */
-  if (flag_traditional && current_function_calls_setjmp)
-    {
-      setjmp_protect (DECL_INITIAL (fndecl));
-      setjmp_protect_args ();
-    }
-
   if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
@@ -6717,6 +6369,22 @@ finish_function (nested)
 
   /* Tie off the statement tree for this function.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+
+  /* Complain if there's just no return statement.  */
+  if (warn_return_type
+      && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
+      && !current_function_returns_value && !current_function_returns_null
+      /* Don't complain if we abort.  */
+      && !current_function_returns_abnormally
+      /* Don't warn for main().  */
+      && !MAIN_NAME_P (DECL_NAME (fndecl))
+      /* Or if they didn't actually specify a return type.  */
+      && !C_FUNCTION_IMPLICIT_INT (fndecl)
+      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
+        inline function, as we might never be compiled separately.  */
+      && DECL_INLINE (fndecl))
+    warning ("no return statement in function returning non-void");
+
   /* Clear out memory we no longer need.  */
   free_after_parsing (cfun);
   /* Since we never call rest_of_compilation, we never clear
@@ -6727,22 +6395,39 @@ finish_function (nested)
   if (! nested)
     {
       /* Generate RTL for the body of this function.  */
-      c_expand_body (fndecl, nested);
+      c_expand_body (fndecl, nested, can_defer_p);
+
       /* Let the error reporting routines know that we're outside a
         function.  For a nested function, this value is used in
-        pop_c_function_context and then reset via pop_function_context.  */
+        c_pop_function_context and then reset via pop_function_context.  */
       current_function_decl = NULL;
     }
 }
 
-/* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
+/* Generate the RTL for a deferred function FNDECL.  */
+
+void
+c_expand_deferred_function (fndecl)
+     tree fndecl;
+{
+  /* DECL_INLINE or DECL_RESULT might got cleared after the inline
+     function was deferred, e.g. in duplicate_decls.  */
+  if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
+    {
+      c_expand_body (fndecl, 0, 0);
+      current_function_decl = NULL;
+    }
+}
+
+/* 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.  */
+   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)
+c_expand_body (fndecl, nested_p, can_defer_p)
      tree fndecl;
-     int nested_p;
+     int nested_p, can_defer_p;
 {
   int uninlinable = 1;
 
@@ -6756,12 +6441,28 @@ c_expand_body (fndecl, nested_p)
       /* 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)
     {
       /* Make sure that we will evaluate variable-sized types involved
@@ -6773,6 +6474,7 @@ c_expand_body (fndecl, nested_p)
 
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
+  input_filename = DECL_SOURCE_FILE (fndecl);
   init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
 
   /* This function is being processed in whole-function mode.  */
@@ -6785,10 +6487,6 @@ c_expand_body (fndecl, nested_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);
 
@@ -6872,7 +6570,7 @@ c_expand_body (fndecl, nested_p)
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
         was an actual function definition.
-        For a nested function, this is done in pop_c_function_context.
+        For a nested function, this is done in c_pop_function_context.
         If rest_of_compilation set this to 0, leave it 0.  */
       if (DECL_INITIAL (fndecl) != 0)
        DECL_INITIAL (fndecl) = error_mark_node;
@@ -6901,6 +6599,7 @@ c_expand_body (fndecl, nested_p)
   if (nested_p)
     /* Return to the enclosing function.  */
     pop_function_context ();
+  timevar_pop (TV_EXPAND);
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
@@ -6935,12 +6634,21 @@ check_for_loop_decls ()
   for (t = gettags (); t; t = TREE_CHAIN (t))
     {
       if (TREE_PURPOSE (t) != 0)
-       error ("`%s %s' declared in `for' loop initial declaration",
-              (TREE_CODE (TREE_VALUE (t)) == RECORD_TYPE ? "struct"
-               : TREE_CODE (TREE_VALUE (t)) == UNION_TYPE ? "union"
-               : "enum"),
-              IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+        {
+          enum tree_code code = TREE_CODE (TREE_VALUE (t));
+         
+          if (code == RECORD_TYPE)
+            error ("`struct %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+          else if (code == UNION_TYPE)
+            error ("`union %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+          else
+            error ("`enum %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+        }
     }
+
   for (t = getdecls (); t; t = TREE_CHAIN (t))
     {
       if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
@@ -6956,13 +6664,14 @@ 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;
   int returns_null;
+  int returns_abnormally;
   int warn_about_return_type;
   int extern_inline;
   struct binding_level *binding_level;
@@ -6972,13 +6681,13 @@ struct c_language_function
    used during compilation of a C function.  */
 
 void
-push_c_function_context (f)
+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;
@@ -6986,6 +6695,7 @@ push_c_function_context (f)
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
+  p->returns_abnormally = current_function_returns_abnormally;
   p->warn_about_return_type = warn_about_return_type;
   p->extern_inline = current_extern_inline;
   p->binding_level = current_binding_level;
@@ -6994,11 +6704,10 @@ push_c_function_context (f)
 /* Restore the variables used during compilation of a C function.  */
 
 void
-pop_c_function_context (f)
+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.  */
@@ -7023,36 +6732,18 @@ pop_c_function_context (f)
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
+  current_function_returns_abnormally = p->returns_abnormally;
   warn_about_return_type = p->warn_about_return_type;
   current_extern_inline = p->extern_inline;
   current_binding_level = p->binding_level;
 
-  free (p);
-  f->language = 0;
+  f->language = NULL;
 }
 
-/* Mark the language specific parts of F for GC.  */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
 
 void
-mark_c_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);
-}
-
-/* Copy the DECL_LANG_SEPECIFIC data associated with NODE.  */
-
-void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
      tree decl;
 {
   struct lang_decl *ld;
@@ -7066,38 +6757,12 @@ copy_lang_decl (decl)
   DECL_LANG_SPECIFIC (decl) = ld;
 }
 
-/* Mark the language specific bits in T for GC.  */
-
-void
-lang_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.  */
 
@@ -7169,7 +6834,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);
+    c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
 }
 
 /* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
@@ -7206,3 +6871,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"