OSDN Git Service

[gcc/ChangeLog]
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.in
index 11e0e44..d45ff5e 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 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -20,25 +20,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
 /* This file defines the grammar of C and that of Objective C.
-   ifobjc ... end ifobjc  conditionals contain code for Objective C only.
-   ifc ... end ifc  conditionals contain code for C only.
+   @@ifobjc ... @@end_ifobjc  conditionals contain code for Objective C only.
+   @@ifc ... @@end_ifc  conditionals contain code for C only.
    Sed commands in Makefile.in are used to convert this file into
    c-parse.y and into objc-parse.y.  */
 
 /* To whomever it may concern: I have heard that such a thing was once
    written by AT&T, but I have never seen it.  */
 
-ifobjc
-%expect 32 /* shift/reduce conflicts, and 1 reduce/reduce conflict.  */
-end ifobjc
-ifc
-%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts.  */
-end ifc
+@@ifc
+%expect 13 /* shift/reduce conflicts, and no reduce/reduce conflicts.  */
+@@end_ifc
 
 %{
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
+#include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
 #include "intl.h"
@@ -46,17 +46,14 @@ end ifc
 #include "c-pragma.h"          /* For YYDEBUG definition, and parse_in.  */
 #include "c-tree.h"
 #include "flags.h"
+#include "varray.h"
 #include "output.h"
 #include "toplev.h"
 #include "ggc.h"
 
-#ifdef MULTIBYTE_CHARS
-#include <locale.h>
-#endif
-
-ifobjc
+@@ifobjc
 #include "objc-act.h"
-end ifobjc
+@@end_ifobjc
 
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
@@ -79,15 +76,13 @@ do {                                                                        \
   newsize = *(YYSSZ) *= 2;                                             \
   if (malloced_yyss)                                                   \
     {                                                                  \
-      newss = (short *)                                                        \
-       really_call_realloc (*(SS), newsize * sizeof (short));          \
-      newvs = (YYSTYPE *)                                              \
-       really_call_realloc (*(VS), newsize * sizeof (YYSTYPE));        \
+      newss = really_call_realloc (*(SS), newsize * sizeof (short));   \
+      newvs = really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
     }                                                                  \
   else                                                                 \
     {                                                                  \
-      newss = (short *) really_call_malloc (newsize * sizeof (short)); \
-      newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+      newss = really_call_malloc (newsize * sizeof (short));           \
+      newvs = really_call_malloc (newsize * sizeof (YYSTYPE));         \
       if (newss)                                                       \
         memcpy (newss, *(SS), (SSSIZE));                               \
       if (newvs)                                                       \
@@ -107,8 +102,8 @@ do {                                                                        \
 
 %start program
 
-%union {long itype; tree ttype; enum tree_code code;
-       const char *filename; int lineno; }
+%union {long itype; tree ttype; struct c_expr exprtype; enum tree_code code;
+       location_t location; }
 
 /* All identifiers that are not reserved words
    and are not declared typedefs in the current block */
@@ -132,12 +127,17 @@ do {                                                                      \
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
 %token TYPE_QUAL
 
+/* Objective-C protocol qualifiers.  These acquire their magic powers
+   only in certain contexts.  */
+%token OBJC_TYPE_QUAL
+
 /* Character or numeric constants.
    yylval is the node for the constant.  */
 %token CONSTANT
 
 /* String constants in raw form.
    yylval is a STRING_CST node.  */
+
 %token STRING
 
 /* "...", used for functions with variable arglists.  */
@@ -150,9 +150,7 @@ do {                                                                        \
 %token ATTRIBUTE EXTENSION LABEL
 %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
 %token PTR_VALUE PTR_BASE PTR_EXTENT
-
-/* function name can be a string const or a var decl. */
-%token STRING_FUNC_NAME VAR_FUNC_NAME
+%token FUNC_NAME OFFSETOF
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc IF
@@ -180,15 +178,19 @@ do {                                                                      \
 
 /* The Objective-C keywords.  These are included in C and in
    Objective C, so that the token codes are the same in both.  */
-%token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE
-%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
+%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_THROW AT_TRY AT_CATCH AT_FINALLY AT_SYNCHRONIZED
+%token OBJC_STRING
 
 %type <code> unop
 %type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
 %type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
 
-%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
-%type <ttype> expr_no_commas cast_expr unary_expr primary STRING
+%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
@@ -203,18 +205,21 @@ do {                                                                      \
 %type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
 %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
 %type <ttype> typespec_nonreserved_nonattr
+%type <ttype> offsetof_member_designator
 
-%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
 %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
-%type <ttype> init maybeasm
+%type <exprtype> init
+%type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word extension
+%type <ttype> any_word
 
-%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
-%type <ttype> do_stmt_start poplevel stmt label
+%type <ttype> compstmt compstmt_start compstmt_primary_start
+%type <ttype> stmt label stmt_nocomp start_break start_continue
 
-%type <ttype> c99_block_start c99_block_end
+%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
@@ -229,18 +234,18 @@ do {                                                                      \
 %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 <ttype> xexpr parms parm firstparm identifiers
+%type <ttype> condition xexpr for_cond_expr for_incr_expr
+%type <ttype> parms parm firstparm identifiers
 
 %type <ttype> parmlist parmlist_1 parmlist_2
 %type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
 %type <ttype> identifiers_or_typenames
 
-%type <itype> setspecs setspecs_fp
+%type <itype> setspecs setspecs_fp extension
 
-%type <filename> save_filename
-%type <lineno> save_lineno
+%type <location> save_location
 \f
-ifobjc
+@@ifobjc
 /* the Objective-C nonterminals */
 
 %type <ttype> ivar_decl_list ivar_decls ivar_decl ivars ivar_declarator
@@ -249,22 +254,14 @@ ifobjc
 %type <ttype> keywordexpr keywordarglist keywordarg
 %type <ttype> myparms myparm optparmlist reservedwords objcselectorexpr
 %type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
-%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
+%type <ttype> non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
+
+%type <ttype> CLASSNAME OBJECTNAME OBJC_STRING
 
-%type <ttype> CLASSNAME OBJECTNAME
-end ifobjc
+%type <ttype> superclass
+@@end_ifobjc
 \f
 %{
-/* Number of statements (loosely speaking) and compound statements
-   seen so far.  */
-static int stmt_count;
-static int compstmt_count;
-
-/* Input file and line number of the end of the body of last simple_if;
-   used by the stmt-rule immediately after simple_if returns.  */
-static const char *if_stmt_file;
-static int if_stmt_line;
-
 /* List of types and structure classes of the current declaration.  */
 static GTY(()) tree current_declspecs;
 static GTY(()) tree prefix_attributes;
@@ -278,6 +275,9 @@ static GTY(()) tree all_prefix_attributes;
    all_prefix_attributes.  */
 static GTY(()) tree 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                                             \
@@ -298,22 +298,21 @@ static GTY(()) tree declspec_stack;
 
 /* For __extension__, save/restore the warning flags which are
    controlled by __extension__.  */
-#define SAVE_EXT_FLAGS()                       \
-       size_int (pedantic                      \
-                 | (warn_pointer_arith << 1)   \
-                 | (warn_traditional << 2)     \
-                 | (flag_iso << 3))
+#define SAVE_EXT_FLAGS()               \
+       (pedantic                       \
+        | (warn_pointer_arith << 1)    \
+        | (warn_traditional << 2)      \
+        | (flag_iso << 3))
 
-#define RESTORE_EXT_FLAGS(tval)                        \
+#define RESTORE_EXT_FLAGS(val)                 \
   do {                                         \
-    int val = tree_low_cst (tval, 0);          \
     pedantic = val & 1;                                \
     warn_pointer_arith = (val >> 1) & 1;       \
     warn_traditional = (val >> 2) & 1;         \
     flag_iso = (val >> 3) & 1;                 \
   } while (0)
 
-ifobjc
+@@ifobjc
 /* Objective-C specific parser/lexer information */
 
 static enum tree_code objc_inherit_code;
@@ -325,29 +324,26 @@ static int objc_pq_context = 0, objc_public_flag = 0;
    exists.  */
 static int objc_need_raw_identifier;
 #define OBJC_NEED_RAW_IDENTIFIER(VAL)  objc_need_raw_identifier = VAL
-end ifobjc
+@@end_ifobjc
 
-ifc
+@@ifc
 #define OBJC_NEED_RAW_IDENTIFIER(VAL)  /* nothing */
-end ifc
-
-static bool parsing_iso_function_signature;
+@@end_ifc
 
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
 
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
 
-static void yyprint      PARAMS ((FILE *, int, YYSTYPE));
-static void yyerror      PARAMS ((const char *));
-static int yylexname     PARAMS ((void));
-static int yylexstring   PARAMS ((void));
-static inline int _yylex  PARAMS ((void));
-static int  yylex        PARAMS ((void));
-static void init_reswords PARAMS ((void));
+static void yyprint (FILE *, int, YYSTYPE);
+static void yyerror (const char *);
+static int yylexname (void);
+static inline int _yylex (void);
+static int  yylex (void);
+static void init_reswords (void);
 
   /* Initialisation routine for this file.  */
 void
-c_parse_init ()
+c_parse_init (void)
 {
   init_reswords ();
 }
@@ -358,20 +354,8 @@ c_parse_init ()
 program: /* empty */
                { if (pedantic)
                    pedwarn ("ISO C forbids an empty source file");
-                 finish_file ();
                }
        | extdefs
-               {
-                 /* In case there were missing closebraces,
-                    get us back to the global binding level.  */
-                 while (! global_bindings_p ())
-                   poplevel (0, 0, 0);
-                 /* __FUNCTION__ is defined at file scope ("").  This
-                    call may not be necessary as my tests indicate it
-                    still works without it.  */
-                 finish_fname_decls ();
-                  finish_file ();
-               }
        ;
 
 /* the reason for the strange actions in this rule
@@ -384,26 +368,14 @@ extdefs:
        ;
 
 extdef:
-       extdef_1
-       { parsing_iso_function_signature = false; } /* Reset after any external definition.  */
-       ;
-
-extdef_1:
        fndef
        | datadef
-ifobjc
-       | objcdef
-end ifobjc
-       | ASM_KEYWORD '(' expr ')' ';'
-               { STRIP_NOPS ($3);
-                 if ((TREE_CODE ($3) == ADDR_EXPR
-                      && TREE_CODE (TREE_OPERAND ($3, 0)) == STRING_CST)
-                     || TREE_CODE ($3) == STRING_CST)
-                   assemble_asm ($3);
-                 else
-                   error ("argument of `asm' is not a constant string"); }
+       | asmdef
        | extension extdef
                { RESTORE_EXT_FLAGS ($1); }
+@@ifobjc
+       | objcdef
+@@end_ifobjc
        ;
 
 datadef:
@@ -433,12 +405,11 @@ fndef:
                                        all_prefix_attributes))
                    YYERROR1;
                }
-         old_style_parm_decls
-               { store_parm_decls (); }
-         save_filename save_lineno compstmt_or_error
-               { DECL_SOURCE_FILE (current_function_decl) = $7;
-                 DECL_SOURCE_LINE (current_function_decl) = $8;
-                 finish_function (0, 1);
+         old_style_parm_decls save_location
+               { DECL_SOURCE_LOCATION (current_function_decl) = $6;
+                 store_parm_decls (); }
+         compstmt_or_error
+               { finish_function ();
                  POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs declarator error
                { POP_DECLSPEC_STACK; }
@@ -447,12 +418,11 @@ fndef:
                                        all_prefix_attributes))
                    YYERROR1;
                }
-         old_style_parm_decls
-               { store_parm_decls (); }
-         save_filename save_lineno compstmt_or_error
-               { DECL_SOURCE_FILE (current_function_decl) = $7;
-                 DECL_SOURCE_LINE (current_function_decl) = $8;
-                 finish_function (0, 1);
+         old_style_parm_decls save_location
+               { DECL_SOURCE_LOCATION (current_function_decl) = $6;
+                 store_parm_decls (); }
+         compstmt_or_error
+               { finish_function ();
                  POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator error
                { POP_DECLSPEC_STACK; }
@@ -461,12 +431,11 @@ fndef:
                                        all_prefix_attributes))
                    YYERROR1;
                }
-         old_style_parm_decls
-               { store_parm_decls (); }
-         save_filename save_lineno compstmt_or_error
-               { DECL_SOURCE_FILE (current_function_decl) = $6;
-                 DECL_SOURCE_LINE (current_function_decl) = $7;
-                 finish_function (0, 1);
+         old_style_parm_decls save_location
+               { DECL_SOURCE_LOCATION (current_function_decl) = $5;
+                 store_parm_decls (); }
+         compstmt_or_error
+               { finish_function ();
                  POP_DECLSPEC_STACK; }
        | setspecs notype_declarator error
                { POP_DECLSPEC_STACK; }
@@ -475,10 +444,10 @@ fndef:
 identifier:
        IDENTIFIER
        | TYPENAME
-ifobjc
+@@ifobjc
        | OBJECTNAME
        | CLASSNAME
-end ifobjc
+@@end_ifobjc
        ;
 
 unop:     '&'
@@ -487,10 +456,10 @@ unop:     '&'
                { $$ = NEGATE_EXPR; }
        | '+'
                { $$ = CONVERT_EXPR;
-ifc
+@@ifc
   if (warn_traditional && !in_system_header)
     warning ("traditional C rejects the unary plus operator");
-end ifc
+@@end_ifc
                }
        | PLUSPLUS
                { $$ = PREINCREMENT_EXPR; }
@@ -502,8 +471,10 @@ end ifc
                { $$ = TRUTH_NOT_EXPR; }
        ;
 
-expr:  nonnull_exprlist
-               { $$ = build_compound_expr ($1); }
+expr:  expr_no_commas
+       | expr ',' expr_no_commas
+               { $$.value = build_compound_expr ($1.value, $3.value);
+                 $$.original_code = COMPOUND_EXPR; }
        ;
 
 exprlist:
@@ -514,44 +485,53 @@ exprlist:
 
 nonnull_exprlist:
        expr_no_commas
-               { $$ = build_tree_list (NULL_TREE, $1); }
+               { $$ = build_tree_list (NULL_TREE, $1.value); }
        | nonnull_exprlist ',' expr_no_commas
-               { chainon ($1, build_tree_list (NULL_TREE, $3)); }
+               { chainon ($1, build_tree_list (NULL_TREE, $3.value)); }
        ;
 
 unary_expr:
        primary
        | '*' cast_expr   %prec UNARY
-               { $$ = build_indirect_ref ($2, "unary *"); }
+               { $$.value = build_indirect_ref ($2.value, "unary *");
+                 $$.original_code = ERROR_MARK; }
        /* __extension__ turns off -pedantic for following primary.  */
        | extension cast_expr     %prec UNARY
                { $$ = $2;
                  RESTORE_EXT_FLAGS ($1); }
        | unop cast_expr  %prec UNARY
-               { $$ = build_unary_op ($1, $2, 0);
-                 overflow_warning ($$); }
+               { $$.value = build_unary_op ($1, $2.value, 0);
+                 overflow_warning ($$.value);
+                 $$.original_code = ERROR_MARK; }
        /* Refer to the address of a label as a pointer.  */
        | ANDAND identifier
-               { $$ = finish_label_address_expr ($2); }
+               { $$.value = finish_label_address_expr ($2);
+                 $$.original_code = ERROR_MARK; }
        | sizeof unary_expr  %prec UNARY
                { skip_evaluation--;
-                 if (TREE_CODE ($2) == COMPONENT_REF
-                     && DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1)))
+                 if (TREE_CODE ($2.value) == COMPONENT_REF
+                     && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
                    error ("`sizeof' applied to a bit-field");
-                 $$ = c_sizeof (TREE_TYPE ($2)); }
+                 $$.value = c_sizeof (TREE_TYPE ($2.value));
+                 $$.original_code = ERROR_MARK; }
        | sizeof '(' typename ')'  %prec HYPERUNARY
                { skip_evaluation--;
-                 $$ = c_sizeof (groktypename ($3)); }
+                 $$.value = c_sizeof (groktypename ($3));
+                 $$.original_code = ERROR_MARK; }
        | alignof unary_expr  %prec UNARY
                { skip_evaluation--;
-                 $$ = c_alignof_expr ($2); }
+                 $$.value = c_alignof_expr ($2.value);
+                 $$.original_code = ERROR_MARK; }
        | alignof '(' typename ')'  %prec HYPERUNARY
                { skip_evaluation--;
-                 $$ = c_alignof (groktypename ($3)); }
+                 $$.value = c_alignof (groktypename ($3));
+                 $$.original_code = ERROR_MARK; }
        | REALPART cast_expr %prec UNARY
-               { $$ = build_unary_op (REALPART_EXPR, $2, 0); }
+               { $$.value = build_unary_op (REALPART_EXPR, $2.value, 0);
+                 $$.original_code = ERROR_MARK; }
        | IMAGPART cast_expr %prec UNARY
-               { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); }
+               { $$.value = build_unary_op (IMAGPART_EXPR, $2.value, 0);
+                 $$.original_code = ERROR_MARK; }
        ;
 
 sizeof:
