OSDN Git Service

* gcc.texi: Fixes for makeinfo 4.0 --html.
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.y
index 4f0b1af..99998fc 100644 (file)
@@ -1,6 +1,7 @@
 /*WARNING: This file is automatically generated!*/
 /* YACC parser for C syntax and for Objective C.  -*-c-*-
-   Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -28,43 +29,21 @@ Boston, MA 02111-1307, USA.  */
 /* To whomever it may concern: I have heard that such a thing was once
    written by AT&T, but I have never seen it.  */
 
-%expect 46
-
-/* These are the 23 conflicts you should get in parse.output;
-   the state numbers may vary if minor changes in the grammar are made.
-
-State 42 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 44 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 103 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 110 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 111 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 115 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 132 contains 1 shift/reduce conflict.  (See comment at component_decl.)
-State 180 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 194 contains 2 shift/reduce conflict.  (Four ways to parse this.)
-State 202 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 214 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 220 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 304 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 335 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 347 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
-State 352 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
-State 383 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 434 contains 2 shift/reduce conflicts.  (Four ways to parse this.)  */
-
+%expect 53
 
 %{
 #include "config.h"
 #include "system.h"
 #include <setjmp.h>
-
 #include "tree.h"
 #include "input.h"
 #include "c-lex.h"
 #include "c-tree.h"
 #include "flags.h"
 #include "output.h"
-
+#include "toplev.h"
+#include "ggc.h"
+  
 #ifdef MULTIBYTE_CHARS
 #include <locale.h>
 #endif
@@ -72,7 +51,7 @@ State 434 contains 2 shift/reduce conflicts.  (Four ways to parse this.)  */
 
 /* Since parsers are distinct for each language, put the language string
    definition here.  */
-char *language_string = "GNU C";
+const char * const language_string = "GNU C";
 
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
@@ -103,7 +82,7 @@ char *language_string = "GNU C";
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
 %token TYPESPEC
 
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
 %token TYPE_QUAL
 
@@ -123,7 +102,11 @@ char *language_string = "GNU C";
 %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
 %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
 %token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART
+%token REALPART IMAGPART VA_ARG
+%token PTR_VALUE PTR_BASE PTR_EXTENT
+
+/* Used in c-lex.c for parsing pragmas.  */
+%token END_OF_LINE
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc IF
@@ -173,9 +156,9 @@ char *language_string = "GNU C";
 %type <ttype> init maybeasm
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word
+%type <ttype> any_word extension
 
-%type <ttype> compstmt
+%type <ttype> compstmt compstmt_nostart compstmt_primary_start
 
 %type <ttype> declarator
 %type <ttype> notype_declarator after_type_declarator
@@ -184,6 +167,7 @@ char *language_string = "GNU C";
 %type <ttype> structsp component_decl_list component_decl_list2
 %type <ttype> component_decl components component_declarator
 %type <ttype> enumlist enumerator
+%type <ttype> struct_head union_head enum_head
 %type <ttype> typename absdcl absdcl1 type_quals
 %type <ttype> xexpr parms parm identifiers
 
@@ -220,11 +204,32 @@ static tree declspec_stack;
 /* 1 if we explained undeclared var errors.  */
 static int undeclared_variable_notice;
 
+/* For __extension__, save/restore the warning flags which are
+   controlled by __extension__.  */
+#define SAVE_WARN_FLAGS()      \
+       size_int (pedantic | (warn_pointer_arith << 1))
+#define RESTORE_WARN_FLAGS(tval) \
+  do {                                     \
+    int val = tree_low_cst (tval, 0);      \
+    pedantic = val & 1;                    \
+    warn_pointer_arith = (val >> 1) & 1;   \
+  } while (0)
+
 
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
 
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint                    PROTO ((FILE *, int, YYSTYPE));
+extern void yyprint                    PARAMS ((FILE *, int, YYSTYPE));
+
+/* Add GC roots for variables local to this file.  */
+void
+c_parse_init ()
+{
+  ggc_add_tree_root (&declspec_stack, 1);
+  ggc_add_tree_root (&current_declspecs, 1);
+  ggc_add_tree_root (&prefix_attributes, 1);
+}
+
 %}
 \f
 %%
