OSDN Git Service

* cse.c (cse_reg_info_free_list, cse_reg_info_used_list,
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.in
index 9774bcf..fe0d517 100644 (file)
@@ -1,6 +1,6 @@
 /* YACC parser for C syntax and for Objective C.  -*-c-*-
-   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -52,7 +52,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "c-common.h"
 
-/* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
 
 /* Like the default stack expander, except (1) use realloc when possible,
@@ -99,8 +98,11 @@ do {                                                                 \
 
 %start program
 
-%union {long itype; tree ttype; struct c_expr exprtype; enum tree_code code;
-       location_t location; }
+%union {long itype; tree ttype; void *otype; struct c_expr exprtype;
+       struct c_arg_info *arginfotype; struct c_declarator *dtrtype;
+       struct c_type_name *typenametype; struct c_parm *parmtype;
+       struct c_declspecs *dsptype; struct c_typespec tstype;
+       enum tree_code code; location_t location; }
 
 /* All identifiers that are not reserved words
    and are not declared typedefs in the current block */
@@ -146,7 +148,6 @@ do {                                                                        \
 %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
 %token ATTRIBUTE EXTENSION LABEL
 %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
-%token PTR_VALUE PTR_BASE PTR_EXTENT
 %token FUNC_NAME OFFSETOF
 
 /* Add precedence rules to solve dangling else s/r conflict */
@@ -177,7 +178,7 @@ do {                                                                        \
    Objective C, so that the token codes are the same in both.  */
 %token AT_INTERFACE AT_IMPLEMENTATION AT_END AT_SELECTOR AT_DEFS AT_ENCODE
 %token CLASSNAME AT_PUBLIC AT_PRIVATE AT_PROTECTED AT_PROTOCOL
-%token OBJECTNAME AT_CLASS AT_ALIAS
+%token AT_CLASS AT_ALIAS
 %token AT_THROW AT_TRY AT_CATCH AT_FINALLY AT_SYNCHRONIZED
 %token OBJC_STRING
 
@@ -188,26 +189,27 @@ do {                                                                      \
 %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT STRING FUNC_NAME
 %type <ttype> nonnull_exprlist exprlist
 %type <exprtype> expr expr_no_commas cast_expr unary_expr primary
-%type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
-%type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
-%type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
-%type <ttype> declspecs_nosc_ts_sa_noea declspecs_nosc_ts_sa_ea
-%type <ttype> declspecs_sc_nots_nosa_noea declspecs_sc_nots_nosa_ea
-%type <ttype> declspecs_sc_nots_sa_noea declspecs_sc_nots_sa_ea
-%type <ttype> declspecs_sc_ts_nosa_noea declspecs_sc_ts_nosa_ea
-%type <ttype> declspecs_sc_ts_sa_noea declspecs_sc_ts_sa_ea
-%type <ttype> declspecs_ts declspecs_nots
-%type <ttype> declspecs_ts_nosa declspecs_nots_nosa
-%type <ttype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
-%type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
-%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
-%type <ttype> typespec_nonreserved_nonattr
+%type <dsptype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
+%type <dsptype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
+%type <dsptype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
+%type <dsptype> declspecs_nosc_ts_sa_noea declspecs_nosc_ts_sa_ea
+%type <dsptype> declspecs_sc_nots_nosa_noea declspecs_sc_nots_nosa_ea
+%type <dsptype> declspecs_sc_nots_sa_noea declspecs_sc_nots_sa_ea
+%type <dsptype> declspecs_sc_ts_nosa_noea declspecs_sc_ts_nosa_ea
+%type <dsptype> declspecs_sc_ts_sa_noea declspecs_sc_ts_sa_ea
+%type <dsptype> declspecs_ts declspecs_nots
+%type <dsptype> declspecs_ts_nosa declspecs_nots_nosa
+%type <dsptype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
+%type <dsptype> maybe_type_quals_attrs
+%type <tstype> typespec_nonattr typespec_attr
+%type <tstype> typespec_reserved_nonattr typespec_reserved_attr
+%type <tstype> typespec_nonreserved_nonattr
 %type <ttype> offsetof_member_designator
 
 %type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
 %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
 %type <exprtype> init
-%type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument
+%type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument asm_string
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
 %type <ttype> any_word
@@ -217,30 +219,34 @@ do {                                                                      \
 
 %type <ttype> c99_block_start c99_block_lineno_labeled_stmt
 %type <ttype> if_statement_1 if_statement_2
-%type <ttype> declarator
-%type <ttype> notype_declarator after_type_declarator
-%type <ttype> parm_declarator
-%type <ttype> parm_declarator_starttypename parm_declarator_nostarttypename
-%type <ttype> array_declarator
+%type <dtrtype> declarator
+%type <dtrtype> notype_declarator after_type_declarator
+%type <dtrtype> parm_declarator
+%type <dtrtype> parm_declarator_starttypename parm_declarator_nostarttypename
+%type <dtrtype> array_declarator
 
-%type <ttype> structsp_attr structsp_nonattr
+%type <tstype> structsp_attr structsp_nonattr
 %type <ttype> component_decl_list component_decl_list2
 %type <ttype> component_decl components components_notype component_declarator
 %type <ttype> component_notype_declarator
 %type <ttype> enumlist enumerator
 %type <ttype> struct_head union_head enum_head
-%type <ttype> typename absdcl absdcl1 absdcl1_ea absdcl1_noea
-%type <ttype> direct_absdcl1 absdcl_maybe_attribute
+%type <typenametype> typename
+%type <dtrtype> absdcl absdcl1 absdcl1_ea absdcl1_noea direct_absdcl1
+%type <parmtype> absdcl_maybe_attribute
 %type <ttype> condition xexpr for_cond_expr for_incr_expr
-%type <ttype> parms parm firstparm identifiers
+%type <parmtype> parm firstparm
+%type <ttype> identifiers
 
-%type <ttype> parmlist parmlist_1 parmlist_2
-%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
+%type <arginfotype> parms parmlist parmlist_1 parmlist_2
+%type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1
 %type <ttype> identifiers_or_typenames
 
 %type <itype> setspecs setspecs_fp extension
 
 %type <location> save_location
+
+%type <otype> save_obstack_position
 \f
 @@ifobjc
 /* the Objective-C nonterminals */
@@ -253,15 +259,15 @@ do {                                                                      \
 %type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
 %type <ttype> non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
 
-%type <ttype> CLASSNAME OBJECTNAME OBJC_STRING OBJC_TYPE_QUAL
+%type <ttype> CLASSNAME OBJC_STRING OBJC_TYPE_QUAL
 
 %type <ttype> superclass objc_quals objc_qual objc_typename
 %type <itype> objc_try_catch_stmt optellipsis
 @@end_ifobjc
 \f
 %{
-/* List of types and structure classes of the current declaration.  */
-static GTY(()) tree current_declspecs;
+/* Declaration specifiers of the current declaration.  */
+static struct c_declspecs *current_declspecs;
 static GTY(()) tree prefix_attributes;
 
 /* List of all the attributes applying to the identifier currently being
@@ -269,29 +275,44 @@ static GTY(()) tree prefix_attributes;
    just after a comma.  */
 static GTY(()) tree all_prefix_attributes;
 
+/* Structure to save declaration specifiers.  */
+struct c_declspec_stack {
+  /* Saved value of current_declspecs.  */
+  struct c_declspecs *current_declspecs;
+  /* Saved value of prefix_attributes.  */
+  tree prefix_attributes;
+  /* Saved value of all_prefix_attributes.  */
+  tree all_prefix_attributes;
+  /* Next level of stack.  */
+  struct c_declspec_stack *next;
+};
+
 /* Stack of saved values of current_declspecs, prefix_attributes and
    all_prefix_attributes.  */
-static GTY(()) tree declspec_stack;
+static struct c_declspec_stack *declspec_stack;
 
 /* INDIRECT_REF with a TREE_TYPE of the type being queried for offsetof.  */
 static tree offsetof_base;
 
 /* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
    should be called from the productions making use of setspecs.  */
-#define PUSH_DECLSPEC_STACK                                             \
-  do {                                                                  \
-    declspec_stack = tree_cons (build_tree_list (prefix_attributes,     \
-                                                all_prefix_attributes), \
-                               current_declspecs,                       \
-                               declspec_stack);                         \
+#define PUSH_DECLSPEC_STACK                                            \
+  do {                                                                 \
+    struct c_declspec_stack *t = XOBNEW (&parser_obstack,              \
+                                        struct c_declspec_stack);      \
+    t->current_declspecs = current_declspecs;                          \
+    t->prefix_attributes = prefix_attributes;                          \
+    t->all_prefix_attributes = all_prefix_attributes;                  \
+    t->next = declspec_stack;                                          \
+    declspec_stack = t;                                                        \
   } while (0)
 
 #define POP_DECLSPEC_STACK                                             \
   do {                                                                 \
-    current_declspecs = TREE_VALUE (declspec_stack);                   \
-    prefix_attributes = TREE_PURPOSE (TREE_PURPOSE (declspec_stack));  \
-    all_prefix_attributes = TREE_VALUE (TREE_PURPOSE (declspec_stack));        \
-    declspec_stack = TREE_CHAIN (declspec_stack);                      \
+    current_declspecs = declspec_stack->current_declspecs;             \
+    prefix_attributes = declspec_stack->prefix_attributes;             \
+    all_prefix_attributes = declspec_stack->all_prefix_attributes;     \
+    declspec_stack = declspec_stack->next;                             \
   } while (0)
 
 /* For __extension__, save/restore the warning flags which are
@@ -338,7 +359,7 @@ static inline int _yylex (void);
 static int  yylex (void);
 static void init_reswords (void);
 
-  /* Initialisation routine for this file.  */
+  /* Initialization routine for this file.  */
 void
 c_parse_init (void)
 {
@@ -357,11 +378,14 @@ program: /* empty */
 
 /* the reason for the strange actions in this rule
  is so that notype_initdecls when reached via datadef
- can find a valid list of type and sc specs in $0. */
+ can find valid declaration specifiers in $0. */
 
 extdefs:
-       {$<ttype>$ = NULL_TREE; } extdef
-       | extdefs {$<ttype>$ = NULL_TREE; ggc_collect(); } extdef
+       save_obstack_position { $<dsptype>$ = NULL; } extdef
+               { obstack_free (&parser_obstack, $1); }
+       | extdefs save_obstack_position
+               { $<dsptype>$ = NULL; ggc_collect (); } extdef
+               { obstack_free (&parser_obstack, $2); }
        ;
 
 extdef:
@@ -375,31 +399,33 @@ extdef:
 @@end_ifobjc
        ;
 
+/* Record the current position of parser_obstack before a
+   declaration to restore it afterwards.  */
+save_obstack_position:
+               { $$ = obstack_alloc (&parser_obstack, 0); }
+       ;
+
 datadef:
          setspecs notype_initdecls ';'
-               { if (pedantic)
-                   error ("ISO C forbids data definition with no type or storage class");
-                 else
-                   warning ("data definition has no type or storage class");
-
+               { pedwarn ("data definition has no type or storage class");
                  POP_DECLSPEC_STACK; }
         | declspecs_nots setspecs notype_initdecls ';'
                { POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs initdecls ';'
                { POP_DECLSPEC_STACK; }
        | declspecs ';'
-         { shadow_tag ($1); }
+         { shadow_tag (finish_declspecs ($1)); }
        | error ';'
        | error '}'
        | ';'
                { if (pedantic)
-                   pedwarn ("ISO C does not allow extra `;' outside of a function"); }
+                   pedwarn ("ISO C does not allow extra %<;%> outside of a function"); }
        ;
 \f
 fndef:
          declspecs_ts setspecs declarator
-               { if (! start_function (current_declspecs, $3,
-                                       all_prefix_attributes))
+               { if (!start_function (current_declspecs, $3,
+                                      all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls save_location
@@ -411,8 +437,8 @@ fndef:
        | declspecs_ts setspecs declarator error
                { POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator
-               { if (! start_function (current_declspecs, $3,
-                                       all_prefix_attributes))
+               { if (!start_function (current_declspecs, $3,
+                                      all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls save_location
@@ -424,8 +450,8 @@ fndef:
        | declspecs_nots setspecs notype_declarator error
                { POP_DECLSPEC_STACK; }
        | setspecs notype_declarator
-               { if (! start_function (NULL_TREE, $2,
-                                       all_prefix_attributes))
+               { if (!start_function (current_declspecs, $2,
+                                      all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls save_location
@@ -442,7 +468,6 @@ identifier:
        IDENTIFIER
        | TYPENAME
 @@ifobjc
-       | OBJECTNAME
        | CLASSNAME
 @@end_ifobjc
        ;
@@ -506,21 +531,23 @@ unary_expr:
                  $$.original_code = ERROR_MARK; }
        | sizeof unary_expr  %prec UNARY
                { skip_evaluation--;
+                 in_sizeof--;
                  if (TREE_CODE ($2.value) == COMPONENT_REF
                      && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
-                   error ("`sizeof' applied to a bit-field");
-                 $$.value = c_sizeof (TREE_TYPE ($2.value));
-                 $$.original_code = ERROR_MARK; }
+                   error ("%<sizeof%> applied to a bit-field");
+                 $$ = c_expr_sizeof_expr ($2); }
        | sizeof '(' typename ')'  %prec HYPERUNARY
                { skip_evaluation--;
-                 $$.value = c_sizeof (groktypename ($3));
-                 $$.original_code = ERROR_MARK; }
+                 in_sizeof--;
+                 $$ = c_expr_sizeof_type ($3); }
        | alignof unary_expr  %prec UNARY
                { skip_evaluation--;
+                 in_alignof--;
                  $$.value = c_alignof_expr ($2.value);
                  $$.original_code = ERROR_MARK; }
        | alignof '(' typename ')'  %prec HYPERUNARY
                { skip_evaluation--;
+                 in_alignof--;
                  $$.value = c_alignof (groktypename ($3));
                  $$.original_code = ERROR_MARK; }
        | REALPART cast_expr %prec UNARY
@@ -532,15 +559,15 @@ unary_expr:
        ;
 
 sizeof:
-       SIZEOF { skip_evaluation++; }
+       SIZEOF { skip_evaluation++; in_sizeof++; }
        ;
 
 alignof:
-       ALIGNOF { skip_evaluation++; }
+       ALIGNOF { skip_evaluation++; in_alignof++; }
        ;
 
 typeof:
-       TYPEOF { skip_evaluation++; }
+       TYPEOF { skip_evaluation++; in_typeof++; }
        ;
 
 cast_expr:
@@ -642,16 +669,21 @@ primary:
                  $$.original_code = ERROR_MARK; }
        | '(' typename ')' '{'
                { start_init (NULL_TREE, NULL, 0);
-                 $2 = groktypename ($2);
-                 really_start_incremental_init ($2); }
+                 $<ttype>$ = groktypename ($2);
+                 if (C_TYPE_VARIABLE_SIZE ($<ttype>$))
+                   {
+                     error ("compound literal has variable size");
+                     $<ttype>$ = error_mark_node;
+                   }
+                 really_start_incremental_init ($<ttype>$); }
          initlist_maybe_comma '}'  %prec UNARY
                { struct c_expr init = pop_init_level (0);
                  tree constructor = init.value;
-                 tree type = $2;
+                 tree type = $<ttype>5;
                  finish_init ();
                  maybe_warn_string_init (type, init);
 
-                 if (pedantic && ! flag_isoc99)
+                 if (pedantic && !flag_isoc99)
                    pedwarn ("ISO C90 forbids compound literals");
                  $$.value = build_compound_literal (type, constructor);
                  $$.original_code = ERROR_MARK;
@@ -701,7 +733,7 @@ primary:
                   c = fold ($3.value);
                   STRIP_NOPS (c);
                   if (TREE_CODE (c) != INTEGER_CST)
-                    error ("first argument to __builtin_choose_expr not"
+                    error ("first argument to %<__builtin_choose_expr%> not"
                           " a constant");
                   $$ = integer_zerop (c) ? $7 : $5;
                }
@@ -801,7 +833,7 @@ datadecl:
        | declspecs_nots_nosa setspecs notype_initdecls ';'
                { POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa ';'
-               { shadow_tag_warned ($1, 1);
+               { shadow_tag_warned (finish_declspecs ($1), 1);
                  pedwarn ("empty declaration"); }
        | declspecs_nots_nosa ';'
                { pedwarn ("empty declaration"); }
@@ -823,8 +855,18 @@ lineno_decl:
 setspecs: /* empty */
                { pending_xref_error ();
                  PUSH_DECLSPEC_STACK;
-                 split_specs_attrs ($<ttype>0,
-                                    &current_declspecs, &prefix_attributes);
+                 if ($<dsptype>0)
+                   {
+                     prefix_attributes = $<dsptype>0->attrs;
+                     $<dsptype>0->attrs = NULL_TREE;
+                     current_declspecs = $<dsptype>0;
+                   }
+                 else
+                   {
+                     prefix_attributes = NULL_TREE;
+                     current_declspecs = build_null_declspecs ();
+                   }
+                 current_declspecs = finish_declspecs (current_declspecs);
                  all_prefix_attributes = prefix_attributes; }
        ;
 
@@ -845,7 +887,7 @@ decl:
        | declspecs_nots setspecs notype_nested_function
                { POP_DECLSPEC_STACK; }
        | declspecs ';'
-               { shadow_tag ($1); }
+               { shadow_tag (finish_declspecs ($1)); }
        | extension decl
                { RESTORE_EXT_FLAGS ($1); }
        ;
@@ -861,16 +903,6 @@ decl:
 
    - Attribute specifier lists (attributes).
 
-   These are stored as a TREE_LIST; the head of the list is the last
-   item in the specifier list.  Each entry in the list has either a
-   TREE_PURPOSE that is an attribute specifier list, or a TREE_VALUE that
-   is a single other specifier or qualifier; and a TREE_CHAIN that is the
-   rest of the list.  TREE_STATIC is set on the list if something other
-   than a storage class specifier or attribute has been seen; this is used
-   to warn for the obsolescent usage of storage class specifiers other than
-   at the start of the list.  (Doing this properly would require function
-   specifiers to be handled separately from storage class specifiers.)
-
    The various cases below are classified according to:
 
    (a) Whether a storage class specifier is included or not; some
@@ -899,334 +931,208 @@ decl:
 
 /* Declspecs which contain at least one type specifier or typedef name.
    (Just `const' or `volatile' is not enough.)
-   A typedef'd name following these is taken as a name to be declared.
-   Declspecs have a non-NULL TREE_VALUE, attributes do not.  */
+   A typedef'd name following these is taken as a name to be declared.  */
 
 declspecs_nosc_nots_nosa_noea:
          TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual (build_null_declspecs (), $1); }
        | declspecs_nosc_nots_nosa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_nots_nosa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        ;
 
 declspecs_nosc_nots_nosa_ea:
          declspecs_nosc_nots_nosa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        ;
 
 declspecs_nosc_nots_sa_noea:
          declspecs_nosc_nots_sa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_nots_sa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        ;
 
 declspecs_nosc_nots_sa_ea:
          attributes
-               { $$ = tree_cons ($1, NULL_TREE, NULL_TREE);
-                 TREE_STATIC ($$) = 0; }
+               { $$ = declspecs_add_attrs (build_null_declspecs (), $1); }
        | declspecs_nosc_nots_sa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        ;
 
 declspecs_nosc_ts_nosa_noea:
          typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type (build_null_declspecs (), $1); }
        | declspecs_nosc_ts_nosa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_ts_nosa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_ts_nosa_noea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_nosa_ea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_nosa_noea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_nosa_ea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 declspecs_nosc_ts_nosa_ea:
          typespec_attr
-               { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type (build_null_declspecs (), $1); }
        | declspecs_nosc_ts_nosa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        | declspecs_nosc_ts_nosa_noea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_nosa_ea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_nosa_noea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_nosa_ea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 declspecs_nosc_ts_sa_noea:
          declspecs_nosc_ts_sa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_ts_sa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_ts_sa_noea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_sa_ea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_sa_noea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_sa_ea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 declspecs_nosc_ts_sa_ea:
          declspecs_nosc_ts_sa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        | declspecs_nosc_ts_sa_noea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_sa_ea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_sa_noea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_nots_sa_ea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 declspecs_sc_nots_nosa_noea:
          scspec
-               { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
-                 TREE_STATIC ($$) = 0; }
+               { $$ = declspecs_add_scspec (build_null_declspecs (), $1); }
        | declspecs_sc_nots_nosa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_nots_nosa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_nots_nosa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_nosc_nots_nosa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_nots_nosa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_nots_nosa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        ;
 
 declspecs_sc_nots_nosa_ea:
          declspecs_sc_nots_nosa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        ;
 
 declspecs_sc_nots_sa_noea:
          declspecs_sc_nots_sa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_nots_sa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_nosc_nots_sa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_nosc_nots_sa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_nots_sa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_nots_sa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        ;
 
 declspecs_sc_nots_sa_ea:
          declspecs_sc_nots_sa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        ;
 
 declspecs_sc_ts_nosa_noea:
          declspecs_sc_ts_nosa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_ts_nosa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_ts_nosa_noea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_ts_nosa_ea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_nosa_noea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_nosa_ea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_nosa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_nosc_ts_nosa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_ts_nosa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_ts_nosa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        ;
 
 declspecs_sc_ts_nosa_ea:
          declspecs_sc_ts_nosa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        | declspecs_sc_ts_nosa_noea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_ts_nosa_ea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_nosa_noea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_nosa_ea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 declspecs_sc_ts_sa_noea:
          declspecs_sc_ts_sa_noea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_ts_sa_ea TYPE_QUAL
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_qual ($1, $2); }
        | declspecs_sc_ts_sa_noea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_ts_sa_ea typespec_reserved_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_sa_noea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_sa_ea typespec_nonattr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_nosc_ts_sa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_nosc_ts_sa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_ts_sa_noea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        | declspecs_sc_ts_sa_ea scspec
-               { if (extra_warnings && TREE_STATIC ($1))
-                   warning ("`%s' is not at beginning of declaration",
-                            IDENTIFIER_POINTER ($2));
-                 $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_scspec ($1, $2); }
        ;
 
 declspecs_sc_ts_sa_ea:
          declspecs_sc_ts_sa_noea attributes
-               { $$ = tree_cons ($2, NULL_TREE, $1);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+               { $$ = declspecs_add_attrs ($1, $2); }
        | declspecs_sc_ts_sa_noea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_ts_sa_ea typespec_reserved_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_sa_noea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        | declspecs_sc_nots_sa_ea typespec_attr
-               { $$ = tree_cons (NULL_TREE, $2, $1);
-                 TREE_STATIC ($$) = 1; }
+               { $$ = declspecs_add_type ($1, $2); }
        ;
 
 /* Particular useful classes of declspecs.  */
@@ -1313,7 +1219,7 @@ declspecs:
 /* A (possibly empty) sequence of type qualifiers and attributes.  */
 maybe_type_quals_attrs:
          /* empty */
-               { $$ = NULL_TREE; }
+               { $$ = NULL; }
        | declspecs_nosc_nots
                { $$ = $1; }
        ;
@@ -1337,7 +1243,7 @@ maybe_type_quals_attrs:
    or are such that any following attributes would
    be parsed as part of the specifier.
 
-   _nonattr: specifiers.  */
+   _nonattr: other specifiers not ending with attributes.  */
 
 typespec_nonattr:
          typespec_reserved_nonattr
@@ -1350,7 +1256,9 @@ typespec_attr:
 
 typespec_reserved_nonattr:
          TYPESPEC
-               { OBJC_NEED_RAW_IDENTIFIER (1); }
+               { OBJC_NEED_RAW_IDENTIFIER (1);
+                 $$.kind = ctsk_resword;
+                 $$.spec = $1; }
        | structsp_nonattr
        ;
 
@@ -1362,26 +1270,39 @@ typespec_nonreserved_nonattr:
          TYPENAME
                { /* For a typedef name, record the meaning, not the name.
                     In case of `foo foo, bar;'.  */
-                 $$ = lookup_name ($1); }
+                 $$.kind = ctsk_typedef;
+                 $$.spec = lookup_name ($1); }
 @@ifobjc
        | CLASSNAME protocolrefs
-               { $$ = objc_get_protocol_qualified_type ($1, $2); }
-       | OBJECTNAME protocolrefs
-               { $$ = objc_get_protocol_qualified_type ($1, $2); }
+               { $$.kind = ctsk_objc;
+                 $$.spec = objc_get_protocol_qualified_type ($1, $2); }
+       | TYPENAME non_empty_protocolrefs
+               { $$.kind = ctsk_objc;
+                 $$.spec = objc_get_protocol_qualified_type ($1, $2); }
 
 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
    - nisse@lysator.liu.se */
         | non_empty_protocolrefs
-                { $$ = objc_get_protocol_qualified_type (NULL_TREE, $1); }
+                { $$.kind = ctsk_objc;
+                 $$.spec = objc_get_protocol_qualified_type (NULL_TREE, $1); }
 @@end_ifobjc
        | typeof '(' expr ')'
                { skip_evaluation--;
+                 in_typeof--;
                  if (TREE_CODE ($3.value) == COMPONENT_REF
                      && DECL_C_BIT_FIELD (TREE_OPERAND ($3.value, 1)))
-                   error ("`typeof' applied to a bit-field");
-                 $$ = TREE_TYPE ($3.value); }
+                   error ("%<typeof%> applied to a bit-field");
+                 $$.kind = ctsk_typeof;
+                 $$.spec = TREE_TYPE ($3.value);
+                 pop_maybe_used (variably_modified_type_p ($$.spec,
+                                                           NULL_TREE)); }
        | typeof '(' typename ')'
-               { skip_evaluation--; $$ = groktypename ($3); }
+               { skip_evaluation--;
+                 in_typeof--;
+                 $$.kind = ctsk_typeof;
+                 $$.spec = groktypename ($3);
+                 pop_maybe_used (variably_modified_type_p ($$.spec,
+                                                           NULL_TREE)); }
        ;
 
 /* typespec_nonreserved_attr does not exist.  */
@@ -1400,16 +1321,23 @@ initdcl:
          declarator maybeasm maybe_attribute '='
                { $<ttype>$ = start_decl ($1, current_declspecs, true,
                                          chainon ($3, all_prefix_attributes));
+                 if (!$<ttype>$)
+                   $<ttype>$ = error_mark_node;
                  start_init ($<ttype>$, $2, global_bindings_p ()); }
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
                { finish_init ();
-                 maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
-                 finish_decl ($<ttype>5, $6.value, $2); }
+                 if ($<ttype>5 != error_mark_node)
+                   {
+                     maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
+                     finish_decl ($<ttype>5, $6.value, $2);
+                   }
+               }
        | declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, false,
                                       chainon ($3, all_prefix_attributes));
-                 finish_decl (d, NULL_TREE, $2);
+                 if (d)
+                   finish_decl (d, NULL_TREE, $2);
                 }
        ;
 
@@ -1417,16 +1345,23 @@ notype_initdcl:
          notype_declarator maybeasm maybe_attribute '='
                { $<ttype>$ = start_decl ($1, current_declspecs, true,
                                          chainon ($3, all_prefix_attributes));
+                 if (!$<ttype>$)
+                   $<ttype>$ = error_mark_node;
                  start_init ($<ttype>$, $2, global_bindings_p ()); }
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
                { finish_init ();
-                 maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
-                 finish_decl ($<ttype>5, $6.value, $2); }
+                 if ($<ttype>5 != error_mark_node)
+                   {
+                     maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
+                     finish_decl ($<ttype>5, $6.value, $2);
+                   }
+               }
        | notype_declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, false,
                                       chainon ($3, all_prefix_attributes));
-                 finish_decl (d, NULL_TREE, $2); }
+                 if (d)
+                    finish_decl (d, NULL_TREE, $2); }
        ;
 /* the * rules are dummies to accept the Apollo extended syntax
    so that the header files compile. */
@@ -1449,7 +1384,7 @@ attribute:
                 '(' '(' attribute_list ')' ')' start_string_translation
                { $$ = $5; }
       | ATTRIBUTE error start_string_translation
-                {}
+                { $$ = NULL_TREE; }
        ;
 
 attribute_list:
@@ -1517,15 +1452,15 @@ initlist1:
    It may use braces.  */
 initelt:
          designator_list '=' initval
-               { if (pedantic && ! flag_isoc99)
+               { if (pedantic && !flag_isoc99)
                    pedwarn ("ISO C90 forbids specifying subobject to initialize"); }
-       | designator initval
+       | array_designator initval
                { if (pedantic)
-                   pedwarn ("obsolete use of designated initializer without `='"); }
+                   pedwarn ("obsolete use of designated initializer without %<=%>"); }
        | identifier ':'
                { set_init_label ($1);
                  if (pedantic)
-                   pedwarn ("obsolete use of designated initializer with `:'"); }
+                   pedwarn ("obsolete use of designated initializer with %<:%>"); }
          initval
                {}
        | initval
@@ -1549,7 +1484,11 @@ designator_list:
 designator:
          '.' identifier
                { set_init_label ($2); }
-       | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
+       | array_designator
+       ;
+
+array_designator:
+         '[' expr_no_commas ELLIPSIS expr_no_commas ']'
                { set_init_index ($2.value, $4.value);
                  if (pedantic)
                    pedwarn ("ISO C forbids specifying range of elements to initialize"); }
@@ -1563,8 +1502,8 @@ nested_function:
                    pedwarn ("ISO C forbids nested functions");
 
                  push_function_context ();
-                 if (! start_function (current_declspecs, $1,
-                                       all_prefix_attributes))
+                 if (!start_function (current_declspecs, $1,
+                                      all_prefix_attributes))
                    {
                      pop_function_context ();
                      YYERROR1;
@@ -1593,8 +1532,8 @@ notype_nested_function:
                    pedwarn ("ISO C forbids nested functions");
 
                  push_function_context ();
-                 if (! start_function (current_declspecs, $1,
-                                       all_prefix_attributes))
+                 if (!start_function (current_declspecs, $1,
+                                      all_prefix_attributes))
                    {
                      pop_function_context ();
                      YYERROR1;
@@ -1637,9 +1576,7 @@ after_type_declarator:
        | '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | TYPENAME
-@@ifobjc
-       | OBJECTNAME
-@@end_ifobjc
+               { $$ = build_id_declarator ($1); }
        ;
 
 /* Kinds of declarator that can appear in a parameter list
@@ -1657,9 +1594,7 @@ parm_declarator_starttypename:
        | parm_declarator_starttypename array_declarator  %prec '.'
                { $$ = set_array_declarator_inner ($2, $1, false); }
        | TYPENAME
-@@ifobjc
-       | OBJECTNAME
-@@end_ifobjc
+               { $$ = build_id_declarator ($1); }
        ;
 
 parm_declarator_nostarttypename:
@@ -1688,6 +1623,7 @@ notype_declarator:
        | notype_declarator array_declarator  %prec '.'
                { $$ = set_array_declarator_inner ($2, $1, false); }
        | IDENTIFIER
+               { $$ = build_id_declarator ($1); }
        ;
 
 struct_head:
@@ -1719,48 +1655,56 @@ enum_head:
 
 structsp_attr:
          struct_head identifier '{'
-               { $$ = start_struct (RECORD_TYPE, $2);
+               { $<ttype>$ = start_struct (RECORD_TYPE, $2);
                  /* Start scope of tag before parsing components.  */
                }
          component_decl_list '}' maybe_attribute
-               { $$ = finish_struct ($<ttype>4, nreverse ($5),
-                                     chainon ($1, $7)); }
+               { $$.spec = finish_struct ($<ttype>4, nreverse ($5),
+                                          chainon ($1, $7));
+                 $$.kind = ctsk_tagdef; }
        | struct_head '{' component_decl_list '}' maybe_attribute
-               { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
-                                     nreverse ($3), chainon ($1, $5));
+               { $$.spec = finish_struct (start_struct (RECORD_TYPE,
+                                                        NULL_TREE),
+                                          nreverse ($3), chainon ($1, $5));
+                 $$.kind = ctsk_tagdef;
                }
        | union_head identifier '{'
-               { $$ = start_struct (UNION_TYPE, $2); }
+               { $<ttype>$ = start_struct (UNION_TYPE, $2); }
          component_decl_list '}' maybe_attribute
-               { $$ = finish_struct ($<ttype>4, nreverse ($5),
-                                     chainon ($1, $7)); }
+               { $$.spec = finish_struct ($<ttype>4, nreverse ($5),
+                                          chainon ($1, $7));
+                 $$.kind = ctsk_tagdef; }
        | union_head '{' component_decl_list '}' maybe_attribute
-               { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
-                                     nreverse ($3), chainon ($1, $5));
+               { $$.spec = finish_struct (start_struct (UNION_TYPE,
+                                                        NULL_TREE),
+                                          nreverse ($3), chainon ($1, $5));
+                 $$.kind = ctsk_tagdef;
                }
        | enum_head identifier '{'
-               { $$ = start_enum ($2); }
+               { $<ttype>$ = start_enum ($2); }
          enumlist maybecomma_warn '}' maybe_attribute
-               { $$ = finish_enum ($<ttype>4, nreverse ($5),
-                                   chainon ($1, $8)); }
+               { $$.spec = finish_enum ($<ttype>4, nreverse ($5),
+                                        chainon ($1, $8));
+                 $$.kind = ctsk_tagdef; }
        | enum_head '{'
-               { $$ = start_enum (NULL_TREE); }
+               { $<ttype>$ = start_enum (NULL_TREE); }
          enumlist maybecomma_warn '}' maybe_attribute
-               { $$ = finish_enum ($<ttype>3, nreverse ($4),
-                                   chainon ($1, $7)); }
+               { $$.spec = finish_enum ($<ttype>3, nreverse ($4),
+                                        chainon ($1, $7));
+                 $$.kind = ctsk_tagdef; }
        ;
 
 structsp_nonattr:
          struct_head identifier
-               { $$ = xref_tag (RECORD_TYPE, $2); }
+               { $$ = parser_xref_tag (RECORD_TYPE, $2); }
        | union_head identifier
-               { $$ = xref_tag (UNION_TYPE, $2); }
+               { $$ = parser_xref_tag (UNION_TYPE, $2); }
        | enum_head identifier
-               { $$ = xref_tag (ENUMERAL_TYPE, $2);
+               { $$ = parser_xref_tag (ENUMERAL_TYPE, $2);
                  /* In ISO C, enumerated types can be referred to
                     only if already defined.  */
-                 if (pedantic && !COMPLETE_TYPE_P ($$))
-                   pedwarn ("ISO C forbids forward references to `enum' types"); }
+                 if (pedantic && !COMPLETE_TYPE_P ($$.spec))
+                   pedwarn ("ISO C forbids forward references to %<enum%> types"); }
        ;
 
 maybecomma:
@@ -1771,7 +1715,7 @@ maybecomma:
 maybecomma_warn:
          /* empty */
        | ','
-               { if (pedantic && ! flag_isoc99)
+               { if (pedantic && !flag_isoc99)
                    pedwarn ("comma at end of enumerator list"); }
        ;
 
@@ -1818,10 +1762,8 @@ component_decl:
                  /* Support for unnamed structs or unions as members of
                     structs or unions (which is [a] useful and [b] supports
                     MS P-SDK).  */
-                 if (pedantic)
-                   pedwarn ("ISO C doesn't support unnamed structs/unions");
-
-                 $$ = grokfield(NULL, current_declspecs, NULL_TREE);
+                 $$ = grokfield (build_id_declarator (NULL_TREE),
+                                 current_declspecs, NULL_TREE);
                  POP_DECLSPEC_STACK; }
        | declspecs_nosc_nots setspecs components_notype
                { $$ = $3;
@@ -1829,7 +1771,7 @@ component_decl:
        | declspecs_nosc_nots
                { if (pedantic)
                    pedwarn ("ISO C forbids member declarations with no members");
-                 shadow_tag_warned ($1, pedantic);
+                 shadow_tag_warned (finish_declspecs ($1), pedantic);
                  $$ = NULL_TREE; }
        | error
                { $$ = NULL_TREE; }
@@ -1860,7 +1802,8 @@ component_declarator:
                  decl_attributes (&$$,
                                   chainon ($4, all_prefix_attributes), 0); }
        | ':' expr_no_commas maybe_attribute
-               { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+               { $$ = grokfield (build_id_declarator (NULL_TREE),
+                                 current_declspecs, $2.value);
                  decl_attributes (&$$,
                                   chainon ($3, all_prefix_attributes), 0); }
        ;
@@ -1875,7 +1818,8 @@ component_notype_declarator:
                  decl_attributes (&$$,
                                   chainon ($4, all_prefix_attributes), 0); }
        | ':' expr_no_commas maybe_attribute
-               { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+               { $$ = grokfield (build_id_declarator (NULL_TREE),
+                                 current_declspecs, $2.value);
                  decl_attributes (&$$,
                                   chainon ($3, all_prefix_attributes), 0); }
        ;
@@ -1905,21 +1849,23 @@ enumerator:
 typename:
          declspecs_nosc
                { pending_xref_error ();
-                 $<ttype>$ = $1; }
+                 $<dsptype>$ = finish_declspecs ($1); }
          absdcl
-               { $$ = build_tree_list ($<ttype>2, $3); }
+               { $$ = XOBNEW (&parser_obstack, struct c_type_name);
+                 $$->specs = $<dsptype>2;
+                 $$->declarator = $3; }
        ;
 
 absdcl:   /* an absolute declarator */
        /* empty */
-               { $$ = NULL_TREE; }
+               { $$ = build_id_declarator (NULL_TREE); }
        | absdcl1
        ;
 
 absdcl_maybe_attribute:   /* absdcl maybe_attribute, but not just attributes */
        /* empty */
                { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
-                                    NULL_TREE); }
+                                    build_id_declarator (NULL_TREE)); }
        | absdcl1
                { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
                                     $1); }
@@ -1942,7 +1888,8 @@ absdcl1_noea:
 
 absdcl1_ea:
          '*' maybe_type_quals_attrs
-               { $$ = make_pointer_declarator ($2, NULL_TREE); }
+               { $$ = make_pointer_declarator
+                   ($2, build_id_declarator (NULL_TREE)); }
        | '*' maybe_type_quals_attrs absdcl1_ea
                { $$ = make_pointer_declarator ($2, $3); }
        ;
@@ -1955,9 +1902,11 @@ direct_absdcl1:
        | direct_absdcl1 array_declarator
                { $$ = set_array_declarator_inner ($2, $1, true); }
        | '(' parmlist
-               { $$ = build_function_declarator ($2, NULL_TREE); }
+               { $$ = build_function_declarator
+                   ($2, build_id_declarator (NULL_TREE)); }
        | array_declarator
-               { $$ = set_array_declarator_inner ($1, NULL_TREE, true); }
+               { $$ = set_array_declarator_inner
+                   ($1, build_id_declarator (NULL_TREE), true); }
        ;
 
 /* The [...] part of a declarator for an array type.  */
@@ -2088,7 +2037,7 @@ compstmt_contents_nonempty:
 
 compstmt_primary_start:
        '(' '{'
-               { if (current_function_decl == 0)
+               { if (cur_stmt_list == NULL)
                    {
                      error ("braced-group within expression allowed "
                             "only inside a function");
@@ -2125,9 +2074,9 @@ c99_block_lineno_labeled_stmt:
 
 lineno_stmt:
          save_location stmt
-               { 
+               {
                  /* Two cases cannot and do not have line numbers associated:
-                    If stmt is degenerate, such as "2;", then stmt is an 
+                    If stmt is degenerate, such as "2;", then stmt is an
                     INTEGER_CST, which cannot hold line numbers.  But that's
                     ok because the statement will either be changed to a
                     MODIFY_EXPR during gimplification of the statement expr,
@@ -2381,7 +2330,7 @@ label:      CASE expr_no_commas ':'
    expression with inputs and outputs does not make sense.  */
 simple_asm_expr:
        ASM_KEYWORD stop_string_translation
-             '(' STRING ')' start_string_translation
+             '(' asm_string ')' start_string_translation
                { $$ = $4; }
        ;
 
@@ -2410,16 +2359,16 @@ asm_stmt:
 
 asm_argument:
        /* no operands */
-       STRING
+       asm_string
                { $$ = build_asm_expr ($1, 0, 0, 0, true); }
        /* output operands */
-       | STRING ':' asm_operands
+       | asm_string ':' asm_operands
                { $$ = build_asm_expr ($1, $3, 0, 0, false); }
        /* output and input operands */
-       | STRING ':' asm_operands ':' asm_operands
+       | asm_string ':' asm_operands ':' asm_operands
                { $$ = build_asm_expr ($1, $3, $5, 0, false); }
        /* output and input operands and clobbers */
-       | STRING ':' asm_operands ':' asm_operands ':' asm_clobbers
+       | asm_string ':' asm_operands ':' asm_operands ':' asm_clobbers
                { $$ = build_asm_expr ($1, $3, $5, $7, false); }
        ;
 
@@ -2453,10 +2402,11 @@ nonnull_asm_operands:
        ;
 
 asm_operand:
-         STRING start_string_translation '(' expr ')' stop_string_translation
+         asm_string start_string_translation '(' expr ')'
+           stop_string_translation
                { $$ = build_tree_list (build_tree_list (NULL_TREE, $1),
                                        $4.value); }
-       | '[' identifier ']' STRING start_string_translation
+       | '[' identifier ']' asm_string start_string_translation
          '(' expr ')' stop_string_translation
                { $2 = build_string (IDENTIFIER_LENGTH ($2),
                                     IDENTIFIER_POINTER ($2));
@@ -2464,12 +2414,25 @@ asm_operand:
        ;
 
 asm_clobbers:
-         STRING
+         asm_string
                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
-       | asm_clobbers ',' STRING
+       | asm_clobbers ',' asm_string
                { $$ = tree_cons (NULL_TREE, $3, $1); }
        ;
 
+/* Strings in 'asm' must be narrow strings.  */
+asm_string:
+         STRING
+               { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE ($1)))
+                     != char_type_node)
+                   {
+                     error ("wide string literal in %<asm%>");
+                     $$ = build_string (1, "");
+                   }
+                 else
+                   $$ = $1; }
+       ;
+
 stop_string_translation:
         { c_lex_string_translate = 0; }
         ;
@@ -2503,18 +2466,29 @@ parmlist_1:
          parmlist_1
                { $$ = $6; }
        | error ')'
-               { $$ = make_node (TREE_LIST); }
+               { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+                 $$->parms = 0;
+                 $$->tags = 0;
+                 $$->types = 0;
+                 $$->others = 0; }
        ;
 
 /* This is what appears inside the parens in a function declarator.
-   Is value is represented in the format that grokdeclarator expects.  */
+   Its value is represented in the format that grokdeclarator expects.  */
 parmlist_2:  /* empty */
-               { $$ = make_node (TREE_LIST); }
+               { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+                 $$->parms = 0;
+                 $$->tags = 0;
+                 $$->types = 0;
+                 $$->others = 0; }
        | ELLIPSIS
-               { $$ = make_node (TREE_LIST); 
+               { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+                 $$->parms = 0;
+                 $$->tags = 0;
+                 $$->others = 0;
                  /* Suppress -Wold-style-definition for this case.  */
-                 TREE_CHAIN ($$) = error_mark_node;
-                 error ("ISO C requires a named argument before `...'");
+                 $$->types = error_mark_node;
+                 error ("ISO C requires a named argument before %<...%>");
                }
        | parms
                { $$ = get_parm_info (/*ellipsis=*/false); }
@@ -2598,7 +2572,11 @@ parmlist_or_identifiers:
 parmlist_or_identifiers_1:
          parmlist_1
        | identifiers ')'
-               { $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+               { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+                 $$->parms = 0;
+                 $$->tags = 0;
+                 $$->types = $1;
+                 $$->others = 0;
 
                  /* Make sure we have a parmlist after attributes.  */
                  if ($<ttype>-1 != 0)
@@ -2624,7 +2602,7 @@ identifiers_or_typenames:
 
 extension:
        EXTENSION
-               { $$ = SAVE_EXT_FLAGS();
+               { $$ = SAVE_EXT_FLAGS ();
                  pedantic = 0;
                  warn_pointer_arith = 0;
                  warn_traditional = 0;
@@ -2893,7 +2871,7 @@ optparms:
                                                     grokparm ($3)));
                }
        ;
-       
+
 optellipsis:
          /* NULL */
                {
@@ -2922,7 +2900,6 @@ selector:
          IDENTIFIER
        | TYPENAME
        | CLASSNAME
-       | OBJECTNAME
        | reservedwords
        ;
 
@@ -2930,7 +2907,7 @@ reservedwords:
          ENUM | STRUCT | UNION | IF | ELSE | WHILE | DO | FOR
        | SWITCH | CASE | DEFAULT | BREAK | CONTINUE | RETURN
        | GOTO | ASM_KEYWORD | SIZEOF | TYPEOF | ALIGNOF
-       | TYPESPEC | TYPE_QUAL
+       | TYPESPEC | TYPE_QUAL | OBJC_TYPE_QUAL
        ;
 
 objc_qual:
@@ -3133,12 +3110,6 @@ static const struct resword reswords[] =
   { "__inline",                RID_INLINE,     0 },
   { "__inline__",      RID_INLINE,     0 },
   { "__label__",       RID_LABEL,      0 },
-  { "__ptrbase",       RID_PTRBASE,    0 },
-  { "__ptrbase__",     RID_PTRBASE,    0 },
-  { "__ptrextent",     RID_PTREXTENT,  0 },
-  { "__ptrextent__",   RID_PTREXTENT,  0 },
-  { "__ptrvalue",      RID_PTRVALUE,   0 },
-  { "__ptrvalue__",    RID_PTRVALUE,   0 },
   { "__real",          RID_REALPART,   0 },
   { "__real__",                RID_REALPART,   0 },
   { "__restrict",      RID_RESTRICT,   0 },
@@ -3188,7 +3159,6 @@ static const struct resword reswords[] =
   { "while",           RID_WHILE,      0 },
 
 @@ifobjc
-  { "id",              RID_ID,                 D_OBJC },
 
   /* These objc keywords are recognized only immediately after
      an '@'.  */
@@ -3292,9 +3262,6 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_IMAGPART */   IMAGPART,
   /* RID_REALPART */   REALPART,
   /* RID_LABEL */      LABEL,
-  /* RID_PTRBASE */    PTR_BASE,
-  /* RID_PTREXTENT */  PTR_EXTENT,
-  /* RID_PTRVALUE */   PTR_VALUE,
 
   /* RID_CHOOSE_EXPR */                        CHOOSE_EXPR,
   /* RID_TYPES_COMPATIBLE_P */         TYPES_COMPATIBLE_P,
@@ -3334,7 +3301,6 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_STATCAST */   0,
 
   /* Objective C */
-  /* RID_ID */                 OBJECTNAME,
   /* RID_AT_ENCODE */          AT_ENCODE,
   /* RID_AT_END */             AT_END,
   /* RID_AT_CLASS */           AT_CLASS,
@@ -3403,15 +3369,6 @@ yylexname (void)
       enum rid rid_code = C_RID_CODE (yylval.ttype);
 
 @@ifobjc
-      /* Turn non-typedefed refs to "id" into plain identifiers; this
-        allows constructs like "void foo(id id);" to work.  */
-      if (rid_code == RID_ID)
-      {
-       decl = lookup_name (yylval.ttype);
-       if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL)
-         return IDENTIFIER;
-      }
-
       if (!OBJC_IS_AT_KEYWORD (rid_code)
          && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
 @@end_ifobjc
@@ -3542,7 +3499,7 @@ _yylex (void)
       /* These tokens should not survive translation phase 4.  */
     case CPP_HASH:
     case CPP_PASTE:
-      error ("syntax error at '%s' token", NAME(last_token));
+      error ("syntax error at %qs token", NAME(last_token));
       goto get_next;
 
     default:
@@ -3574,13 +3531,12 @@ yyprint (FILE *file, int yychar, YYSTYPE yyl)
     {
     case IDENTIFIER:
     case TYPENAME:
-    case OBJECTNAME:
     case TYPESPEC:
     case TYPE_QUAL:
     case SCSPEC:
     case STATIC:
       if (IDENTIFIER_POINTER (t))
-       fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
+       fprintf (file, " '%s'", IDENTIFIER_POINTER (t));
       break;
 
     case CONSTANT:
@@ -3612,4 +3568,21 @@ c_parse_file (void)
     }
 }
 
+#ifdef __XGETTEXT__
+/* Depending on the version of Bison used to compile this grammar,
+   it may issue generic diagnostics spelled "syntax error" or
+   "parse error".  To prevent this from changing the translation
+   template randomly, we list all the variants of this particular
+   diagnostic here.  Translators: there is no fine distinction
+   between diagnostics with "syntax error" in them, and diagnostics
+   with "parse error" in them.  It's okay to give them both the same
+   translation.  */
+const char d1[] = N_("syntax error");
+const char d2[] = N_("parse error");
+const char d3[] = N_("syntax error; also virtual memory exhausted");
+const char d4[] = N_("parse error; also virtual memory exhausted");
+const char d5[] = N_("syntax error: cannot back up");
+const char d6[] = N_("parse error: cannot back up");
+#endif
+
 #include "gt-c-parse.h"