@@ -562,10 +542,15 @@ alignof:
        ALIGNOF { skip_evaluation++; }
        ;
 
+typeof:
+       TYPEOF { skip_evaluation++; }
+       ;
+
 cast_expr:
        unary_expr
        | '(' typename ')' cast_expr  %prec UNARY
-               { $$ = c_cast_expr ($2, $4); }
+               { $$.value = c_cast_expr ($2, $4.value);
+                 $$.original_code = ERROR_MARK; }
        ;
 
 expr_no_commas:
@@ -595,55 +580,51 @@ expr_no_commas:
        | expr_no_commas '^' expr_no_commas
                { $$ = parser_build_binary_op ($2, $1, $3); }
        | expr_no_commas ANDAND
-               { $1 = c_common_truthvalue_conversion
-                   (default_conversion ($1));
-                 skip_evaluation += $1 == boolean_false_node; }
+               { $1.value = lang_hooks.truthvalue_conversion
+                   (default_conversion ($1.value));
+                 skip_evaluation += $1.value == truthvalue_false_node; }
          expr_no_commas
-               { skip_evaluation -= $1 == boolean_false_node;
+               { skip_evaluation -= $1.value == truthvalue_false_node;
                  $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
        | expr_no_commas OROR
-               { $1 = c_common_truthvalue_conversion
-                   (default_conversion ($1));
-                 skip_evaluation += $1 == boolean_true_node; }
+               { $1.value = lang_hooks.truthvalue_conversion
+                   (default_conversion ($1.value));
+                 skip_evaluation += $1.value == truthvalue_true_node; }
          expr_no_commas
-               { skip_evaluation -= $1 == boolean_true_node;
+               { skip_evaluation -= $1.value == truthvalue_true_node;
                  $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
        | expr_no_commas '?'
-               { $1 = c_common_truthvalue_conversion
-                   (default_conversion ($1));
-                 skip_evaluation += $1 == boolean_false_node; }
+               { $1.value = lang_hooks.truthvalue_conversion
+                   (default_conversion ($1.value));
+                 skip_evaluation += $1.value == truthvalue_false_node; }
           expr ':'
-               { skip_evaluation += (($1 == boolean_true_node)
-                                     - ($1 == boolean_false_node)); }
+               { skip_evaluation += (($1.value == truthvalue_true_node)
+                                     - ($1.value == truthvalue_false_node)); }
          expr_no_commas
-               { skip_evaluation -= $1 == boolean_true_node;
-                 $$ = build_conditional_expr ($1, $4, $7); }
+               { skip_evaluation -= $1.value == truthvalue_true_node;
+                 $$.value = build_conditional_expr ($1.value, $4.value,
+                                                    $7.value);
+                 $$.original_code = ERROR_MARK; }
        | expr_no_commas '?'
                { if (pedantic)
                    pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
                  /* Make sure first operand is calculated only once.  */
-                 $<ttype>2 = save_expr ($1);
-                 $1 = c_common_truthvalue_conversion
-                   (default_conversion ($<ttype>2));
-                 skip_evaluation += $1 == boolean_true_node; }
+                 $<ttype>2 = save_expr (default_conversion ($1.value));
+                 $1.value = lang_hooks.truthvalue_conversion ($<ttype>2);
+                 skip_evaluation += $1.value == truthvalue_true_node; }
          ':' expr_no_commas
-               { skip_evaluation -= $1 == boolean_true_node;
-                 $$ = build_conditional_expr ($1, $<ttype>2, $5); }
+               { skip_evaluation -= $1.value == truthvalue_true_node;
+                 $$.value = build_conditional_expr ($1.value, $<ttype>2,
+                                                    $5.value);
+                 $$.original_code = ERROR_MARK; }
        | expr_no_commas '=' expr_no_commas
-               { char class;
-                 $$ = build_modify_expr ($1, NOP_EXPR, $3);
-                 class = TREE_CODE_CLASS (TREE_CODE ($$));
-                 if (IS_EXPR_CODE_CLASS (class))
-                   C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
+               { $$.value = build_modify_expr ($1.value, NOP_EXPR, $3.value);
+                 $$.original_code = MODIFY_EXPR;
                }
        | expr_no_commas ASSIGN expr_no_commas
-               { char class;
-                 $$ = build_modify_expr ($1, $2, $3);
-                 /* This inhibits warnings in
-                    c_common_truthvalue_conversion.  */
-                 class = TREE_CODE_CLASS (TREE_CODE ($$));
-                 if (IS_EXPR_CODE_CLASS (class))
-                   C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
+               { $$.value = build_modify_expr ($1.value, $2, $3.value);
+                 TREE_NO_WARNING ($$.value) = 1;
+                 $$.original_code = ERROR_MARK;
                }
        ;
 
@@ -652,147 +633,149 @@ primary:
                {
                  if (yychar == YYEMPTY)
                    yychar = YYLEX;
-                 $$ = build_external_ref ($1, yychar == '(');
+                 $$.value = build_external_ref ($1, yychar == '(');
+                 $$.original_code = ERROR_MARK;
                }
        | CONSTANT
+               { $$.value = $1; $$.original_code = ERROR_MARK; }
        | STRING
-               { $$ = fix_string_type ($$); }
-       | VAR_FUNC_NAME
-               { $$ = fname_decl (C_RID_CODE ($$), $$); }
+               { $$.value = $1; $$.original_code = STRING_CST; }
+       | FUNC_NAME
+               { $$.value = fname_decl (C_RID_CODE ($1), $1);
+                 $$.original_code = ERROR_MARK; }
        | '(' typename ')' '{'
                { start_init (NULL_TREE, NULL, 0);
                  $2 = groktypename ($2);
                  really_start_incremental_init ($2); }
          initlist_maybe_comma '}'  %prec UNARY
-               { tree constructor = pop_init_level (0);
+               { struct c_expr init = pop_init_level (0);
+                 tree constructor = init.value;
                  tree type = $2;
                  finish_init ();
+                 maybe_warn_string_init (type, init);
 
                  if (pedantic && ! flag_isoc99)
-                   pedwarn ("ISO C89 forbids compound literals");
-                 $$ = build_compound_literal (type, constructor);
+                   pedwarn ("ISO C90 forbids compound literals");
+                 $$.value = build_compound_literal (type, constructor);
+                 $$.original_code = ERROR_MARK;
                }
        | '(' expr ')'
-               { char class = TREE_CODE_CLASS (TREE_CODE ($2));
-                 if (IS_EXPR_CODE_CLASS (class))
-                   C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
-                 $$ = $2; }
+               { $$.value = $2.value;
+                 if (TREE_CODE ($$.value) == MODIFY_EXPR)
+                   TREE_NO_WARNING ($$.value) = 1;
+                 $$.original_code = ERROR_MARK; }
        | '(' error ')'
-               { $$ = error_mark_node; }
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
        | compstmt_primary_start compstmt_nostart ')'
-                 { tree saved_last_tree;
-
-                  if (pedantic)
-                    pedwarn ("ISO C forbids braced-groups within expressions");
-                 pop_label_level ();
-
-                 saved_last_tree = COMPOUND_BODY ($1);
-                 RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
-                 last_tree = saved_last_tree;
-                 TREE_CHAIN (last_tree) = NULL_TREE;
-                 if (!last_expr_type)
-                   last_expr_type = void_type_node;
-                 $$ = build1 (STMT_EXPR, last_expr_type, $1);
-                 TREE_SIDE_EFFECTS ($$) = 1;
+                { if (pedantic)
+                   pedwarn ("ISO C forbids braced-groups within expressions");
+                 $$.value = c_finish_stmt_expr ($1);
+                 $$.original_code = ERROR_MARK;
                }
        | compstmt_primary_start error ')'
-               {
-                 pop_label_level ();
-                 last_tree = COMPOUND_BODY ($1);
-                 TREE_CHAIN (last_tree) = NULL_TREE;
-                 $$ = error_mark_node;
+               { c_finish_stmt_expr ($1);
+                 $$.value = error_mark_node;
+                 $$.original_code = ERROR_MARK;
                }
        | primary '(' exprlist ')'   %prec '.'
-               { $$ = build_function_call ($1, $3); }
+               { $$.value = build_function_call ($1.value, $3);
+                 $$.original_code = ERROR_MARK; }
        | VA_ARG '(' expr_no_commas ',' typename ')'
-               { $$ = build_va_arg ($3, groktypename ($5)); }
+               { $$.value = build_va_arg ($3.value, groktypename ($5));
+                 $$.original_code = ERROR_MARK; }
 
-      | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')'
+       | OFFSETOF '(' typename ','
+               { tree type = groktypename ($3);
+                 if (type == error_mark_node)
+                   offsetof_base = error_mark_node;
+                 else
+                   offsetof_base = build1 (INDIRECT_REF, type, NULL);
+               }
+         offsetof_member_designator ')'
+               { $$.value = fold_offsetof ($6);
+                 $$.original_code = ERROR_MARK; }
+       | OFFSETOF '(' error ')'
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
+       | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
+                         expr_no_commas ')'
                {
                   tree c;
 
-                  c = fold ($3);
+                  c = fold ($3.value);
                   STRIP_NOPS (c);
                   if (TREE_CODE (c) != INTEGER_CST)
-                    error ("first argument to __builtin_choose_expr not a constant");
+                    error ("first argument to __builtin_choose_expr not"
+                          " a constant");
                   $$ = integer_zerop (c) ? $7 : $5;
                }
-      | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
+       | CHOOSE_EXPR '(' error ')'
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
+       | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
                {
                  tree e1, e2;
 
                  e1 = TYPE_MAIN_VARIANT (groktypename ($3));
                  e2 = TYPE_MAIN_VARIANT (groktypename ($5));
 
-                 $$ = comptypes (e1, e2)
-                   ? build_int_2 (1, 0) : build_int_2 (0, 0);
+                 $$.value = comptypes (e1, e2)
+                   ? build_int_cst (NULL_TREE, 1)
+                   : build_int_cst (NULL_TREE, 0);
+                 $$.original_code = ERROR_MARK;
                }
+       | TYPES_COMPATIBLE_P '(' error ')'
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
        | primary '[' expr ']'   %prec '.'
-               { $$ = build_array_ref ($1, $3); }
+               { $$.value = build_array_ref ($1.value, $3.value);
+                 $$.original_code = ERROR_MARK; }
        | primary '.' identifier
-               {
-ifobjc
-                   if (!is_public ($1, $3))
-                     $$ = error_mark_node;
-                   else
-end ifobjc
-                     $$ = build_component_ref ($1, $3);
-               }
+               { $$.value = build_component_ref ($1.value, $3);
+                 $$.original_code = ERROR_MARK; }
        | primary POINTSAT identifier
                {
-                  tree expr = build_indirect_ref ($1, "->");
-
-ifobjc
-                     if (!is_public (expr, $3))
-                       $$ = error_mark_node;
-                     else
-end ifobjc
-                       $$ = build_component_ref (expr, $3);
+                  tree expr = build_indirect_ref ($1.value, "->");
+                 $$.value = build_component_ref (expr, $3);
+                 $$.original_code = ERROR_MARK;
                }
        | primary PLUSPLUS
-               { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
+               { $$.value = build_unary_op (POSTINCREMENT_EXPR, $1.value, 0);
+                 $$.original_code = ERROR_MARK; }
        | primary MINUSMINUS
-               { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
-ifobjc
+               { $$.value = build_unary_op (POSTDECREMENT_EXPR, $1.value, 0);
+                 $$.original_code = ERROR_MARK; }
+@@ifobjc
        | objcmessageexpr
-               { $$ = build_message_expr ($1); }
+               { $$.value = objc_build_message_expr ($1);
+                 $$.original_code = ERROR_MARK; }
        | objcselectorexpr
-               { $$ = build_selector_expr ($1); }
+               { $$.value = objc_build_selector_expr ($1);
+                 $$.original_code = ERROR_MARK; }
        | objcprotocolexpr
-               { $$ = build_protocol_expr ($1); }
+               { $$.value = objc_build_protocol_expr ($1);
+                 $$.original_code = ERROR_MARK; }
        | objcencodeexpr
-               { $$ = build_encode_expr ($1); }
-       | objc_string
-               { $$ = build_objc_string_object ($1); }
-end ifobjc
+               { $$.value = objc_build_encode_expr ($1);
+                 $$.original_code = ERROR_MARK; }
+       | OBJC_STRING
+               { $$.value = objc_build_string_object ($1);
+                 $$.original_code = ERROR_MARK; }
+@@end_ifobjc
        ;
 
-ifobjc
-/* Produces an STRING_CST with perhaps more STRING_CSTs chained
-   onto it, which is to be read as an ObjC string object.  */
-objc_string:
-         '@' STRING
-               { $$ = $2; }
-       | objc_string '@' STRING
-               { $$ = chainon ($1, $3); }
-       ;
-end ifobjc
+/* This is the second argument to __builtin_offsetof.  We must have one
+   identifier, and beyond that we want to accept sub structure and sub
+   array references.  */
 
-old_style_parm_decls:
-       old_style_parm_decls_1
-       {
-         parsing_iso_function_signature = false; /* Reset after decls.  */
-       }
+offsetof_member_designator:
+         identifier
+               { $$ = build_component_ref (offsetof_base, $1); }
+       | offsetof_member_designator '.' identifier
+               { $$ = build_component_ref ($1, $3); }
+       | offsetof_member_designator '[' expr ']'
+               { $$ = build_array_ref ($1, $3.value); }
        ;
 
-old_style_parm_decls_1:
+old_style_parm_decls:
        /* empty */
-       {
-         if (warn_traditional && !in_system_header
-             && parsing_iso_function_signature)
-           warning ("traditional C rejects ISO C style function definitions");
-         parsing_iso_function_signature = false; /* Reset after warning.  */
-       }
        | datadecls
        ;
 
@@ -800,7 +783,7 @@ old_style_parm_decls_1:
    except that they do not allow nested functions.
    They are used for old-style parm decls.  */
 lineno_datadecl:
-         save_filename save_lineno datadecl
+         save_location datadecl
                { }
        ;
 
@@ -832,7 +815,7 @@ datadecl:
    This is to avoid shift/reduce conflicts in contexts
    where statement labels are allowed.  */
 lineno_decl:
-         save_filename save_lineno decl
+         save_location decl
                { }
        ;
 
@@ -1383,21 +1366,25 @@ typespec_nonreserved_nonattr:
                { /* For a typedef name, record the meaning, not the name.
                     In case of `foo foo, bar;'.  */
                  $$ = lookup_name ($1); }
-ifobjc
+@@ifobjc
        | CLASSNAME protocolrefs
                { $$ = get_static_reference ($1, $2); }
        | OBJECTNAME protocolrefs
-               { $$ = get_object_reference ($2); }
+               { $$ = get_protocol_reference ($2); }
 
 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
    - nisse@lysator.liu.se */
         | non_empty_protocolrefs
-                { $$ = get_object_reference ($1); }
-end ifobjc
-       | TYPEOF '(' expr ')'
-               { $$ = TREE_TYPE ($3); }
-       | TYPEOF '(' typename ')'
-               { $$ = groktypename ($3); }
+                { $$ = get_protocol_reference ($1); }
+@@end_ifobjc
+       | typeof '(' expr ')'
+               { skip_evaluation--;
+                 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); }
+       | typeof '(' typename ')'
+               { skip_evaluation--; $$ = groktypename ($3); }
        ;
 
 /* typespec_nonreserved_attr does not exist.  */
@@ -1412,24 +1399,18 @@ notype_initdecls:
        | notype_initdecls ',' maybe_resetattrs notype_initdcl
        ;
 
-maybeasm:
-         /* empty */
-               { $$ = NULL_TREE; }
-       | ASM_KEYWORD '(' STRING ')'
-               { $$ = $3; }
-       ;
-
 initdcl:
          declarator maybeasm maybe_attribute '='
-               { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+               { $<ttype>$ = start_decl ($1, current_declspecs, true,
                                          chainon ($3, all_prefix_attributes));
                  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 ();
-                 finish_decl ($<ttype>5, $6, $2); }
+                 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, 0,
+               { tree d = start_decl ($1, current_declspecs, false,
                                       chainon ($3, all_prefix_attributes));
                  finish_decl (d, NULL_TREE, $2);
                 }
@@ -1437,15 +1418,16 @@ initdcl:
 
 notype_initdcl:
          notype_declarator maybeasm maybe_attribute '='
-               { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+               { $<ttype>$ = start_decl ($1, current_declspecs, true,
                                          chainon ($3, all_prefix_attributes));
                  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 ();
-                 finish_decl ($<ttype>5, $6, $2); }
+                 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, 0,
+               { tree d = start_decl ($1, current_declspecs, false,
                                       chainon ($3, all_prefix_attributes));
                  finish_decl (d, NULL_TREE, $2); }
        ;
@@ -1453,7 +1435,7 @@ notype_initdcl:
    so that the header files compile. */
 maybe_attribute:
       /* empty */
-               { $$ = NULL_TREE; }
+               { $$ = NULL_TREE; }
        | attributes
                { $$ = $1; }
        ;
@@ -1466,8 +1448,11 @@ attributes:
        ;
 
 attribute:
-      ATTRIBUTE '(' '(' attribute_list ')' ')'
-               { $$ = $4; }
+      ATTRIBUTE stop_string_translation
+                '(' '(' attribute_list ')' ')' start_string_translation
+               { $$ = $5; }
+      | ATTRIBUTE error start_string_translation
+                {}
        ;
 
 attribute_list:
@@ -1509,12 +1494,13 @@ scspec:
 
 init:
        expr_no_commas
+               { $$ = $1; }
        | '{'
                { really_start_incremental_init (NULL_TREE); }
          initlist_maybe_comma '}'
                { $$ = pop_init_level (0); }
        | error
-               { $$ = error_mark_node; }
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
        ;
 
 /* `initlist_maybe_comma' is the guts of an initializer in braces.  */
@@ -1535,7 +1521,7 @@ initlist1:
 initelt:
          designator_list '=' initval
                { if (pedantic && ! flag_isoc99)
-                   pedwarn ("ISO C89 forbids specifying subobject to initialize"); }
+                   pedwarn ("ISO C90 forbids specifying subobject to initialize"); }
        | designator initval
                { if (pedantic)
                    pedwarn ("obsolete use of designated initializer without `='"); }
@@ -1567,15 +1553,15 @@ designator:
          '.' identifier
                { set_init_label ($2); }
        | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
-               { set_init_index ($2, $4);
+               { set_init_index ($2.value, $4.value);
                  if (pedantic)
                    pedwarn ("ISO C forbids specifying range of elements to initialize"); }
        | '[' expr_no_commas ']'
-               { set_init_index ($2, NULL_TREE); }
+               { set_init_index ($2.value, NULL_TREE); }
        ;
 \f
 nested_function:
-         declarator
+       declarator
                { if (pedantic)
                    pedwarn ("ISO C forbids nested functions");
 
@@ -1586,27 +1572,26 @@ nested_function:
                      pop_function_context ();
                      YYERROR1;
                    }
-                 parsing_iso_function_signature = false; /* Don't warn about nested functions.  */
-               }
-          old_style_parm_decls
-               { store_parm_decls (); }
-/* This used to use compstmt_or_error.
-   That caused a bug with input `f(g) int g {}',
-   where the use of YYERROR1 above caused an error
-   which then was handled by compstmt_or_error.
-   There followed a repeated execution of that same rule,
-   which called YYERROR1 again, and so on.  */
-         save_filename save_lineno compstmt
+               }
+       old_style_parm_decls save_location
                { tree decl = current_function_decl;
-                 DECL_SOURCE_FILE (decl) = $5;
-                 DECL_SOURCE_LINE (decl) = $6;
-                 finish_function (1, 1);
+                 DECL_SOURCE_LOCATION (decl) = $4;
+                 store_parm_decls (); }
+       /* This used to use compstmt_or_error.  That caused a bug with
+          input `f(g) int g {}', where the use of YYERROR1 above caused
+          an error which then was handled by compstmt_or_error.  There
+          followed a repeated execution of that same rule, which called
+          YYERROR1 again, and so on.  */
+       compstmt
+               { tree decl = current_function_decl;
+                 add_stmt ($6);
+                 finish_function ();
                  pop_function_context ();
-                 add_decl_stmt (decl); }
+                 add_stmt (build_stmt (DECL_EXPR, decl)); }
        ;
 
 notype_nested_function:
-         notype_declarator
+       notype_declarator
                { if (pedantic)
                    pedwarn ("ISO C forbids nested functions");
 
@@ -1617,23 +1602,22 @@ notype_nested_function:
                      pop_function_context ();
                      YYERROR1;
                    }
-                 parsing_iso_function_signature = false; /* Don't warn about nested functions.  */
-               }
-         old_style_parm_decls
-               { store_parm_decls (); }
-/* This used to use compstmt_or_error.
-   That caused a bug with input `f(g) int g {}',
-   where the use of YYERROR1 above caused an error
-   which then was handled by compstmt_or_error.
-   There followed a repeated execution of that same rule,
-   which called YYERROR1 again, and so on.  */
-         save_filename save_lineno compstmt
+               }
+       old_style_parm_decls save_location
                { tree decl = current_function_decl;
-                 DECL_SOURCE_FILE (decl) = $5;
-                 DECL_SOURCE_LINE (decl) = $6;
-                 finish_function (1, 1);
+                 DECL_SOURCE_LOCATION (decl) = $4;
+                 store_parm_decls (); }
+       /* This used to use compstmt_or_error.  That caused a bug with
+          input `f(g) int g {}', where the use of YYERROR1 above caused
+          an error which then was handled by compstmt_or_error.  There
+          followed a repeated execution of that same rule, which called
+          YYERROR1 again, and so on.  */
+       compstmt
+               { tree decl = current_function_decl;
+                 add_stmt ($6);
+                 finish_function ();
                  pop_function_context ();
-                 add_decl_stmt (decl); }
+                 add_stmt (build_stmt (DECL_EXPR, decl)); }
        ;
 
 /* Any kind of declarator (thus, all declarators allowed
@@ -1648,20 +1632,17 @@ declarator:
 
 after_type_declarator:
          '(' maybe_attribute after_type_declarator ')'
-               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
+               { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
        | after_type_declarator '(' parmlist_or_identifiers  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/*     | after_type_declarator '(' error ')'  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
-                 poplevel (0, 0, 0); }  */
+               { $$ = build_function_declarator ($3, $1); }
        | after_type_declarator array_declarator  %prec '.'
-               { $$ = set_array_declarator_type ($2, $1, 0); }
+               { $$ = set_array_declarator_inner ($2, $1, false); }
        | '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | TYPENAME
-ifobjc
+@@ifobjc
        | OBJECTNAME
-end ifobjc
+@@end_ifobjc
        ;
 
 /* Kinds of declarator that can appear in a parameter list
@@ -1675,32 +1656,26 @@ parm_declarator:
 
 parm_declarator_starttypename:
          parm_declarator_starttypename '(' parmlist_or_identifiers  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/*     | parm_declarator_starttypename '(' error ')'  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
-                 poplevel (0, 0, 0); }  */
+               { $$ = build_function_declarator ($3, $1); }
        | parm_declarator_starttypename array_declarator  %prec '.'
-               { $$ = set_array_declarator_type ($2, $1, 0); }
+               { $$ = set_array_declarator_inner ($2, $1, false); }
        | TYPENAME
-ifobjc
+@@ifobjc
        | OBJECTNAME
-end ifobjc
+@@end_ifobjc
        ;
 
 parm_declarator_nostarttypename:
          parm_declarator_nostarttypename '(' parmlist_or_identifiers  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/*     | parm_declarator_nostarttypename '(' error ')'  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
-                 poplevel (0, 0, 0); }  */
+               { $$ = build_function_declarator ($3, $1); }
        | parm_declarator_nostarttypename array_declarator  %prec '.'
-               { $$ = set_array_declarator_type ($2, $1, 0); }
+               { $$ = set_array_declarator_inner ($2, $1, false); }
        | '*' maybe_type_quals_attrs parm_declarator_starttypename  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | '*' maybe_type_quals_attrs parm_declarator_nostarttypename  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | '(' maybe_attribute parm_declarator_nostarttypename ')'
-               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
+               { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
        ;
 
 /* A declarator allowed whether or not there has been
@@ -1708,16 +1683,13 @@ parm_declarator_nostarttypename:
 
 notype_declarator:
          notype_declarator '(' parmlist_or_identifiers  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/*     | notype_declarator '(' error ')'  %prec '.'
-               { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
-                 poplevel (0, 0, 0); }  */
+               { $$ = build_function_declarator ($3, $1); }
        | '(' maybe_attribute notype_declarator ')'
-               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
+               { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
        | '*' maybe_type_quals_attrs notype_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | notype_declarator array_declarator  %prec '.'
-               { $$ = set_array_declarator_type ($2, $1, 0); }
+               { $$ = set_array_declarator_inner ($2, $1, false); }
        | IDENTIFIER
        ;
 
@@ -1754,18 +1726,20 @@ structsp_attr:
                  /* Start scope of tag before parsing components.  */
                }
          component_decl_list '}' maybe_attribute
-               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+               { $$ = finish_struct ($<ttype>4, nreverse ($5),
+                                     chainon ($1, $7)); }
        | struct_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
-                                     $3, chainon ($1, $5));
+                                     nreverse ($3), chainon ($1, $5));
                }
        | union_head identifier '{'
                { $$ = start_struct (UNION_TYPE, $2); }
          component_decl_list '}' maybe_attribute
-               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+               { $$ = finish_struct ($<ttype>4, nreverse ($5),
+                                     chainon ($1, $7)); }
        | union_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
-                                     $3, chainon ($1, $5));
+                                     nreverse ($3), chainon ($1, $5));
                }
        | enum_head identifier '{'
                { $$ = start_enum ($2); }