@@ -264,7 +269,7 @@ extdef:
                  else
                    error ("argument of `asm' is not a constant string"); }
        | extension extdef
-               { pedantic = $<itype>1; }
+               { RESTORE_WARN_FLAGS ($1); }
        ;
 
 datadef:
@@ -276,18 +281,15 @@ datadef:
 
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($1); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
         | declmods setspecs notype_initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2);  }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
         | declmods ';'
          { pedwarn ("empty declaration"); }
        | typed_declspecs ';'
@@ -302,7 +304,7 @@ datadef:
 fndef:
          typed_declspecs setspecs declarator
                { if (! start_function (current_declspecs, $3,
-                                       prefix_attributes, NULL_TREE, 0))
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
                  reinit_parse_for_function (); }
          old_style_parm_decls
@@ -311,16 +313,14 @@ fndef:
                { finish_function (0); 
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs declarator error
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_declarator
                { if (! start_function (current_declspecs, $3,
-                                       prefix_attributes, NULL_TREE, 0))
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
                  reinit_parse_for_function (); }
          old_style_parm_decls
@@ -329,16 +329,14 @@ fndef:
                { finish_function (0); 
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_declarator error
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | setspecs notype_declarator
                { if (! start_function (NULL_TREE, $2,
-                                       prefix_attributes, NULL_TREE, 0))
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
                  reinit_parse_for_function (); }
          old_style_parm_decls
@@ -347,13 +345,11 @@ fndef:
                { finish_function (0); 
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($1); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | setspecs notype_declarator error
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($1); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        ;
 
 identifier:
@@ -401,7 +397,7 @@ unary_expr:
        /* __extension__ turns off -pedantic for following primary.  */
        | extension cast_expr     %prec UNARY
                { $$ = $2;
-                 pedantic = $<itype>1; }
+                 RESTORE_WARN_FLAGS ($1); }
        | unop cast_expr  %prec UNARY
                { $$ = build_unary_op ($1, $2, 0);
                  overflow_warning ($$); }
@@ -453,6 +449,8 @@ unary_expr:
                { $$ = build_unary_op (REALPART_EXPR, $2, 0); }
        | IMAGPART cast_expr %prec UNARY
                { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); }
+       | VA_ARG '(' expr_no_commas ',' typename ')'
+               { $$ = build_va_arg ($3, groktypename ($5)); }
        ;
 
 sizeof:
@@ -473,12 +471,12 @@ cast_expr:
                  $2 = groktypename ($2);
                  really_start_incremental_init ($2); }
          initlist_maybe_comma '}'  %prec UNARY