@@ -1804,44 +1778,45 @@ maybecomma_warn:
                    pedwarn ("comma at end of enumerator list"); }
        ;
 
+/* We chain the components in reverse order.  They are put in forward
+   order in structsp_attr.
+
+   Note that component_declarator returns single decls, so components
+   and components_notype can use TREE_CHAIN directly, wheras components
+   and components_notype return lists (of comma separated decls), so
+   component_decl_list and component_decl_list2 must use chainon.
+
+   The theory behind all this is that there will be more semicolon
+   separated fields than comma separated fields, and so we'll be
+   minimizing the number of node traversals required by chainon.  */
+
 component_decl_list:
          component_decl_list2
                { $$ = $1; }
        | component_decl_list2 component_decl
-               { $$ = chainon ($1, $2);
+               { $$ = chainon ($2, $1);
                  pedwarn ("no semicolon at end of struct or union"); }
        ;
 
 component_decl_list2:  /* empty */
                { $$ = NULL_TREE; }
        | component_decl_list2 component_decl ';'
-               { $$ = chainon ($1, $2); }
+               { $$ = chainon ($2, $1); }
        | component_decl_list2 ';'
                { if (pedantic)
                    pedwarn ("extra semicolon in struct or union specified"); }
-ifobjc
+@@ifobjc
        /* foo(sizeof(struct{ @defs(ClassName)})); */
-       | DEFS '(' CLASSNAME ')'
-               {
-                 tree interface = lookup_interface ($3);
-
-                 if (interface)
-                   $$ = get_class_ivars (interface);
-                 else
-                   {
-                     error ("cannot find interface declaration for `%s'",
-                            IDENTIFIER_POINTER ($3));
-                     $$ = NULL_TREE;
-                   }
-               }
-end ifobjc
+       | AT_DEFS '(' CLASSNAME ')'
+               { $$ = nreverse (objc_get_class_ivars ($3)); }
+@@end_ifobjc
        ;
 
 component_decl:
          declspecs_nosc_ts setspecs components
                { $$ = $3;
                  POP_DECLSPEC_STACK; }
-       | declspecs_nosc_ts setspecs save_filename save_lineno
+       | declspecs_nosc_ts setspecs
                {
                  /* Support for unnamed structs or unions as members of
                     structs or unions (which is [a] useful and [b] supports
@@ -1849,7 +1824,7 @@ component_decl:
                  if (pedantic)
                    pedwarn ("ISO C doesn't support unnamed structs/unions");
 
-                 $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+                 $$ = grokfield(NULL, current_declspecs, NULL_TREE);
                  POP_DECLSPEC_STACK; }
        | declspecs_nosc_nots setspecs components_notype
                { $$ = $3;
@@ -1857,7 +1832,7 @@ component_decl:
        | declspecs_nosc_nots
                { if (pedantic)
                    pedwarn ("ISO C forbids member declarations with no members");
-                 shadow_tag($1);
+                 shadow_tag_warned ($1, pedantic);
                  $$ = NULL_TREE; }
        | error
                { $$ = NULL_TREE; }
@@ -1869,45 +1844,47 @@ component_decl:
 components:
          component_declarator
        | components ',' maybe_resetattrs component_declarator
-               { $$ = chainon ($1, $4); }
+               { TREE_CHAIN ($4) = $1; $$ = $4; }
        ;
 
 components_notype:
          component_notype_declarator
        | components_notype ',' maybe_resetattrs component_notype_declarator
-               { $$ = chainon ($1, $4); }
+               { TREE_CHAIN ($4) = $1; $$ = $4; }
        ;
 
 component_declarator:
-         save_filename save_lineno declarator maybe_attribute
-               { $$ = grokfield ($1, $2, $3, current_declspecs, NULL_TREE);
-                 decl_attributes (&$$, chainon ($4, all_prefix_attributes), 0); }
-       | save_filename save_lineno
-         declarator ':' expr_no_commas maybe_attribute
-               { $$ = grokfield ($1, $2, $3, current_declspecs, $5);
-                 decl_attributes (&$$, chainon ($6, all_prefix_attributes), 0); }
-       | save_filename save_lineno ':' expr_no_commas maybe_attribute
-               { $$ = grokfield ($1, $2, NULL_TREE, current_declspecs, $4);
-                 decl_attributes (&$$, chainon ($5, all_prefix_attributes), 0); }
+         declarator maybe_attribute
+               { $$ = grokfield ($1, current_declspecs, NULL_TREE);
+                 decl_attributes (&$$,
+                                  chainon ($2, all_prefix_attributes), 0); }
+       | declarator ':' expr_no_commas maybe_attribute
+               { $$ = grokfield ($1, current_declspecs, $3.value);
+                 decl_attributes (&$$,
+                                  chainon ($4, all_prefix_attributes), 0); }
+       | ':' expr_no_commas maybe_attribute
+               { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+                 decl_attributes (&$$,
+                                  chainon ($3, all_prefix_attributes), 0); }
        ;
 
 component_notype_declarator:
-         save_filename save_lineno notype_declarator maybe_attribute
-               { $$ = grokfield ($1, $2, $3, current_declspecs, NULL_TREE);
-                 decl_attributes (&$$, chainon ($4, all_prefix_attributes), 0); }
-       | save_filename save_lineno
-         notype_declarator ':' expr_no_commas maybe_attribute
-               { $$ = grokfield ($1, $2, $3, current_declspecs, $5);
-                 decl_attributes (&$$, chainon ($6, all_prefix_attributes), 0); }
-       | save_filename save_lineno ':' expr_no_commas maybe_attribute
-               { $$ = grokfield ($1, $2, NULL_TREE, current_declspecs, $4);
-                 decl_attributes (&$$, chainon ($5, all_prefix_attributes), 0); }
+         notype_declarator maybe_attribute
+               { $$ = grokfield ($1, current_declspecs, NULL_TREE);
+                 decl_attributes (&$$,
+                                  chainon ($2, all_prefix_attributes), 0); }
+       | notype_declarator ':' expr_no_commas maybe_attribute
+               { $$ = grokfield ($1, current_declspecs, $3.value);
+                 decl_attributes (&$$,
+                                  chainon ($4, all_prefix_attributes), 0); }
+       | ':' expr_no_commas maybe_attribute
+               { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+                 decl_attributes (&$$,
+                                  chainon ($3, all_prefix_attributes), 0); }
        ;
 
 /* We chain the enumerators in reverse order.
-   They are put in forward order where enumlist is used.
-   (The order used to be significant, but no longer is so.
-   However, we still maintain the order, just to be clean.)  */
+   They are put in forward order in structsp_attr.  */
 
 enumlist:
          enumerator
@@ -1915,7 +1892,7 @@ enumlist:
                { if ($1 == error_mark_node)
                    $$ = $1;
                  else
-                   $$ = chainon ($3, $1); }
+                   TREE_CHAIN ($3) = $1, $$ = $3; }
        | error
                { $$ = error_mark_node; }
        ;
@@ -1925,7 +1902,7 @@ enumerator:
          identifier
                { $$ = build_enumerator ($1, NULL_TREE); }
        | identifier '=' expr_no_commas
-               { $$ = build_enumerator ($1, $3); }
+               { $$ = build_enumerator ($1, $3.value); }
        ;
 
 typename:
@@ -1944,17 +1921,15 @@ absdcl:   /* an absolute declarator */
 
 absdcl_maybe_attribute:   /* absdcl maybe_attribute, but not just attributes */
        /* empty */
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        NULL_TREE),
-                                       all_prefix_attributes); }
+               { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
+                                    NULL_TREE); }
        | absdcl1
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $1),
-                                       all_prefix_attributes); }
+               { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
+                                    $1); }
        | absdcl1_noea attributes
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $1),
-                                       chainon ($2, all_prefix_attributes)); }
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($2, all_prefix_attributes),
+                                    $1); }
        ;
 
 absdcl1:  /* a nonempty absolute declarator */