-               { char *name;
+               { const char *name;
                  tree result = pop_init_level (0);
                  tree type = $2;
                  finish_init ();
 
-                 if (pedantic)
+                 if (pedantic && ! flag_isoc99)
                    pedwarn ("ANSI C forbids constructor expressions");
                  if (TYPE_NAME (type) != 0)
                    {
@@ -490,7 +488,7 @@ cast_expr:
                  else
                    name = "";
                  $$ = result;
-                 if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
+                 if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
                    {
                      int failure = complete_array_type (type, $$, 1);
                      if (failure)
@@ -557,12 +555,22 @@ expr_no_commas:
                { skip_evaluation -= $1 == boolean_true_node;
                  $$ = build_conditional_expr ($1, $<ttype>2, $5); }
        | expr_no_commas '=' expr_no_commas
-               { $$ = build_modify_expr ($1, NOP_EXPR, $3);
-                 C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+               { char class;
+                 $$ = build_modify_expr ($1, NOP_EXPR, $3);
+                 class = TREE_CODE_CLASS (TREE_CODE ($$));
+                 if (class == 'e' || class == '1'
+                     || class == '2' || class == '<')
+                   C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
+               }
        | expr_no_commas ASSIGN expr_no_commas
-               { $$ = build_modify_expr ($1, $2, $3);
+               { char class;
+                 $$ = build_modify_expr ($1, $2, $3);
                  /* This inhibits warnings in truthvalue_conversion.  */
-                 C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+                 class = TREE_CODE_CLASS (TREE_CODE ($$));
+                 if (class == 'e' || class == '1'
+                     || class == '2' || class == '<')
+                   C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
+               }
        ;
 
 primary:
@@ -675,42 +683,37 @@ primary:
                  $$ = $2; }
        | '(' error ')'
                { $$ = error_mark_node; }
-       | '('
-               { if (current_function_decl == 0)
-                   {
-                     error ("braced-group within expression allowed only inside a function");
-                     YYERROR;
-                   }
-                 /* We must force a BLOCK for this level
-                    so that, if it is not expanded later,
-                    there is a way to turn off the entire subtree of blocks
-                    that are contained in it.  */
-                 keep_next_level ();
-                 push_iterator_stack ();
-                 push_label_level ();
-                 $<ttype>$ = expand_start_stmt_expr (); }
-         compstmt ')'
+       | compstmt_primary_start compstmt_nostart ')'
                { tree rtl_exp;
                  if (pedantic)
                    pedwarn ("ANSI C forbids braced-groups within expressions");
                  pop_iterator_stack ();
                  pop_label_level ();
-                 rtl_exp = expand_end_stmt_expr ($<ttype>2);
+                 rtl_exp = expand_end_stmt_expr ($1);
                  /* The statements have side effects, so the group does.  */
                  TREE_SIDE_EFFECTS (rtl_exp) = 1;
 
-                 if (TREE_CODE ($3) == BLOCK)
+                 if (TREE_CODE ($2) == BLOCK)
                    {
                      /* Make a BIND_EXPR for the BLOCK already made.  */
                      $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
-                                 NULL_TREE, rtl_exp, $3);
+                                 NULL_TREE, rtl_exp, $2);
                      /* Remove the block from the tree at this point.
                         It gets put back at the proper place
                         when the BIND_EXPR is expanded.  */
-                     delete_block ($3);
+                     delete_block ($2);
                    }
                  else
-                   $$ = $3;
+                   $$ = $2;
+               }
+       | compstmt_primary_start error ')'
+               {
+                 /* Make sure we call expand_end_stmt_expr.  Otherwise
+                    we are likely to lose sequences and crash later.  */
+                 pop_iterator_stack ();
+                 pop_label_level ();
+                 expand_end_stmt_expr ($1);
+                 $$ = error_mark_node;
                }
        | primary '(' exprlist ')'   %prec '.'
                { $$ = build_function_call ($1, $3); }
@@ -736,7 +739,10 @@ primary:
 string:
          STRING
        | string STRING
-               { $$ = chainon ($1, $2); }
+               { $$ = chainon ($1, $2);
+                 if (warn_traditional && !in_system_header)
+                   warning ("Use of ANSI string concatenation");
+               }
        ;
 
 
@@ -773,13 +779,11 @@ datadecl:
        typed_declspecs_no_prefix_attr setspecs initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods_no_prefix_attr setspecs notype_initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);      
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs_no_prefix_attr ';'
                { shadow_tag_warned ($1, 1);
                  pedwarn ("empty declaration"); }
@@ -808,8 +812,7 @@ decls:
    Maintains a stack of outer-level values of current_declspecs,
    for the sake of parm declarations nested in function declarators.  */
 setspecs: /* empty */
-               { $$ = suspend_momentary ();
-                 pending_xref_error ();
+               { pending_xref_error ();
                  declspec_stack = tree_cons (prefix_attributes,
                                              current_declspecs,
                                              declspec_stack);
@@ -826,29 +829,25 @@ decl:
        typed_declspecs setspecs initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs nested_function
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_nested_function
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs ';'
                { shadow_tag ($1); }
        | declmods ';'
                { pedwarn ("empty declaration"); }
        | extension decl
-               { pedantic = $<itype>1; }
+               { RESTORE_WARN_FLAGS ($1); }
        ;
 
 /* Declspecs which contain at least one type specifier or typedef name.
@@ -1075,18 +1074,9 @@ any_word:
 init:
        expr_no_commas
        | '{'
-               { really_start_incremental_init (NULL_TREE);
-                 /* Note that the call to clear_momentary
-                    is in process_init_element.  */
-                 push_momentary (); }
+               { really_start_incremental_init (NULL_TREE); }
          initlist_maybe_comma '}'
-               { $$ = pop_init_level (0);
-                 if ($$ == error_mark_node
-                     && ! (yychar == STRING || yychar == CONSTANT))
-                   pop_momentary ();
-                 else
-                   pop_momentary_nofree (); }
-
+               { $$ = pop_init_level (0); }
        | error
                { $$ = error_mark_node; }
        ;
@@ -1107,40 +1097,51 @@ initlist1:
 /* `initelt' is a single element of an initializer.
    It may use braces.  */
 initelt:
-       expr_no_commas
-               { process_init_element ($1); }
-       | '{' 
+         designator_list '=' initval
+       | designator initval
+       | identifier ':'
+               { set_init_label ($1); }
+         initval
+       | initval
+       ;
+
+initval:
+         '{'
                { push_init_level (0); }
          initlist_maybe_comma '}'
                { process_init_element (pop_init_level (0)); }
+       | expr_no_commas
+               { process_init_element ($1); }
        | error
+       ;
+
+designator_list:
+         designator
+       | designator_list designator
+       ;
+
+designator:
+         '.' identifier
+               { set_init_label ($2); }
        /* These are for labeled elements.  The syntax for an array element
           initializer conflicts with the syntax for an Objective-C message,
           so don't include these productions in the Objective-C grammar.  */
-       | '[' expr_no_commas ELLIPSIS expr_no_commas ']' '='
+       | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
                { set_init_index ($2, $4); }
-         initelt
-       | '[' expr_no_commas ']' '='
-               { set_init_index ($2, NULL_TREE); }
-         initelt
        | '[' expr_no_commas ']'
                { set_init_index ($2, NULL_TREE); }
-         initelt
-       | identifier ':'
-               { set_init_label ($1); }
-         initelt
-       | '.' identifier '='
-               { set_init_label ($2); }
-         initelt
        ;
 \f
 nested_function:
          declarator
-               { push_c_function_context ();
+               { if (pedantic)
+                   pedwarn ("ANSI C forbids nested functions");
+
+                 push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, NULL_TREE, 1))
+                                       prefix_attributes, NULL_TREE))
                    {
-                     pop_c_function_context ();
+                     pop_function_context ();
                      YYERROR1;
                    }
                  reinit_parse_for_function (); }
@@ -1154,16 +1155,19 @@ nested_function:
    which called YYERROR1 again, and so on.  */
          compstmt
                { finish_function (1);
-                 pop_c_function_context (); }
+                 pop_function_context (); }
        ;
 
 notype_nested_function:
          notype_declarator
-               { push_c_function_context ();
+               { if (pedantic)
+                   pedwarn ("ANSI C forbids nested functions");
+
+                 push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, NULL_TREE, 1))
+                                       prefix_attributes, NULL_TREE))
                    {
-                     pop_c_function_context ();
+                     pop_function_context ();
                      YYERROR1;
                    }
                  reinit_parse_for_function (); }
@@ -1177,7 +1181,7 @@ notype_nested_function:
    which called YYERROR1 again, and so on.  */
          compstmt
                { finish_function (1);
-                 pop_c_function_context (); }
+                 pop_function_context (); }
        ;
 
 /* Any kind of declarator (thus, all declarators allowed
@@ -1225,6 +1229,11 @@ parm_declarator:
 /*     | parm_declarator '(' error ')'  %prec '.'
                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                  poplevel (0, 0, 0); }  */
+       | parm_declarator '[' '*' ']'  %prec '.'
+               { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+                 if (! flag_isoc99)
+                   error ("`[*]' in parameter declaration only allowed in ISO C 99");
+               }
        | parm_declarator '[' expr ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, $3); }
        | parm_declarator '[' ']'  %prec '.'