@@ -1977,31 +1952,31 @@ absdcl1_ea:
 
 direct_absdcl1:
          '(' maybe_attribute absdcl1 ')'
-               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
+               { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
        | direct_absdcl1 '(' parmlist
-               { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
+               { $$ = build_function_declarator ($3, $1); }
        | direct_absdcl1 array_declarator
-               { $$ = set_array_declarator_type ($2, $1, 1); }
+               { $$ = set_array_declarator_inner ($2, $1, true); }
        | '(' parmlist
-               { $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }
+               { $$ = build_function_declarator ($2, NULL_TREE); }
        | array_declarator
-               { $$ = set_array_declarator_type ($1, NULL_TREE, 1); }
+               { $$ = set_array_declarator_inner ($1, NULL_TREE, true); }
        ;
 
 /* The [...] part of a declarator for an array type.  */
 
 array_declarator:
-       '[' maybe_type_quals_attrs expr ']'
-               { $$ = build_array_declarator ($3, $2, 0, 0); }
+       '[' maybe_type_quals_attrs expr_no_commas ']'
+               { $$ = build_array_declarator ($3.value, $2, false, false); }
        | '[' maybe_type_quals_attrs ']'
-               { $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
+               { $$ = build_array_declarator (NULL_TREE, $2, false, false); }
        | '[' maybe_type_quals_attrs '*' ']'
-               { $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
-       | '[' STATIC maybe_type_quals_attrs expr ']'
-               { $$ = build_array_declarator ($4, $3, 1, 0); }
+               { $$ = build_array_declarator (NULL_TREE, $2, false, true); }
+       | '[' STATIC maybe_type_quals_attrs expr_no_commas ']'
+               { $$ = build_array_declarator ($4.value, $3, true, false); }
        /* declspecs_nosc_nots is a synonym for type_quals_attrs.  */
-       | '[' declspecs_nosc_nots STATIC expr ']'
-               { $$ = build_array_declarator ($4, $2, 1, 0); }
+       | '[' declspecs_nosc_nots STATIC expr_no_commas ']'
+               { $$ = build_array_declarator ($4.value, $2, true, false); }
        ;
 
 /* A nonempty series of declarations and statements (possibly followed by
@@ -2015,7 +1990,7 @@ stmts_and_decls:
        | lineno_stmt_decl_or_labels_ending_decl
        | lineno_stmt_decl_or_labels_ending_label
                {
-                 pedwarn ("deprecated use of label at end of compound statement");
+                 error ("label at end of compound statement");
                }
        | lineno_stmt_decl_or_labels_ending_error
        ;
@@ -2031,8 +2006,11 @@ lineno_stmt_decl_or_labels_ending_stmt:
 lineno_stmt_decl_or_labels_ending_decl:
          lineno_decl
        | lineno_stmt_decl_or_labels_ending_stmt lineno_decl
-               { if (pedantic && !flag_isoc99)
-                   pedwarn ("ISO C89 forbids mixed declarations and code"); }
+               {
+                 if ((pedantic && !flag_isoc99)
+                     || warn_declaration_after_statement)
+                   pedwarn_c90 ("ISO C90 forbids mixed declarations and code");
+               }
        | lineno_stmt_decl_or_labels_ending_decl lineno_decl
        | lineno_stmt_decl_or_labels_ending_error lineno_decl
        ;
@@ -2060,53 +2038,9 @@ lineno_stmt_decl_or_labels:
 errstmt:  error ';'
        ;
 
-pushlevel:  /* empty */
-               { pushlevel (0);
-                 clear_last_expr ();
-                 add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-ifobjc
-                 if (objc_method_context)
-                   add_objc_decls ();
-end ifobjc
-               }
-       ;
-
-poplevel:  /* empty */
-                { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
-        ;
-
 /* Start and end blocks created for the new scopes of C99.  */
 c99_block_start: /* empty */
-               { if (flag_isoc99)
-                   {
-                     $$ = c_begin_compound_stmt ();
-                     pushlevel (0);
-                     clear_last_expr ();
-                     add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-ifobjc
-                     if (objc_method_context)
-                       add_objc_decls ();
-end ifobjc
-                   }
-                 else
-                   $$ = NULL_TREE;
-               }
-       ;
-
-/* Productions using c99_block_start and c99_block_end will need to do what's
-   in compstmt: RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); $$ = $2; where
-   $1 is the value of c99_block_start and $2 of c99_block_end.  */
-c99_block_end: /* empty */
-                { if (flag_isoc99)
-                   {
-                     tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
-                     $$ = poplevel (kept_level_p (), 0, 0);
-                     SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
-                       = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
-                       = $$;
-                   }
-                 else
-                   $$ = NULL_TREE; }
+               { $$ = c_begin_compound_stmt (flag_isoc99); }
        ;
 
 /* Read zero or more forward-declarations for labels
@@ -2128,9 +2062,9 @@ label_decl:
                { tree link;
                  for (link = $2; link; link = TREE_CHAIN (link))
                    {
-                     tree label = shadow_label (TREE_VALUE (link));
+                     tree label = declare_label (TREE_VALUE (link));
                      C_DECLARED_LABEL_FLAG (label) = 1;
-                     add_decl_stmt (label);
+                     add_stmt (build_stmt (DECL_EXPR, label));
                    }
                }
        ;
@@ -2139,21 +2073,15 @@ label_decl:
    It causes syntax errors to ignore to the next openbrace.  */
 compstmt_or_error:
          compstmt
-               {}
+               { add_stmt ($1); }
        | error compstmt
        ;
 
-compstmt_start: '{' { compstmt_count++;
-                      $$ = c_begin_compound_stmt (); }
+compstmt_start: '{' { $$ = c_begin_compound_stmt (true); }
         ;
 
 compstmt_nostart: '}'
-               { $$ = convert (void_type_node, integer_zero_node); }
-       | pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
-               { $$ = poplevel (kept_level_p (), 1, 0);
-                 SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
-                   = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
-                   = $$; }
+       | maybe_label_decls compstmt_contents_nonempty '}'
        ;
 
 compstmt_contents_nonempty:
@@ -2165,260 +2093,267 @@ compstmt_primary_start:
        '(' '{'
                { if (current_function_decl == 0)
                    {
-                     error ("braced-group within expression allowed only inside a function");
+                     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_label_level ();
-                 compstmt_count++;
-                 $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
+                 $$ = c_begin_stmt_expr ();
                }
         ;
 
 compstmt: compstmt_start compstmt_nostart
-               { RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
-                 last_expr_type = NULL_TREE;
-                  $$ = $1; }
-       ;
-
-/* Value is number of statements counted as of the closeparen.  */
-simple_if:
-         if_prefix c99_block_lineno_labeled_stmt
-                { c_finish_then (); }
-/* Make sure c_expand_end_cond is run once
-   for each call to c_expand_start_cond.
-   Otherwise a crash is likely.  */
-       | if_prefix error
-       ;
-
-if_prefix:
-         /* We must build the IF_STMT node before parsing its
-            condition so that STMT_LINENO refers to the line
-            containing the "if", and not the line containing
-            the close-parenthesis.
-
-            c_begin_if_stmt returns the IF_STMT node, which
-            we later pass to c_expand_start_cond to fill
-            in the condition and other tidbits.  */
-          IF
-                { $<ttype>$ = c_begin_if_stmt (); }
-            '(' expr ')'
-               { c_expand_start_cond (c_common_truthvalue_conversion ($4),
-                                      compstmt_count,$<ttype>2);
-                 $<itype>$ = stmt_count;
-                 if_stmt_file = $<filename>-2;
-                 if_stmt_line = $<lineno>-1; }
-        ;
-
-/* This is a subroutine of stmt.
-   It is used twice, once for valid DO statements
-   and once for catching errors in parsing the end test.  */
-do_stmt_start:
-         DO
-               { stmt_count++;
-                 compstmt_count++;
-                 $<ttype>$
-                   = add_stmt (build_stmt (DO_STMT, NULL_TREE,
-                                           NULL_TREE));
-                 /* In the event that a parse error prevents
-                    parsing the complete do-statement, set the
-                    condition now.  Otherwise, we can get crashes at
-                    RTL-generation time.  */
-                 DO_COND ($<ttype>$) = error_mark_node; }
-         c99_block_lineno_labeled_stmt WHILE
-               { $$ = $<ttype>2;
-                 RECHAIN_STMTS ($$, DO_BODY ($$)); }
+               { $$ = c_end_compound_stmt ($1, true); }
        ;
 
 /* The forced readahead in here is because we might be at the end of a
    line, and the line and file won't be bumped until yylex absorbs the
    first token on the next line.  */
-save_filename:
-               { if (yychar == YYEMPTY)
-                   yychar = YYLEX;
-                 $$ = input_filename; }
-       ;
 
-save_lineno:
+save_location:
                { if (yychar == YYEMPTY)
                    yychar = YYLEX;
-                 $$ = lineno; }
+                 $$ = input_location; }
        ;
 
-lineno_labeled_stmt:
-         lineno_stmt
-       | lineno_label lineno_labeled_stmt
+lineno_labels:
+         /* empty */
+       | lineno_labels lineno_label
        ;
 
-/* Like lineno_labeled_stmt, but a block in C99.  */
+/* A labeled statement.  In C99 it also generates an implicit block.  */
 c99_block_lineno_labeled_stmt:
-         c99_block_start lineno_labeled_stmt c99_block_end
-               { if (flag_isoc99)
-                   RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
+         c99_block_start lineno_labels lineno_stmt
+                { $$ = c_end_compound_stmt ($1, flag_isoc99); }
        ;
 
 lineno_stmt:
-         save_filename save_lineno stmt
-               { if ($3)
-                   {
-                     STMT_LINENO ($3) = $2;
-                     /* ??? We currently have no way of recording
-                        the filename for a statement.  This probably
-                        matters little in practice at the moment,
-                        but I suspect that problems will occur when
-                        doing inlining at the tree level.  */
-                   }
+         save_location stmt
+               { 
+                 /* Two cases cannot and do not have line numbers associated:
+                    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,
+                    or discarded.  If stmt was compound, but without new
+                    variables, we will have skipped the creation of a BIND
+                    and will have a bare STATEMENT_LIST.  But that's ok
+                    because (recursively) all of the component statments
+                    should already have line numbers assigned.  */
+                 if ($2 && EXPR_P ($2))
+                   SET_EXPR_LOCATION ($2, $1);
                }
        ;
 
 lineno_label:
-         save_filename save_lineno label
-               { if ($3)
-                   {
-                     STMT_LINENO ($3) = $2;
-                   }
-               }
+         save_location label
+               { if ($2) SET_EXPR_LOCATION ($2, $1); }
        ;
 
-select_or_iter_stmt:
-         simple_if ELSE
-               { c_expand_start_else ();
-                 $<itype>1 = stmt_count; }
-         c99_block_lineno_labeled_stmt
-                { c_finish_else ();
-                 c_expand_end_cond ();
-                 if (extra_warnings && stmt_count == $<itype>1)
-                   warning ("empty body in an else-statement"); }
-       | simple_if %prec IF
-               { c_expand_end_cond ();
-                 /* This warning is here instead of in simple_if, because we
-                    do not want a warning if an empty if is followed by an
-                    else statement.  Increment stmt_count so we don't
-                    give a second error if this is a nested `if'.  */
-                 if (extra_warnings && stmt_count++ == $<itype>1)
-                   warning_with_file_and_line (if_stmt_file, if_stmt_line,
-                                               "empty body in an if-statement"); }
-/* Make sure c_expand_end_cond is run once
-   for each call to c_expand_start_cond.
-   Otherwise a crash is likely.  */
-       | simple_if ELSE error
-               { c_expand_end_cond (); }
-       /* We must build the WHILE_STMT node before parsing its
-         condition so that STMT_LINENO refers to the line
-         containing the "while", and not the line containing
-         the close-parenthesis.
-
-         c_begin_while_stmt returns the WHILE_STMT node, which
-         we later pass to c_finish_while_stmt_cond to fill
-         in the condition and other tidbits.  */
-       | WHILE
-                { stmt_count++;
-                 $<ttype>$ = c_begin_while_stmt (); }
-         '(' expr ')'
-                { $4 = c_common_truthvalue_conversion ($4);
-                 c_finish_while_stmt_cond
-                   (c_common_truthvalue_conversion ($4), $<ttype>2);
-                 $<ttype>$ = add_stmt ($<ttype>2); }
-         c99_block_lineno_labeled_stmt
-               { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
-       | do_stmt_start
-         '(' expr ')' ';'
-                { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
-       | do_stmt_start error
-               { }
-       | FOR
-               { $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
-                                         NULL_TREE, NULL_TREE);
-                 add_stmt ($<ttype>$); }
-         '(' for_init_stmt
-               { stmt_count++;
-                 RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
-         xexpr ';'
-                { if ($6)
-                   FOR_COND ($<ttype>2)
-                     = c_common_truthvalue_conversion ($6); }
-         xexpr ')'
-               { FOR_EXPR ($<ttype>2) = $9; }
-         c99_block_lineno_labeled_stmt
-                { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
-       | SWITCH '(' expr ')'
-               { stmt_count++;
-                 $<ttype>$ = c_start_case ($3); }
-         c99_block_lineno_labeled_stmt
-                { c_finish_case (); }
+condition: save_location expr
+               { $$ = lang_hooks.truthvalue_conversion ($2.value);
+                 if (EXPR_P ($$))
+                   SET_EXPR_LOCATION ($$, $1); }
+       ;
+
+/* Implement -Wparenthesis by special casing IF statement directly nested
+   within IF statement.  This requires some amount of duplication of the
+   productions under c99_block_lineno_labeled_stmt in order to work out.
+   But it's still likely more maintainable than lots of state outside the
+   parser...  */
+
+if_statement_1:
+       c99_block_start lineno_labels if_statement
+               { $$ = c_end_compound_stmt ($1, flag_isoc99); }
+       ;
+
+if_statement_2:
+         c99_block_start lineno_labels ';'
+               { if (extra_warnings)
+                   add_stmt (build (NOP_EXPR, NULL_TREE, NULL_TREE));
+                 $$ = c_end_compound_stmt ($1, flag_isoc99); }
+       | c99_block_lineno_labeled_stmt
+       ;
+
+if_statement:
+         IF c99_block_start save_location '(' condition ')'
+           if_statement_1 ELSE if_statement_2
+               { c_finish_if_stmt ($3, $5, $7, $9, true);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       | IF c99_block_start save_location '(' condition ')'
+           if_statement_2 ELSE if_statement_2
+               { c_finish_if_stmt ($3, $5, $7, $9, false);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       | IF c99_block_start save_location '(' condition ')'
+           if_statement_1                              %prec IF
+               { c_finish_if_stmt ($3, $5, $7, NULL, true);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       | IF c99_block_start save_location '(' condition ')'
+           if_statement_2                              %prec IF
+               { c_finish_if_stmt ($3, $5, $7, NULL, false);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       ;
+
+start_break: /* empty */
+               { $$ = c_break_label; c_break_label = NULL; }
+       ;
+
+start_continue: /* empty */
+               { $$ = c_cont_label; c_cont_label = NULL; }
+       ;
+
+while_statement:
+       WHILE c99_block_start save_location '(' condition ')'
+       start_break start_continue c99_block_lineno_labeled_stmt
+               { c_finish_loop ($3, $5, NULL, $9, c_break_label,
+                                c_cont_label, true);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99));
+                 c_break_label = $7; c_cont_label = $8; }
+       ;
+
+do_statement:
+       DO c99_block_start save_location start_break start_continue
+       c99_block_lineno_labeled_stmt WHILE
+               { $<ttype>$ = c_break_label; c_break_label = $4; }
+               { $<ttype>$ = c_cont_label; c_cont_label = $5; }
+       '(' condition ')' ';'
+                { c_finish_loop ($3, $11, NULL, $6, $<ttype>8,
+                                $<ttype>9, false);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       ;
+
+xexpr:
+       /* empty */
+               { $$ = NULL_TREE; }
+       | expr
+               { $$ = $1.value; }
        ;
 
 for_init_stmt:
          xexpr ';'
-               { add_stmt (build_stmt (EXPR_STMT, $1)); }
+               { c_finish_expr_stmt ($1); }
        | decl
                { check_for_loop_decls (); }
        ;
 
-/* Parse a single real statement, not including any labels.  */
-stmt:
-         compstmt
-               { stmt_count++; $$ = $1; }
-       | expr ';'
-               { stmt_count++;
-                 $$ = c_expand_expr_stmt ($1); }
-       | c99_block_start select_or_iter_stmt c99_block_end
-               { if (flag_isoc99)
-                   RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
-                 $$ = NULL_TREE; }
+for_cond_expr: save_location xexpr
+               { if ($2)
+                   {
+                     $$ = lang_hooks.truthvalue_conversion ($2);
+                     if (EXPR_P ($$))
+                       SET_EXPR_LOCATION ($$, $1);
+                   }
+                 else
+                   $$ = NULL;
+               }
+       ;
+
+for_incr_expr: xexpr
+               { $$ = c_process_expr_stmt ($1); }
+       ;
+
+for_statement:
+       FOR c99_block_start '(' for_init_stmt
+       save_location for_cond_expr ';' for_incr_expr ')'
+       start_break start_continue c99_block_lineno_labeled_stmt
+               { c_finish_loop ($5, $6, $8, $12, c_break_label,
+                                c_cont_label, true);
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99));
+                 c_break_label = $10; c_cont_label = $11; }
+       ;
+
+switch_statement:
+       SWITCH c99_block_start '(' expr ')'
+               { $<ttype>$ = c_start_case ($4.value); }
+       start_break c99_block_lineno_labeled_stmt
+                { c_finish_case ($8);
+                 if (c_break_label)
+                   add_stmt (build (LABEL_EXPR, void_type_node,
+                                    c_break_label));
+                 c_break_label = $7;
+                 add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+       ;
+
+/* Parse a single real statement, not including any labels or compounds.  */
+stmt_nocomp:
+         expr ';'
+               { $$ = c_finish_expr_stmt ($1.value); }
+       | if_statement
+               { $$ = NULL_TREE; }
+       | while_statement
+               { $$ = NULL_TREE; }
+       | do_statement
+               { $$ = NULL_TREE; }
+       | for_statement
+               { $$ = NULL_TREE; }
+       | switch_statement
+               { $$ = NULL_TREE; }
        | BREAK ';'
-               { stmt_count++;
-                 $$ = add_stmt (build_break_stmt ()); }
+               { $$ = c_finish_bc_stmt (&c_break_label, true); }
        | CONTINUE ';'
-                { stmt_count++;
-                 $$ = add_stmt (build_continue_stmt ()); }
+                { $$ = c_finish_bc_stmt (&c_cont_label, false); }
        | RETURN ';'
-                { stmt_count++;
-                 $$ = c_expand_return (NULL_TREE); }
+                { $$ = c_finish_return (NULL_TREE); }
        | RETURN expr ';'
-                { stmt_count++;
-                 $$ = c_expand_return ($2); }
-       | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
-               { stmt_count++;
-                 $$ = simple_asm_stmt ($4); }
-       /* This is the case with just output operands.  */
-       | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
-               { stmt_count++;
-                 $$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
-       /* This is the case with input operands as well.  */
-       | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
-         asm_operands ')' ';'
-               { stmt_count++;
-                 $$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
-       /* This is the case with clobbered registers as well.  */
-       | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
-         asm_operands ':' asm_clobbers ')' ';'
-               { stmt_count++;
-                 $$ = build_asm_stmt ($2, $4, $6, $8, $10); }
+                { $$ = c_finish_return ($2.value); }
+       | asm_stmt
        | GOTO identifier ';'
-               { tree decl;
-                 stmt_count++;
-                 decl = lookup_label ($2);
-                 if (decl != 0)
-                   {
-                     TREE_USED (decl) = 1;
-                     $$ = add_stmt (build_stmt (GOTO_STMT, decl));
-                   }
-                 else
-                   $$ = NULL_TREE;
-               }
+               { $$ = c_finish_goto_label ($2); }
        | GOTO '*' expr ';'
-               { if (pedantic)
-                   pedwarn ("ISO C forbids `goto *expr;'");
-                 stmt_count++;
-                 $3 = convert (ptr_type_node, $3);
-                 $$ = add_stmt (build_stmt (GOTO_STMT, $3)); }
+               { $$ = c_finish_goto_ptr ($3.value); }
        | ';'
                { $$ = NULL_TREE; }
+@@ifobjc
+       | AT_THROW expr ';'
+               { $$ = objc_build_throw_stmt ($2.value); }
+       | AT_THROW ';'
+               { $$ = objc_build_throw_stmt (NULL_TREE); }
+       | objc_try_catch_stmt
+               { $$ = NULL_TREE; }
+       | AT_SYNCHRONIZED save_location '(' expr ')' compstmt
+               { objc_build_synchronized ($2, $4.value, $6); $$ = NULL_TREE; }
+       ;
+
+objc_catch_prefix:
+       AT_CATCH '(' parm ')'
+               { objc_begin_catch_clause ($3); }
+       ;
+
+objc_catch_clause:
+         objc_catch_prefix '{' compstmt_nostart
+               { objc_finish_catch_clause (); }
+       | objc_catch_prefix '{' error '}'
+               { objc_finish_catch_clause (); }
+       ;
+
+objc_opt_catch_list:
+         /* empty */
+       | objc_opt_catch_list objc_catch_clause
+       ;
+
+objc_try_catch_clause:
+       AT_TRY save_location compstmt
+               { objc_begin_try_stmt ($2, $3); }
+       objc_opt_catch_list
+       ;
+
+objc_finally_clause:
+       AT_FINALLY save_location compstmt
+               { objc_build_finally_clause ($2, $3); }
+       ;
+
+objc_try_catch_stmt:
+         objc_try_catch_clause
+               { objc_finish_try_stmt (); }
+       | objc_try_catch_clause objc_finally_clause
+               { objc_finish_try_stmt (); }
+@@end_ifobjc
+       ;
+
+/* Parse a single or compound real statement, not including any labels.  */
+stmt:
+         compstmt
+               { add_stmt ($1); $$ = NULL_TREE; }
+       | stmt_nocomp
        ;
 
 /* Any kind of label, including jump labels and case labels.
@@ -2426,41 +2361,85 @@ stmt:
    also at the end of a compound statement.  */
 
 label:   CASE expr_no_commas ':'
-                { stmt_count++;
-                 $$ = do_case ($2, NULL_TREE); }
+                { $$ = do_case ($2.value, NULL_TREE); }
        | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
-                { stmt_count++;
-                 $$ = do_case ($2, $4); }
+                { $$ = do_case ($2.value, $4.value); }
        | DEFAULT ':'
-                { stmt_count++;
-                 $$ = do_case (NULL_TREE, NULL_TREE); }
-       | identifier save_filename save_lineno ':' maybe_attribute
-               { tree label = define_label ($2, $3, $1);
-                 stmt_count++;
+                { $$ = do_case (NULL_TREE, NULL_TREE); }
+       | identifier save_location ':' maybe_attribute
+               { tree label = define_label ($2, $1);
                  if (label)
                    {
-                     decl_attributes (&label, $5, 0);
-                     $$ = add_stmt (build_stmt (LABEL_STMT, label));
+                     decl_attributes (&label, $4, 0);
+                     $$ = add_stmt (build_stmt (LABEL_EXPR, label));
                    }
                  else
                    $$ = NULL_TREE;
                }
        ;
 
-/* Either a type-qualifier or nothing.  First thing in an `asm' statement.  */
+/* Asm expressions and statements */
 
-maybe_type_qual:
-       /* empty */
-               { emit_line_note (input_filename, lineno);
-                 $$ = NULL_TREE; }
-       | TYPE_QUAL
-               { emit_line_note (input_filename, lineno); }
+/* simple_asm_expr is used in restricted contexts, where a full
+   expression with inputs and outputs does not make sense.  */
+simple_asm_expr:
+       ASM_KEYWORD stop_string_translation
+             '(' STRING ')' start_string_translation
+               { $$ = $4; }
        ;
 
-xexpr:
-       /* empty */
+/* maybeasm: used for assembly names for declarations */
+maybeasm:
+         /* empty */
                { $$ = NULL_TREE; }
-       | expr
+       | simple_asm_expr
+       ;
+
+/* asmdef: asm() outside a function body.  */
+asmdef:
+       simple_asm_expr ';'
+               { assemble_asm ($1); }
+        | ASM_KEYWORD error start_string_translation ';'
+                {}
+       ;
+
+/* Full-blown asm statement with inputs, outputs, clobbers, and
+   volatile tag allowed.  */
+asm_stmt:
+       ASM_KEYWORD maybe_volatile stop_string_translation
+               '(' asm_argument ')' start_string_translation ';'
+               { $$ = build_asm_stmt ($2, $5); }
+       ;
+
+asm_argument:
+       /* no operands */
+       STRING
+               { $$ = build_asm_expr ($1, 0, 0, 0, true); }
+       /* output operands */
+       | STRING ':' asm_operands
+               { $$ = build_asm_expr ($1, $3, 0, 0, false); }
+       /* output and input operands */
+       | 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
+               { $$ = build_asm_expr ($1, $3, $5, $7, false); }
+       ;
+
+/* Either 'volatile' or nothing.  First thing in an `asm' statement.  */
+
+maybe_volatile:
+       /* empty */
+               { $$ = 0; }
+       | TYPE_QUAL
+               { if ($1 != ridpointers[RID_VOLATILE])
+                   {
+                     warning ("%E qualifier ignored on asm", $1);
+                     $$ = 0;
+                   }
+                 else
+                   $$ = $1;
+               }
        ;
 
 /* These are the operands other than the first string and colon
@@ -2477,12 +2456,14 @@ nonnull_asm_operands:
        ;
 
 asm_operand:
-         STRING '(' expr ')'
-               { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
-       | '[' identifier ']' STRING '(' expr ')'
+         STRING start_string_translation '(' expr ')' stop_string_translation
+               { $$ = build_tree_list (build_tree_list (NULL_TREE, $1),
+                                       $4.value); }
+       | '[' identifier ']' STRING start_string_translation
+         '(' expr ')' stop_string_translation
                { $2 = build_string (IDENTIFIER_LENGTH ($2),
                                     IDENTIFIER_POINTER ($2));
-                 $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+                 $$ = build_tree_list (build_tree_list ($2, $4), $7.value); }
        ;
 
 asm_clobbers:
@@ -2491,6 +2472,15 @@ asm_clobbers:
        | asm_clobbers ',' STRING
                { $$ = tree_cons (NULL_TREE, $3, $1); }
        ;
+
+stop_string_translation:
+        { c_lex_string_translate = 0; }
+        ;
+
+start_string_translation:
+        { c_lex_string_translate = 1; }
+        ;
+
 \f
 /* This is what appears inside the parens in a function declarator.
    Its value is a list of ..._TYPE nodes.  Attributes must appear here
@@ -2499,54 +2489,40 @@ asm_clobbers:
    "void bar (int (__attribute__((__mode__(SI))) int foo));".  */
 parmlist:
          maybe_attribute
-               { pushlevel (0);
-                 clear_parm_order ();
-                 declare_parm_level (0); }
+               { push_scope ();
+                 declare_parm_level (); }
          parmlist_1
                { $$ = $3;
-                 parmlist_tags_warning ();
-                 poplevel (0, 0, 0); }
+                 pop_scope (); }
        ;
 
 parmlist_1:
          parmlist_2 ')'
        | parms ';'
-               { tree parm;
-                 if (pedantic)
-                   pedwarn ("ISO C forbids forward parameter declarations");
-                 /* Mark the forward decls as such.  */
-                 for (parm = getdecls (); parm; parm = TREE_CHAIN (parm))
-                   TREE_ASM_WRITTEN (parm) = 1;
-                 clear_parm_order (); }
+               { mark_forward_parm_decls (); }
          maybe_attribute
                { /* Dummy action so attributes are in known place
                     on parser stack.  */ }
          parmlist_1
                { $$ = $6; }
        | error ')'
-               { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
+               { $$ = make_node (TREE_LIST); }
        ;
 
 /* This is what appears inside the parens in a function declarator.
    Is value is represented in the format that grokdeclarator expects.  */
 parmlist_2:  /* empty */
-               { $$ = get_parm_info (0); }
+               { $$ = make_node (TREE_LIST); }
        | ELLIPSIS
-               { $$ = get_parm_info (0);
-                 /* Gcc used to allow this as an extension.  However, it does
-                    not work for all targets, and thus has been disabled.
-                    Also, since func (...) and func () are indistinguishable,
-                    it caused problems with the code in expand_builtin which
-                    tries to verify that BUILT_IN_NEXT_ARG is being used
-                    correctly.  */
+               { $$ = make_node (TREE_LIST); 
+                 /* Suppress -Wold-style-definition for this case.  */
+                 TREE_CHAIN ($$) = error_mark_node;
                  error ("ISO C requires a named argument before `...'");
                }
        | parms
-               { $$ = get_parm_info (1);
-                 parsing_iso_function_signature = true;
-               }
+               { $$ = get_parm_info (/*ellipsis=*/false); }
        | parms ',' ELLIPSIS
-               { $$ = get_parm_info (0); }
+               { $$ = get_parm_info (/*ellipsis=*/true); }
        ;
 
 parms:
@@ -2560,22 +2536,19 @@ parms:
    as found in a parmlist.  */
 parm:
          declspecs_ts setspecs parm_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs notype_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs absdcl_maybe_attribute
                { $$ = $3;
                  POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
 
        | declspecs_nots setspecs absdcl_maybe_attribute
@@ -2587,22 +2560,19 @@ parm:
    stack.  */
 firstparm:
          declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
                { $$ = $3;
                  POP_DECLSPEC_STACK; }
        | declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute
-               { $$ = build_tree_list (build_tree_list (current_declspecs,
-                                                        $3),
-                                       chainon ($4, all_prefix_attributes));
+               { $$ = build_c_parm (current_declspecs,
+                                    chainon ($4, all_prefix_attributes), $3);
                  POP_DECLSPEC_STACK; }
 
        | declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
@@ -2621,29 +2591,20 @@ setspecs_fp:
    Its value is a list of ..._TYPE nodes or a list of identifiers.  */
 parmlist_or_identifiers:
          maybe_attribute
-               { pushlevel (0);
-                 clear_parm_order ();
-                 declare_parm_level (1); }
+               { push_scope ();
+                 declare_parm_level (); }
          parmlist_or_identifiers_1
                { $$ = $3;
-                 parmlist_tags_warning ();
-                 poplevel (0, 0, 0); }
+                 pop_scope (); }
        ;
 
 parmlist_or_identifiers_1:
          parmlist_1
        | identifiers ')'
-               { tree t;
-                 for (t = $1; t; t = TREE_CHAIN (t))
-                   if (TREE_VALUE (t) == NULL_TREE)
-                     error ("`...' in old-style identifier list");
-                 $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+               { $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
 
                  /* Make sure we have a parmlist after attributes.  */
-                 if ($<ttype>-1 != 0
-                     && (TREE_CODE ($$) != TREE_LIST
-                         || TREE_PURPOSE ($$) == 0
-                         || TREE_CODE (TREE_PURPOSE ($$)) != PARM_DECL))
+                 if ($<ttype>-1 != 0)
                    YYERROR1;
                }
        ;
@@ -2673,7 +2634,7 @@ extension:
                  flag_iso = 0; }
        ;
 \f
-ifobjc
+@@ifobjc
 /* Objective-C productions.  */
 
 objcdef:
@@ -2682,7 +2643,7 @@ objcdef:
        | aliasdecl
        | protocoldef
        | methoddef
-       | END
+       | AT_END
                {
                  if (objc_implementation_context)
                     {
@@ -2704,134 +2665,71 @@ identifier_list:
        ;
 
 classdecl:
-         CLASS identifier_list ';'
+         AT_CLASS identifier_list ';'
                {
                  objc_declare_class ($2);
                }
        ;
 
 aliasdecl:
-         ALIAS identifier identifier ';'
+         AT_ALIAS identifier identifier ';'
                {
                  objc_declare_alias ($2, $3);
                }
        ;
 
-classdef:
-         INTERFACE identifier protocolrefs '{'
-               {
-                 objc_interface_context = objc_ivar_context
-                   = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
-                  objc_public_flag = 0;
-               }
-         ivar_decl_list '}'
-               {
-                  continue_class (objc_interface_context);
-               }
-         methodprotolist
-         END
-               {
-                 finish_class (objc_interface_context);
-                 objc_interface_context = NULL_TREE;
-               }
+superclass:
+         ':' identifier { $$ = $2; }
+       | /* NULL */ %prec HYPERUNARY    { $$ = NULL_TREE; }
+       ;
 
-       | INTERFACE identifier protocolrefs
-               {
-                 objc_interface_context
-                   = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
-                  continue_class (objc_interface_context);
-               }
-         methodprotolist
-         END
-               {
-                 finish_class (objc_interface_context);
-                 objc_interface_context = NULL_TREE;
-               }
+class_ivars:
+         '{' ivar_decl_list '}'
+       | /* NULL */
+       ;
 
-       | INTERFACE identifier ':' identifier protocolrefs '{'
+classdef:
+         AT_INTERFACE identifier superclass protocolrefs
                {
                  objc_interface_context = objc_ivar_context
-                   = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
+                   = start_class (CLASS_INTERFACE_TYPE, $2, $3, $4);
                   objc_public_flag = 0;
                }
-         ivar_decl_list '}'
+         class_ivars
                {
                   continue_class (objc_interface_context);
                }
-         methodprotolist
-         END
+         methodprotolist AT_END
                {
                  finish_class (objc_interface_context);
                  objc_interface_context = NULL_TREE;
                }
 
-       | INTERFACE identifier ':' identifier protocolrefs
-               {
-                 objc_interface_context
-                   = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
-                  continue_class (objc_interface_context);
-               }
-         methodprotolist
-         END
-               {
-                 finish_class (objc_interface_context);
-                 objc_interface_context = NULL_TREE;
-               }
-
-       | IMPLEMENTATION identifier '{'
-               {
-                 objc_implementation_context = objc_ivar_context
-                   = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
-                  objc_public_flag = 0;
-               }
-         ivar_decl_list '}'
-               {
-                  objc_ivar_chain
-                   = continue_class (objc_implementation_context);
-               }
-
-       | IMPLEMENTATION identifier
-               {
-                 objc_implementation_context
-                   = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
-                  objc_ivar_chain
-                   = continue_class (objc_implementation_context);
-               }
-
-       | IMPLEMENTATION identifier ':' identifier '{'
+       | AT_IMPLEMENTATION identifier superclass
                {
                  objc_implementation_context = objc_ivar_context
-                   = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
+                   = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $3, NULL_TREE);
                   objc_public_flag = 0;
                }
-         ivar_decl_list '}'
+         class_ivars
                {
                   objc_ivar_chain
                    = continue_class (objc_implementation_context);
                }
 
-       | IMPLEMENTATION identifier ':' identifier
-               {
-                 objc_implementation_context
-                   = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
-                  objc_ivar_chain
-                   = continue_class (objc_implementation_context);
-               }
-
-       | INTERFACE identifier '(' identifier ')' protocolrefs
+       | AT_INTERFACE identifier '(' identifier ')' protocolrefs
                {
                  objc_interface_context
                    = start_class (CATEGORY_INTERFACE_TYPE, $2, $4, $6);
                   continue_class (objc_interface_context);
                }
-         methodprotolist
-         END
+         methodprotolist AT_END
                {
                  finish_class (objc_interface_context);
                  objc_interface_context = NULL_TREE;
                }
 
-       | IMPLEMENTATION identifier '(' identifier ')'
+       | AT_IMPLEMENTATION identifier '(' identifier ')'
                {
                  objc_implementation_context
                    = start_class (CATEGORY_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
@@ -2841,13 +2739,13 @@ classdef:
        ;
 
 protocoldef:
-         PROTOCOL identifier protocolrefs
+         AT_PROTOCOL identifier protocolrefs
                {
                  objc_pq_context = 1;
                  objc_interface_context
                    = start_protocol(PROTOCOL_INTERFACE_TYPE, $2, $3);
                }
-         methodprotolist END
+         methodprotolist AT_END
                {
                  objc_pq_context = 0;
                  finish_protocol(objc_interface_context);
@@ -2856,7 +2754,7 @@ protocoldef:
        /* The @protocol forward-declaration production introduces a
           reduce/reduce conflict on ';', which should be resolved in
           favor of the production 'identifier_list -> identifier'.  */
-       | PROTOCOL identifier_list ';'
+       | AT_PROTOCOL identifier_list ';'
                {
                  objc_declare_protocols ($2);
                }
@@ -2886,9 +2784,9 @@ ivar_decl_list:
         ;
 
 visibility_spec:
-         PRIVATE { objc_public_flag = 2; }
-       | PROTECTED { objc_public_flag = 0; }
-       | PUBLIC { objc_public_flag = 1; }
+         AT_PRIVATE { objc_public_flag = 2; }
+       | AT_PROTECTED { objc_public_flag = 0; }
+       | AT_PUBLIC { objc_public_flag = 1; }
        ;
 
 ivar_decls:
@@ -2944,14 +2842,14 @@ ivar_declarator:
                {
                  $$ = add_instance_variable (objc_ivar_context,
                                              objc_public_flag,
-                                             $1, current_declspecs, $3);
+                                             $1, current_declspecs, $3.value);
                 }
        | ':' expr_no_commas
                {
                  $$ = add_instance_variable (objc_ivar_context,
                                              objc_public_flag,
                                              NULL_TREE,
-                                             current_declspecs, $2);
+                                             current_declspecs, $2.value);
                 }
        ;
 
@@ -2972,10 +2870,9 @@ methoddef:
          methoddecl
                {
                  objc_pq_context = 0;
-                 if (objc_inherit_code == CLASS_METHOD_DECL)
-                   add_class_method (objc_implementation_context, $3);
-                 else
-                   add_instance_method (objc_implementation_context, $3);
+                 objc_add_method (objc_implementation_context,
+                                  $3,
+                                  objc_inherit_code == CLASS_METHOD_DECL);
                  start_method_def ($3);
                }
          optarglist
@@ -2994,14 +2891,8 @@ methoddef:
 
 methodprotolist:
          /* empty  */
-       | {$<ttype>$ = NULL_TREE; } methodprotolist2
-       ;
-
-methodprotolist2:               /* eliminates a shift/reduce conflict */
-          methodproto
-       |  datadef
-       | methodprotolist2 methodproto
-       | methodprotolist2 {$<ttype>$ = NULL_TREE; } datadef
+       | methodprotolist methodproto
+       | methodprotolist { $<ttype>$ = NULL_TREE; } datadef
        ;
 
 semi_or_error:
@@ -3019,10 +2910,9 @@ methodproto:
                {
                  /* Forget protocol qualifiers here.  */
                  objc_pq_context = 0;
-                 if (objc_inherit_code == CLASS_METHOD_DECL)
-                   add_class_method (objc_interface_context, $3);
-                 else
-                   add_instance_method (objc_interface_context, $3);
+                 objc_add_method (objc_interface_context,
+                                  $3,
+                                  objc_inherit_code == CLASS_METHOD_DECL);
                }
          semi_or_error
        ;
@@ -3107,7 +2997,7 @@ myparm:
 optparmlist:
          /* empty */
                {
-                 $$ = NULL_TREE;
+                 $$ = NULL_TREE;
                }
        | ',' ELLIPSIS
                {
@@ -3116,13 +3006,13 @@ optparmlist:
                }
        | ','
                {
-                 pushlevel (0);
+                 push_scope ();
                }
          parmlist_2
                {
-                 /* returns a tree list node generated by get_parm_info */
+                 /* returns a tree list node generated by get_parm_info */
                  $$ = $3;
-                 poplevel (0, 0, 0);
+                 pop_scope ();
                }
        ;
 
@@ -3157,22 +3047,22 @@ reservedwords:
 keyworddecl:
          selector ':' '(' typename ')' identifier
                {
-                 $$ = build_keyword_decl ($1, $4, $6);
+                 $$ = objc_build_keyword_decl ($1, $4, $6);
                }
 
        | selector ':' identifier
                {
-                 $$ = build_keyword_decl ($1, NULL_TREE, $3);
+                 $$ = objc_build_keyword_decl ($1, NULL_TREE, $3);
                }
 
        | ':' '(' typename ')' identifier
                {
-                 $$ = build_keyword_decl (NULL_TREE, $3, $5);
+                 $$ = objc_build_keyword_decl (NULL_TREE, $3, $5);
                }
 
        | ':' identifier
                {
-                 $$ = build_keyword_decl (NULL_TREE, NULL_TREE, $2);
+                 $$ = objc_build_keyword_decl (NULL_TREE, NULL_TREE, $2);
                }
        ;
 
@@ -3215,9 +3105,14 @@ keywordarg:
 
 receiver:
          expr
+               { $$ = $1.value; }
        | CLASSNAME
                {
-                 $$ = get_class_reference ($1);
+                 $$ = objc_get_class_reference ($1);
+               }
+       | TYPENAME
+               {
+                 $$ = objc_get_class_reference ($1);
                }
        ;
 
@@ -3251,14 +3146,14 @@ keywordname:
        ;
 
 objcselectorexpr:
-         SELECTOR '(' selectorarg ')'
+         AT_SELECTOR '(' selectorarg ')'
                {
                  $$ = $3;
                }
        ;
 
 objcprotocolexpr:
-         PROTOCOL '(' identifier ')'
+         AT_PROTOCOL '(' identifier ')'
                {
                  $$ = $3;
                }
@@ -3267,13 +3162,13 @@ objcprotocolexpr:
 /* extension to support C-structures in the archiver */
 
 objcencodeexpr:
-         ENCODE '(' typename ')'
+         AT_ENCODE '(' typename ')'
                {
                  $$ = groktypename ($3);
                }
        ;
 
-end ifobjc
+@@end_ifobjc
 %%
 
 /* yylex() is a thin wrapper around c_lex(), all it does is translate
@@ -3308,9 +3203,8 @@ static const struct resword reswords[] =
   { "__asm__",         RID_ASM,        0 },
   { "__attribute",     RID_ATTRIBUTE,  0 },
   { "__attribute__",   RID_ATTRIBUTE,  0 },
-  { "__bounded",       RID_BOUNDED,    0 },
-  { "__bounded__",     RID_BOUNDED,    0 },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+  { "__builtin_offsetof", RID_OFFSETOF, 0 },
   { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
   { "__builtin_va_arg",        RID_VA_ARG,     0 },
   { "__complex",       RID_COMPLEX,    0 },
@@ -3339,8 +3233,6 @@ static const struct resword reswords[] =
   { "__thread",                RID_THREAD,     0 },
   { "__typeof",                RID_TYPEOF,     0 },
   { "__typeof__",      RID_TYPEOF,     0 },
-  { "__unbounded",     RID_UNBOUNDED,  0 },
-  { "__unbounded__",   RID_UNBOUNDED,  0 },
   { "__volatile",      RID_VOLATILE,   0 },
   { "__volatile__",    RID_VOLATILE,   0 },
   { "asm",             RID_ASM,        D_EXT },
@@ -3379,7 +3271,8 @@ static const struct resword reswords[] =
   { "void",            RID_VOID,       0 },
   { "volatile",                RID_VOLATILE,   0 },
   { "while",           RID_WHILE,      0 },
-ifobjc
+
+@@ifobjc
   { "id",              RID_ID,                 D_OBJC },
 
   /* These objc keywords are recognized only immediately after
@@ -3396,7 +3289,11 @@ ifobjc
   { "protocol",                RID_AT_PROTOCOL,        D_OBJC },
   { "public",          RID_AT_PUBLIC,          D_OBJC },
   { "selector",                RID_AT_SELECTOR,        D_OBJC },
-
+  { "throw",           RID_AT_THROW,           D_OBJC },
+  { "try",             RID_AT_TRY,             D_OBJC },
+  { "catch",           RID_AT_CATCH,           D_OBJC },
+  { "finally",         RID_AT_FINALLY,         D_OBJC },
+  { "synchronized",    RID_AT_SYNCHRONIZED,    D_OBJC },
   /* These are recognized only in protocol-qualifier context
      (see above) */
   { "bycopy",          RID_BYCOPY,             D_OBJC },
@@ -3405,7 +3302,7 @@ ifobjc
   { "inout",           RID_INOUT,              D_OBJC },
   { "oneway",          RID_ONEWAY,             D_OBJC },
   { "out",             RID_OUT,                D_OBJC },
-end ifobjc
+@@end_ifobjc
 };
 #define N_reswords (sizeof reswords / sizeof (struct resword))
 
@@ -3429,8 +3326,6 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_RESTRICT */   TYPE_QUAL,
 
   /* C extensions */
-  /* RID_BOUNDED */    TYPE_QUAL,
-  /* RID_UNBOUNDED */  TYPE_QUAL,
   /* RID_COMPLEX */    TYPESPEC,
   /* RID_THREAD */     SCSPEC,
 
@@ -3489,9 +3384,9 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_CHOOSE_EXPR */                        CHOOSE_EXPR,
   /* RID_TYPES_COMPATIBLE_P */         TYPES_COMPATIBLE_P,
 
-  /* RID_FUNCTION_NAME */              STRING_FUNC_NAME,
-  /* RID_PRETTY_FUNCTION_NAME */       STRING_FUNC_NAME,
-  /* RID_C99_FUNCTION_NAME */          VAR_FUNC_NAME,
+  /* RID_FUNCTION_NAME */              FUNC_NAME,
+  /* RID_PRETTY_FUNCTION_NAME */       FUNC_NAME,
+  /* RID_C99_FUNCTION_NAME */          FUNC_NAME,
 
   /* C++ */
   /* RID_BOOL */       TYPESPEC,
@@ -3507,6 +3402,7 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_FALSE */      0,
   /* RID_NAMESPACE */  0,
   /* RID_NEW */                0,
+  /* RID_OFFSETOF */    OFFSETOF,
   /* RID_OPERATOR */   0,
   /* RID_THIS */       0,
   /* RID_THROW */      0,
@@ -3524,35 +3420,37 @@ static const short rid_to_yy[RID_MAX] =
 
   /* Objective C */
   /* RID_ID */                 OBJECTNAME,
-  /* RID_AT_ENCODE */          ENCODE,
-  /* RID_AT_END */             END,
-  /* RID_AT_CLASS */           CLASS,
-  /* RID_AT_ALIAS */           ALIAS,
-  /* RID_AT_DEFS */            DEFS,
-  /* RID_AT_PRIVATE */         PRIVATE,
-  /* RID_AT_PROTECTED */       PROTECTED,
-  /* RID_AT_PUBLIC */          PUBLIC,
-  /* RID_AT_PROTOCOL */                PROTOCOL,
-  /* RID_AT_SELECTOR */                SELECTOR,
-  /* RID_AT_INTERFACE */       INTERFACE,
-  /* RID_AT_IMPLEMENTATION */  IMPLEMENTATION
+  /* RID_AT_ENCODE */          AT_ENCODE,
+  /* RID_AT_END */             AT_END,
+  /* RID_AT_CLASS */           AT_CLASS,
+  /* RID_AT_ALIAS */           AT_ALIAS,
+  /* RID_AT_DEFS */            AT_DEFS,
+  /* RID_AT_PRIVATE */         AT_PRIVATE,
+  /* RID_AT_PROTECTED */       AT_PROTECTED,
+  /* RID_AT_PUBLIC */          AT_PUBLIC,
+  /* RID_AT_PROTOCOL */                AT_PROTOCOL,
+  /* RID_AT_SELECTOR */                AT_SELECTOR,
+  /* RID_AT_THROW */           AT_THROW,
+  /* RID_AT_TRY */             AT_TRY,
+  /* RID_AT_CATCH */           AT_CATCH,
+  /* RID_AT_FINALLY */         AT_FINALLY,
+  /* RID_AT_SYNCHRONIZED */    AT_SYNCHRONIZED,
+  /* RID_AT_INTERFACE */       AT_INTERFACE,
+  /* RID_AT_IMPLEMENTATION */  AT_IMPLEMENTATION
 };
 
 static void
-init_reswords ()
+init_reswords (void)
 {
   unsigned int i;
   tree id;
   int mask = (flag_isoc99 ? 0 : D_C89)
              | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);
 
-  if (!flag_objc)
+  if (!c_dialect_objc ())
      mask |= D_OBJC;
 
-  /* It is not necessary to register ridpointers as a GC root, because
-     all the trees it points to are permanently interned in the
-     get_identifier hash anyway.  */
-  ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+  ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
   for (i = 0; i < N_reswords; i++)
     {
       /* If a keyword is disabled, do not enter it into the table
@@ -3570,48 +3468,26 @@ init_reswords ()
 #define NAME(type) cpp_type2name (type)
 
 static void
-yyerror (msgid)
-     const char *msgid;
+yyerror (const char *msgid)
 {
-  const char *string = _(msgid);
-
-  if (last_token == CPP_EOF)
-    error ("%s at end of input", string);
-  else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
-    {
-      unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
-      const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
-      if (val <= UCHAR_MAX && ISGRAPH (val))
-       error ("%s before %s'%c'", string, ell, val);
-      else
-       error ("%s before %s'\\x%x'", string, ell, val);
-    }
-  else if (last_token == CPP_STRING
-          || last_token == CPP_WSTRING)
-    error ("%s before string constant", string);
-  else if (last_token == CPP_NUMBER)
-    error ("%s before numeric constant", string);
-  else if (last_token == CPP_NAME)
-    error ("%s before \"%s\"", string, IDENTIFIER_POINTER (yylval.ttype));
-  else
-    error ("%s before '%s' token", string, NAME(last_token));
+  c_parse_error (msgid, last_token, yylval.ttype);
 }
 
 static int
-yylexname ()
+yylexname (void)
 {
   tree decl;
 
-ifobjc
+@@ifobjc
   int objc_force_identifier = objc_need_raw_identifier;
   OBJC_NEED_RAW_IDENTIFIER (0);
-end ifobjc
+@@end_ifobjc
 
   if (C_IS_RESERVED_WORD (yylval.ttype))
     {
       enum rid rid_code = C_RID_CODE (yylval.ttype);
 
-ifobjc
+@@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)
@@ -3623,24 +3499,11 @@ ifobjc
 
       if (!OBJC_IS_AT_KEYWORD (rid_code)
          && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
-end ifobjc
+@@end_ifobjc
       {
-       int yycode = rid_to_yy[(int) rid_code];
-       if (yycode == STRING_FUNC_NAME)
-         {
-           /* __FUNCTION__ and __PRETTY_FUNCTION__ get converted
-              to string constants.  */
-           const char *name = fname_string (rid_code);
-
-           yylval.ttype = build_string (strlen (name) + 1, name);
-           C_ARTIFICIAL_STRING_P (yylval.ttype) = 1;
-           last_token = CPP_STRING;  /* so yyerror won't choke */
-           return STRING;
-         }
-
        /* Return the canonical spelling for this keyword.  */
        yylval.ttype = ridpointers[(int) rid_code];
-       return yycode;
+       return rid_to_yy[(int) rid_code];
       }
     }
 
@@ -3650,10 +3513,10 @@ end ifobjc
       if (TREE_CODE (decl) == TYPE_DECL)
        return TYPENAME;
     }
-ifobjc
+@@ifobjc
   else
     {
-      tree objc_interface_decl = is_class_name (yylval.ttype);
+      tree objc_interface_decl = objc_is_class_name (yylval.ttype);
       /* ObjC class names are in the same namespace as variables and
         typedefs, and hence are shadowed by local declarations.  */
       if (objc_interface_decl
@@ -3664,65 +3527,13 @@ ifobjc
          return CLASSNAME;
        }
     }
-end ifobjc
+@@end_ifobjc
 
   return IDENTIFIER;
 }
 
-/* Concatenate strings before returning them to the parser.  This isn't quite
-   as good as having it done in the lexer, but it's better than nothing.  */
-
-static int
-yylexstring ()
-{
-  enum cpp_ttype next_type;
-  tree orig = yylval.ttype;
-
-  next_type = c_lex (&yylval.ttype);
-  if (next_type == CPP_STRING
-      || next_type == CPP_WSTRING
-      || (next_type == CPP_NAME && yylexname () == STRING))
-    {
-      varray_type strings;
-
-ifc
-      static int last_lineno = 0;
-      static const char *last_input_filename = 0;
-      if (warn_traditional && !in_system_header
-         && (lineno != last_lineno || !last_input_filename ||
-             strcmp (last_input_filename, input_filename)))
-       {
-         warning ("traditional C rejects string concatenation");
-         last_lineno = lineno;
-         last_input_filename = input_filename;
-       }
-end ifc
-
-      VARRAY_TREE_INIT (strings, 32, "strings");
-      VARRAY_PUSH_TREE (strings, orig);
-
-      do
-       {
-         VARRAY_PUSH_TREE (strings, yylval.ttype);
-         next_type = c_lex (&yylval.ttype);
-       }
-      while (next_type == CPP_STRING
-            || next_type == CPP_WSTRING
-            || (next_type == CPP_NAME && yylexname () == STRING));
-
-      yylval.ttype = combine_strings (strings);
-    }
-  else
-    yylval.ttype = orig;
-
-  /* We will have always read one token too many.  */
-  _cpp_backup_tokens (parse_in, 1);
-
-  return STRING;
-}
-
 static inline int
-_yylex ()
+_yylex (void)
 {
  get_next:
   last_token = c_lex (&yylval.ttype);
@@ -3786,13 +3597,11 @@ _yylex ()
       return 0;
 
     case CPP_NAME:
-      {
-       int ret = yylexname ();
-       if (ret == STRING)
-         return yylexstring ();
-       else
-         return ret;
-      }
+      return yylexname ();
+
+    case CPP_AT_NAME:
+      /* This only happens in Objective-C; it must be a keyword.  */
+      return rid_to_yy [(int) C_RID_CODE (yylval.ttype)];
 
     case CPP_NUMBER:
     case CPP_CHAR:
@@ -3801,30 +3610,10 @@ _yylex ()
 
     case CPP_STRING:
     case CPP_WSTRING:
-      return yylexstring ();
+      return STRING;
 
-      /* This token is Objective-C specific.  It gives the next token
-        special significance.  */
-    case CPP_ATSIGN:
-ifobjc
-      {
-       tree after_at;
-       enum cpp_ttype after_at_type;
-
-       after_at_type = c_lex (&after_at);
-
-       if (after_at_type == CPP_NAME
-           && C_IS_RESERVED_WORD (after_at)
-           && OBJC_IS_AT_KEYWORD (C_RID_CODE (after_at)))
-         {
-           yylval.ttype = after_at;
-           last_token = after_at_type;
-           return rid_to_yy [(int) C_RID_CODE (after_at)];
-         }
-       _cpp_backup_tokens (parse_in, 1);
-       return '@';
-      }
-end ifobjc
+    case CPP_OBJC_STRING:
+      return OBJC_STRING;
 
       /* These tokens are C++ specific (and will not be generated
          in C mode, but let's be cautious).  */
@@ -3848,7 +3637,7 @@ end ifobjc
 }
 
 static int
-yylex()
+yylex (void)
 {
   int r;
   timevar_push (TV_LEX);
@@ -3860,10 +3649,7 @@ yylex()
 /* Function used when yydebug is set, to print a token in more detail.  */
 
 static void
-yyprint (file, yychar, yyl)
-     FILE *file;
-     int yychar;
-     YYSTYPE yyl;
+yyprint (FILE *file, int yychar, YYSTYPE yyl)
 {
   tree t = yyl.ttype;
 
@@ -3885,41 +3671,29 @@ yyprint (file, yychar, yyl)
     case CONSTANT:
       fprintf (file, " %s", GET_MODE_NAME (TYPE_MODE (TREE_TYPE (t))));
       if (TREE_CODE (t) == INTEGER_CST)
-       fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-                " 0x%x%016x",
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-                " 0x%lx%016lx",
-#else
-                " 0x%llx%016llx",
-#endif
-#endif
-#else
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
-                " 0x%lx%08lx",
-#else
-                " 0x%x%08x",
-#endif
-#endif
-                TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+       {
+         fputs (" ", file);
+         fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+                  TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+       }
       break;
     }
 }
 \f
-/* This is not the ideal place to put these, but we have to get them out
-   of c-lex.c because cp/lex.c has its own versions.  */
-
-/* Free malloced parser stacks if necessary.  */
+/* This is not the ideal place to put this, but we have to get it out
+   of c-lex.c because cp/lex.c has its own version.  */
 
+/* Parse the file.  */
 void
-free_parser_stacks ()
+c_parse_file (void)
 {
+  yyparse ();
+
   if (malloced_yyss)
     {
       free (malloced_yyss);
       free (malloced_yyvs);
+      malloced_yyss = 0;
     }
 }