@@ -1254,6 +1263,11 @@ notype_declarator:
                { $$ = $2; }
        | '*' type_quals notype_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
+       | notype_declarator '[' '*' ']'  %prec '.'
+               { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+                 if (! flag_isoc99)
+                   error ("`[*]' in parameter declaration only allowed in ISO C 99");
+               }
        | notype_declarator '[' expr ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, $3); }
        | notype_declarator '[' ']'  %prec '.'
@@ -1268,42 +1282,61 @@ notype_declarator:
        | IDENTIFIER
        ;
 
+struct_head:
+         STRUCT
+               { $$ = NULL_TREE; }
+       | STRUCT attributes
+               { $$ = $2; }
+       ;
+
+union_head:
+         UNION
+               { $$ = NULL_TREE; }
+       | UNION attributes
+               { $$ = $2; }
+       ;
+
+enum_head:
+         ENUM
+               { $$ = NULL_TREE; }
+       | ENUM attributes
+               { $$ = $2; }
+       ;
+
 structsp:
-         STRUCT identifier '{'
+         struct_head identifier '{'
                { $$ = start_struct (RECORD_TYPE, $2);
                  /* Start scope of tag before parsing components.  */
                }
          component_decl_list '}' maybe_attribute 
-               { $$ = finish_struct ($<ttype>4, $5, $7); }
-       | STRUCT '{' component_decl_list '}' maybe_attribute
+               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+       | struct_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
-                                     $3, $5);
+                                     $3, chainon ($1, $5));
                }
-       | STRUCT identifier
+       | struct_head identifier
                { $$ = xref_tag (RECORD_TYPE, $2); }
-       | UNION identifier '{'
+       | union_head identifier '{'
                { $$ = start_struct (UNION_TYPE, $2); }
          component_decl_list '}' maybe_attribute
-               { $$ = finish_struct ($<ttype>4, $5, $7); }
-       | UNION '{' component_decl_list '}' maybe_attribute
+               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+       | union_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
-                                     $3, $5);
+                                     $3, chainon ($1, $5));
                }
-       | UNION identifier
+       | union_head identifier
                { $$ = xref_tag (UNION_TYPE, $2); }
-       | ENUM identifier '{'
-               { $<itype>3 = suspend_momentary ();
-                 $$ = start_enum ($2); }
+       | enum_head identifier '{'
+               { $$ = start_enum ($2); }
          enumlist maybecomma_warn '}' maybe_attribute
-               { $$ = finish_enum ($<ttype>4, nreverse ($5), $8);
-                 resume_momentary ($<itype>3); }
-       | ENUM '{'
-               { $<itype>2 = suspend_momentary ();
-                 $$ = start_enum (NULL_TREE); }
+               { $$ = finish_enum ($<ttype>4, nreverse ($5),
+                                   chainon ($1, $8)); }
+       | enum_head '{'
+               { $$ = start_enum (NULL_TREE); }
          enumlist maybecomma_warn '}' maybe_attribute
-               { $$ = finish_enum ($<ttype>3, nreverse ($4), $7);
-                 resume_momentary ($<itype>2); }
-       | ENUM identifier
+               { $$ = finish_enum ($<ttype>3, nreverse ($4),
+                                   chainon ($1, $7)); }
+       | enum_head identifier
                { $$ = xref_tag (ENUMERAL_TYPE, $2); }
        ;
 
@@ -1315,7 +1348,8 @@ maybecomma:
 maybecomma_warn:
          /* empty */
        | ','
-               { if (pedantic) pedwarn ("comma at end of enumerator list"); }
+               { if (pedantic && ! flag_isoc99)
+                   pedwarn ("comma at end of enumerator list"); }
        ;
 
 component_decl_list:
@@ -1349,19 +1383,25 @@ component_decl:
                { $$ = $3;
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | typed_typespecs setspecs save_filename save_lineno maybe_attribute
+               {
+                 /* 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 ("ANSI C doesn't support unnamed structs/unions");
+
+                 $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
                  declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
-       | typed_typespecs
-               { if (pedantic)
-                   pedwarn ("ANSI C forbids member declarations with no members");
-                 shadow_tag($1);
-                 $$ = NULL_TREE; }
-       | nonempty_type_quals setspecs components
+               }
+    | nonempty_type_quals setspecs components
                { $$ = $3;
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | nonempty_type_quals
                { if (pedantic)
                    pedwarn ("ANSI C forbids member declarations with no members");
@@ -1371,7 +1411,7 @@ component_decl:
                { $$ = NULL_TREE; }
        | extension component_decl
                { $$ = $2;
-                 pedantic = $<itype>1; }
+                 RESTORE_WARN_FLAGS ($1); }
        ;
 
 components:
@@ -1466,6 +1506,8 @@ absdcl1:  /* a nonempty absolute declarator */
                { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
        /* ??? It appears we have to support attributes here, however
           using prefix_attributes is wrong.  */
+       | attributes setattrs absdcl1
+               { $$ = $3; }
        ;
 
 /* at least one statement, the first of which parses without error.  */
@@ -1500,7 +1542,6 @@ pushlevel:  /* empty */
                { emit_line_note (input_filename, lineno);
                  pushlevel (0);
                  clear_last_expr ();
-                 push_momentary ();
                  expand_start_bindings (0);
                }
        ;
@@ -1541,32 +1582,42 @@ compstmt_or_error:
 
 compstmt_start: '{' { compstmt_count++; }
 
-compstmt: compstmt_start '}'
+compstmt_nostart: '}'
                { $$ = convert (void_type_node, integer_zero_node); }
-       | compstmt_start pushlevel maybe_label_decls decls xstmts '}'
+       | pushlevel maybe_label_decls decls xstmts '}'
                { emit_line_note (input_filename, lineno);
                  expand_end_bindings (getdecls (), 1, 0);
-                 $$ = poplevel (1, 1, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
-       | compstmt_start pushlevel maybe_label_decls error '}'
+                 $$ = poplevel (1, 1, 0); }
+       | pushlevel maybe_label_decls error '}'
                { emit_line_note (input_filename, lineno);
                  expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
-       | compstmt_start pushlevel maybe_label_decls stmts '}'
+                 $$ = poplevel (kept_level_p (), 0, 0); }
+       | pushlevel maybe_label_decls stmts '}'
                { emit_line_note (input_filename, lineno);
                  expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
+                 $$ = poplevel (kept_level_p (), 0, 0); }
+       ;
+
+compstmt_primary_start:
+       '(' '{'
+               { if (current_function_decl == 0)
+                   {
+                     error ("braced-group within expression allowed only inside a function");
+                     YYERROR;
+                   }
+                 /* We must force a BLOCK for this level
+                    so that, if it is not expanded later,
+                    there is a way to turn off the entire subtree of blocks
+                    that are contained in it.  */
+                 keep_next_level ();
+                 push_iterator_stack ();
+                 push_label_level ();
+                 $$ = expand_start_stmt_expr ();
+                 compstmt_count++;
+               }
+
+compstmt: compstmt_start compstmt_nostart
+               { $$ = $2; }
        ;
 
 /* Value is number of statements counted as of the closeparen.  */
@@ -1655,8 +1706,7 @@ stmt:
                      || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
                    $1 = default_conversion ($1);
 #endif
-                 iterator_expand ($1);
-                 clear_momentary (); }
+                 iterator_expand ($1); }
        | simple_if ELSE
                { c_expand_start_else ();
                  $<itype>1 = stmt_count;
@@ -1705,12 +1755,10 @@ stmt:
                { emit_line_note (input_filename, lineno);
                  expand_exit_loop_if_false (NULL_PTR,
                                             truthvalue_conversion ($3));
-                 expand_end_loop ();
-                 clear_momentary (); }
+                 expand_end_loop (); }
 /* This rule is needed to make sure we end every loop we start.  */
        | do_stmt_start error
-               { expand_end_loop ();
-                 clear_momentary (); }
+               { expand_end_loop (); }
        | FOR
          '(' xexpr ';'
                { stmt_count++;
@@ -1737,9 +1785,6 @@ stmt:
                  if ($6)
                    expand_exit_loop_if_false (NULL_PTR,
                                               truthvalue_conversion ($6));
-                 /* Don't let the tree nodes for $9 be discarded by
-                    clear_momentary during the parsing of the next stmt.  */
-                 push_momentary ();
                  $<lineno>7 = lineno;
                  $<filename>8 = input_filename;
                  position_after_white_space (); }
@@ -1749,25 +1794,14 @@ stmt:
                  expand_loop_continue_here ();
                  if ($9)
                    c_expand_expr_stmt ($9);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary ();
                  expand_end_loop (); }
        | SWITCH '(' expr ')'
                { stmt_count++;
                  emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_start_case ($3);
-                 /* Don't let the tree nodes for $3 be discarded by
-                    clear_momentary during the parsing of the next stmt.  */
-                 push_momentary ();
                  position_after_white_space (); }
          lineno_labeled_stmt
-               { expand_end_case ($3);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
+               { expand_end_case ($3); }
        | BREAK ';'
                { stmt_count++;
                  emit_line_note ($<filename>-1, $<lineno>0);
@@ -1889,10 +1923,6 @@ all_iter_stmt_with_decl:
            emit_line_note (input_filename, lineno);
            expand_end_bindings (getdecls (), 1, 0);
            $<ttype>$ = poplevel (1, 1, 0);
-           if (yychar == CONSTANT || yychar == STRING)
-             pop_momentary_nofree ();
-           else
-             pop_momentary ();     
          }
 */
 
@@ -1977,12 +2007,15 @@ label:    CASE expr_no_commas ':'
                      error_with_decl (duplicate, "this is the first default label");
                    }
                  position_after_white_space (); }
-       | identifier ':'
+       | identifier ':' maybe_attribute
                { tree label = define_label (input_filename, lineno, $1);
                  stmt_count++;
                  emit_nop ();
                  if (label)
-                   expand_label (label);
+                   {
+                     expand_label (label);
+                     decl_attributes (label, $3, NULL_TREE);
+                   }
                  position_after_white_space (); }
        ;
 
@@ -2092,8 +2125,7 @@ parm:
                                                         $4));
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
@@ -2101,8 +2133,7 @@ parm:
                                                         $4)); 
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs absdcl maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
@@ -2110,8 +2141,7 @@ parm:
                                                         $4));
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
@@ -2119,8 +2149,7 @@ parm:
                                                         $4));
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2);  }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
 
        | declmods setspecs absdcl maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
@@ -2129,8 +2158,7 @@ parm:
                                                         $4));
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2);  }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        ;
 
 /* This is used in a function definition
@@ -2174,8 +2202,9 @@ identifiers_or_typenames:
 
 extension:
        EXTENSION
-               { $<itype>$ = pedantic;
-                 pedantic = 0; }
+               { $$ = SAVE_WARN_FLAGS();
+                 pedantic = 0;
+                 warn_pointer_arith = 0; }
        ;
 \f
 %%