OSDN Git Service

2001-12-13 Aldy Hernandez <aldyh@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.in
index e64e140..4967a09 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
    1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+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.
@@ -29,16 +29,15 @@ Boston, MA 02111-1307, USA.  */
    written by AT&T, but I have never seen it.  */
 
 ifobjc
-%expect 31
+%expect 31 /* shift/reduce conflicts, and 1 reduce/reduce conflict.  */
 end ifobjc
 ifc
-%expect 10
+%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts.  */
 end ifc
 
 %{
 #include "config.h"
 #include "system.h"
-#include <setjmp.h>
 #include "tree.h"
 #include "input.h"
 #include "cpplib.h"
@@ -60,15 +59,6 @@ ifobjc
 #include "objc-act.h"
 end ifobjc
 
-/* Since parsers are distinct for each language, put the language string
-   definition here.  */
-ifobjc
-const char * const language_string = "GNU Objective-C";
-end ifobjc
-ifc
-const char * const language_string = "GNU C";
-end ifc
-
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
 
@@ -121,7 +111,7 @@ end ifc
 %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
 %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
 %token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART VA_ARG
+%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. */
@@ -156,11 +146,6 @@ end ifc
 %token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE
 %token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
 
-/* Objective-C string constants in raw form.
-   yylval is an STRING_CST node.  */
-%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
@@ -178,7 +163,7 @@ end ifc
 %type <ttype> declspecs_ts declspecs_nots
 %type <ttype> declspecs_ts_nosa declspecs_nots_nosa
 %type <ttype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
-%type <ttype> maybe_type_quals_setattrs typespec_nonattr typespec_attr
+%type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
 %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
 %type <ttype> typespec_nonreserved_nonattr
 
@@ -187,7 +172,6 @@ end ifc
 %type <ttype> init maybeasm
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> maybe_setattrs
 %type <ttype> any_word extension
 
 %type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
@@ -230,7 +214,7 @@ ifobjc
 %type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
 %type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
 
-%type <ttype> CLASSNAME OBJC_STRING OBJECTNAME
+%type <ttype> CLASSNAME OBJECTNAME
 end ifobjc
 \f
 %{
@@ -248,9 +232,33 @@ static int if_stmt_line;
 static tree current_declspecs = NULL_TREE;
 static tree prefix_attributes = NULL_TREE;
 
-/* Stack of saved values of current_declspecs and prefix_attributes.  */
+/* List of all the attributes applying to the identifier currently being
+   declared; includes prefix_attributes and possibly some more attributes
+   just after a comma.  */
+static tree all_prefix_attributes = NULL_TREE;
+
+/* Stack of saved values of current_declspecs, prefix_attributes and
+   all_prefix_attributes.  */
 static tree declspec_stack;
 
+/* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
+   should be called from the productions making use of setspecs.  */
+#define PUSH_DECLSPEC_STACK                                             \
+  do {                                                                  \
+    declspec_stack = tree_cons (build_tree_list (prefix_attributes,     \
+                                                all_prefix_attributes), \
+                               current_declspecs,                       \
+                               declspec_stack);                         \
+  } while (0)
+
+#define POP_DECLSPEC_STACK                                             \
+  do {                                                                 \
+    current_declspecs = TREE_VALUE (declspec_stack);                   \
+    prefix_attributes = TREE_PURPOSE (TREE_PURPOSE (declspec_stack));  \
+    all_prefix_attributes = TREE_VALUE (TREE_PURPOSE (declspec_stack));        \
+    declspec_stack = TREE_CHAIN (declspec_stack);                      \
+  } while (0)
+
 /* For __extension__, save/restore the warning flags which are
    controlled by __extension__.  */
 #define SAVE_WARN_FLAGS()      \
@@ -263,20 +271,23 @@ static tree declspec_stack;
   } while (0)
 
 ifobjc
-/* Objective-C specific information */
-
-tree objc_interface_context;
-tree objc_implementation_context;
-tree objc_method_context;
-tree objc_ivar_chain;
-tree objc_ivar_context;
-enum tree_code objc_inherit_code;
-int objc_receiver_context;
-int objc_public_flag;
-int objc_pq_context;
+/* Objective-C specific parser/lexer information */
 
+static enum tree_code objc_inherit_code;
+static int objc_pq_context = 0, objc_public_flag = 0;
+
+/* The following flag is needed to contextualize ObjC lexical analysis.
+   In some cases (e.g., 'int NSObject;'), it is undesirable to bind 
+   an identifier to an ObjC class, even if a class with that name 
+   exists.  */
+static int objc_need_raw_identifier;
+#define OBJC_NEED_RAW_IDENTIFIER(VAL)  objc_need_raw_identifier = VAL
 end ifobjc
 
+ifc
+#define OBJC_NEED_RAW_IDENTIFIER(VAL)  /* nothing */
+end ifc
+
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
 
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -292,16 +303,12 @@ static void init_reswords PARAMS ((void));
 void
 c_parse_init ()
 {
+  init_reswords ();
+
   ggc_add_tree_root (&declspec_stack, 1);
   ggc_add_tree_root (&current_declspecs, 1);
   ggc_add_tree_root (&prefix_attributes, 1);
-ifobjc
-  ggc_add_tree_root (&objc_interface_context, 1);
-  ggc_add_tree_root (&objc_implementation_context, 1);
-  ggc_add_tree_root (&objc_method_context, 1);
-  ggc_add_tree_root (&objc_ivar_chain, 1);
-  ggc_add_tree_root (&objc_ivar_context, 1);
-end ifobjc
+  ggc_add_tree_root (&all_prefix_attributes, 1);
 }
 
 %}
@@ -359,17 +366,11 @@ datadef:
                  else if (!flag_traditional)
                    warning ("data definition has no type or storage class"); 
 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
         | declspecs_nots setspecs notype_initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs ';'
          { shadow_tag ($1); }
        | error ';'
@@ -382,7 +383,7 @@ datadef:
 fndef:
          declspecs_ts setspecs declarator
                { if (! start_function (current_declspecs, $3,
-                                       prefix_attributes, NULL_TREE))
+                                       all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls
@@ -391,16 +392,12 @@ fndef:
                { DECL_SOURCE_FILE (current_function_decl) = $7;
                  DECL_SOURCE_LINE (current_function_decl) = $8;
                  finish_function (0); 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs declarator error
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator
                { if (! start_function (current_declspecs, $3,
-                                       prefix_attributes, NULL_TREE))
+                                       all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls
@@ -409,16 +406,12 @@ fndef:
                { DECL_SOURCE_FILE (current_function_decl) = $7;
                  DECL_SOURCE_LINE (current_function_decl) = $8;
                  finish_function (0); 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator error
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | setspecs notype_declarator
                { if (! start_function (NULL_TREE, $2,
-                                       prefix_attributes, NULL_TREE))
+                                       all_prefix_attributes))
                    YYERROR1;
                }
          old_style_parm_decls
@@ -427,13 +420,9 @@ fndef:
                { DECL_SOURCE_FILE (current_function_decl) = $6;
                  DECL_SOURCE_LINE (current_function_decl) = $7;
                  finish_function (0); 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | setspecs notype_declarator error
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        ;
 
 identifier:
@@ -441,7 +430,7 @@ identifier:
        | TYPENAME
 ifobjc
        | OBJECTNAME
-        | CLASSNAME
+       | CLASSNAME
 end ifobjc
        ;
 
@@ -608,8 +597,7 @@ expr_no_commas:
                { char class;
                  $$ = build_modify_expr ($1, NOP_EXPR, $3);
                  class = TREE_CODE_CLASS (TREE_CODE ($$));
-                 if (class == 'e' || class == '1'
-                     || class == '2' || class == '<')
+                 if (IS_EXPR_CODE_CLASS (class))
                    C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
                }
        | expr_no_commas ASSIGN expr_no_commas
@@ -617,8 +605,7 @@ expr_no_commas:
                  $$ = build_modify_expr ($1, $2, $3);
                  /* This inhibits warnings in truthvalue_conversion.  */
                  class = TREE_CODE_CLASS (TREE_CODE ($$));
-                 if (class == 'e' || class == '1'
-                     || class == '2' || class == '<')
+                 if (IS_EXPR_CODE_CLASS (class))
                    C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
                }
        ;
@@ -640,34 +627,17 @@ primary:
                  $2 = groktypename ($2);
                  really_start_incremental_init ($2); }
          initlist_maybe_comma '}'  %prec UNARY
-               { const char *name;
-                 tree result = pop_init_level (0);
+               { tree constructor = pop_init_level (0);
                  tree type = $2;
                  finish_init ();
 
                  if (pedantic && ! flag_isoc99)
                    pedwarn ("ISO C89 forbids compound literals");
-                 if (TYPE_NAME (type) != 0)
-                   {
-                     if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-                       name = IDENTIFIER_POINTER (TYPE_NAME (type));
-                     else
-                       name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
-                   }
-                 else
-                   name = "";
-                 $$ = result;
-                 if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
-                   {
-                     int failure = complete_array_type (type, $$, 1);
-                     if (failure)
-                       abort ();
-                   }
+                 $$ = build_compound_literal (type, constructor);
                }
        | '(' expr ')'
                { char class = TREE_CODE_CLASS (TREE_CODE ($2));
-                 if (class == 'e' || class == '1'
-                     || class == '2' || class == '<')
+                 if (IS_EXPR_CODE_CLASS (class))
                    C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
                  $$ = $2; }
        | '(' error ')'
@@ -699,6 +669,26 @@ primary:
                { $$ = build_function_call ($1, $3); }
        | VA_ARG '(' expr_no_commas ',' typename ')'
                { $$ = build_va_arg ($3, groktypename ($5)); }
+      | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')'
+               {
+                  tree c;
+
+                  c = fold ($3);
+                  STRIP_NOPS (c);
+                  if (TREE_CODE (c) != INTEGER_CST)
+                    error ("first argument to __builtin_choose_expr not a constant");
+                  $$ = integer_zerop (c) ? $7 : $5;
+               }
+      | 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);
+               }
        | primary '[' expr ']'   %prec '.'
                { $$ = build_array_ref ($1, $3); }
        | primary '.' identifier
@@ -766,9 +756,10 @@ 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:
-         OBJC_STRING
-       | objc_string OBJC_STRING
-               { $$ = chainon ($1, $2); }
+         '@' STRING
+               { $$ = $2; }
+       | objc_string '@' STRING
+               { $$ = chainon ($1, $3); }
        ;
 end ifobjc
 
@@ -803,13 +794,9 @@ datadecls:
    style parm.  */
 datadecl:
        declspecs_ts_nosa setspecs initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_nots_nosa setspecs notype_initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);      
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa ';'
                { shadow_tag_warned ($1, 1);
                  pedwarn ("empty declaration"); }
@@ -832,48 +819,28 @@ lineno_decl:
    for the sake of parm declarations nested in function declarators.  */
 setspecs: /* empty */
                { pending_xref_error ();
-                 declspec_stack = tree_cons (prefix_attributes,
-                                             current_declspecs,
-                                             declspec_stack);
+                 PUSH_DECLSPEC_STACK;
                  split_specs_attrs ($<ttype>0,
-                                    &current_declspecs, &prefix_attributes); }
-       ;
-
-/* ??? Yuck.  See maybe_setattrs.  */
-setattrs: /* empty */
-               { prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
+                                    &current_declspecs, &prefix_attributes);
+                 all_prefix_attributes = prefix_attributes; }
        ;
 
-maybe_setattrs:
-       /* ??? Yuck.  setattrs is a quick hack.  We can't use
-          prefix_attributes because $1 only applies to this
-          declarator.  We assume setspecs has already been done.
-          setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
-          attributes could be recognized here or in `attributes').
-          Properly attributes ought to be able to apply to any level of
-          nested declarator, but the necessary compiler support isn't
-          present, so the attributes apply to a declaration (which may be
-          nested).  */
-         maybe_attribute setattrs
+/* Possibly attributes after a comma, which should reset all_prefix_attributes
+   to prefix_attributes with these ones chained on the front.  */
+maybe_resetattrs:
+         maybe_attribute
+               { all_prefix_attributes = chainon ($1, prefix_attributes); }
        ;
 
 decl:
        declspecs_ts setspecs initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_initdecls ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs nested_function
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_nested_function
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs ';'
                { shadow_tag ($1); }
        | extension decl
@@ -1340,18 +1307,12 @@ declspecs:
        | declspecs_sc_ts_sa_ea
        ;
 
-/* A (possibly empty) sequence of type qualifiers and attributes, to be
-   followed by the effect of setattrs if any attributes were present.  */
-maybe_type_quals_setattrs:
+/* A (possibly empty) sequence of type qualifiers and attributes.  */
+maybe_type_quals_attrs:
          /* empty */
                { $$ = NULL_TREE; }
        | declspecs_nosc_nots
-               { tree specs, attrs;
-                 split_specs_attrs ($1, &specs, &attrs);
-                 /* ??? Yuck.  See maybe_setattrs.  */
-                 if (attrs != NULL_TREE)
-                   prefix_attributes = chainon (prefix_attributes, attrs);
-                 $$ = specs; }
+               { $$ = $1; }
        ;
 
 /* A type specifier (but not a type qualifier).
@@ -1386,6 +1347,7 @@ typespec_attr:
 
 typespec_reserved_nonattr:
          TYPESPEC
+               { OBJC_NEED_RAW_IDENTIFIER (1); }
        | structsp_nonattr
        ;
 
@@ -1419,12 +1381,12 @@ end ifobjc
 
 initdecls:
        initdcl
-       | initdecls ',' maybe_setattrs initdcl
+       | initdecls ',' maybe_resetattrs initdcl
        ;
 
 notype_initdecls:
        notype_initdcl
-       | notype_initdecls ',' maybe_setattrs notype_initdcl
+       | notype_initdecls ',' maybe_resetattrs notype_initdcl
        ;
 
 maybeasm:
@@ -1439,7 +1401,7 @@ maybeasm:
 initdcl:
          declarator maybeasm maybe_attribute '='
                { $<ttype>$ = start_decl ($1, current_declspecs, 1,
-                                         $3, prefix_attributes);
+                                         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! */
@@ -1447,7 +1409,7 @@ initdcl:
                  finish_decl ($<ttype>5, $6, $2); }
        | declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, 0,
-                                      $3, prefix_attributes);
+                                      chainon ($3, all_prefix_attributes));
                  finish_decl (d, NULL_TREE, $2); 
                 }
        ;
@@ -1455,16 +1417,15 @@ initdcl:
 notype_initdcl:
          notype_declarator maybeasm maybe_attribute '='
                { $<ttype>$ = start_decl ($1, current_declspecs, 1,
-                                         $3, prefix_attributes);
+                                         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 ();
-                 decl_attributes ($<ttype>5, $3, prefix_attributes);
                  finish_decl ($<ttype>5, $6, $2); }
        | notype_declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, 0,
-                                      $3, prefix_attributes);
+                                      chainon ($3, all_prefix_attributes));
                  finish_decl (d, NULL_TREE, $2); }
        ;
 /* the * rules are dummies to accept the Apollo extended syntax
@@ -1598,7 +1559,7 @@ nested_function:
 
                  push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, NULL_TREE))
+                                       all_prefix_attributes))
                    {
                      pop_function_context ();
                      YYERROR1;
@@ -1628,7 +1589,7 @@ notype_nested_function:
 
                  push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, NULL_TREE))
+                                       all_prefix_attributes))
                    {
                      pop_function_context ();
                      YYERROR1;
@@ -1662,8 +1623,8 @@ declarator:
 /* A declarator that is allowed only after an explicit typespec.  */
 
 after_type_declarator:
-         '(' maybe_setattrs after_type_declarator ')'
-               { $$ = $3; }
+         '(' maybe_attribute after_type_declarator ')'
+               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
        | after_type_declarator '(' parmlist_or_identifiers  %prec '.'
                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
 /*     | after_type_declarator '(' error ')'  %prec '.'
@@ -1671,7 +1632,7 @@ after_type_declarator:
                  poplevel (0, 0, 0); }  */
        | after_type_declarator array_declarator  %prec '.'
                { $$ = set_array_declarator_type ($2, $1, 0); }
-       | '*' maybe_type_quals_setattrs after_type_declarator  %prec UNARY
+       | '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
        | TYPENAME
 ifobjc
@@ -1697,6 +1658,9 @@ parm_declarator_starttypename:
        | parm_declarator_starttypename array_declarator  %prec '.'
                { $$ = set_array_declarator_type ($2, $1, 0); }
        | TYPENAME
+ifobjc
+       | OBJECTNAME
+end ifobjc
        ;
 
 parm_declarator_nostarttypename:
@@ -1707,12 +1671,12 @@ parm_declarator_nostarttypename:
                  poplevel (0, 0, 0); }  */
        | parm_declarator_nostarttypename array_declarator  %prec '.'
                { $$ = set_array_declarator_type ($2, $1, 0); }
-       | '*' maybe_type_quals_setattrs parm_declarator_starttypename  %prec UNARY
+       | '*' maybe_type_quals_attrs parm_declarator_starttypename  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
-       | '*' maybe_type_quals_setattrs parm_declarator_nostarttypename  %prec UNARY
+       | '*' maybe_type_quals_attrs parm_declarator_nostarttypename  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
-       | '(' maybe_setattrs parm_declarator_nostarttypename ')'
-               { $$ = $3; }
+       | '(' maybe_attribute parm_declarator_nostarttypename ')'
+               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
        ;
 
 /* A declarator allowed whether or not there has been
@@ -1724,9 +1688,9 @@ notype_declarator:
 /*     | notype_declarator '(' error ')'  %prec '.'
                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                  poplevel (0, 0, 0); }  */
-       | '(' maybe_setattrs notype_declarator ')'
-               { $$ = $3; }
-       | '*' maybe_type_quals_setattrs notype_declarator  %prec UNARY
+       | '(' maybe_attribute notype_declarator ')'
+               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $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); }
@@ -1841,7 +1805,7 @@ ifobjc
                    $$ = get_class_ivars (interface);
                  else
                    {
-                     error ("Cannot find interface declaration for `%s'",
+                     error ("cannot find interface declaration for `%s'",
                             IDENTIFIER_POINTER ($3));
                      $$ = NULL_TREE;
                    }
@@ -1852,9 +1816,7 @@ end ifobjc
 component_decl:
          declspecs_nosc_ts setspecs components
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nosc_ts setspecs save_filename save_lineno
                {
                  /* Support for unnamed structs or unions as members of 
@@ -1864,15 +1826,10 @@ component_decl:
                    pedwarn ("ISO C doesn't support unnamed structs/unions");
 
                  $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-               }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nosc_nots setspecs components_notype
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nosc_nots
                { if (pedantic)
                    pedwarn ("ISO C forbids member declarations with no members");
@@ -1887,40 +1844,40 @@ component_decl:
 
 components:
          component_declarator
-       | components ',' maybe_setattrs component_declarator
+       | components ',' maybe_resetattrs component_declarator
                { $$ = chainon ($1, $4); }
        ;
 
 components_notype:
          component_notype_declarator
-       | components_notype ',' maybe_setattrs component_notype_declarator
+       | components_notype ',' maybe_resetattrs component_notype_declarator
                { $$ = chainon ($1, $4); }
        ;
 
 component_declarator:
          save_filename save_lineno declarator maybe_attribute
                { $$ = grokfield ($1, $2, $3, current_declspecs, NULL_TREE);
-                 decl_attributes ($$, $4, prefix_attributes); }
+                 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 ($$, $6, prefix_attributes); }
+                 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 ($$, $5, prefix_attributes); }
+                 decl_attributes (&$$, chainon ($5, 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 ($$, $4, prefix_attributes); }
+                 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 ($$, $6, prefix_attributes); }
+                 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 ($$, $5, prefix_attributes); }
+                 decl_attributes (&$$, chainon ($5, all_prefix_attributes), 0); }
        ;
 
 /* We chain the enumerators in reverse order.
@@ -1970,18 +1927,15 @@ absdcl_maybe_attribute:   /* absdcl maybe_attribute, but not just attributes */
        /* empty */
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         NULL_TREE),
-                                       build_tree_list (prefix_attributes,
-                                                        NULL_TREE)); }
+                                       all_prefix_attributes); }
        | absdcl1
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $1),
-                                       build_tree_list (prefix_attributes,
-                                                        NULL_TREE)); }
+                                       all_prefix_attributes); }
        | absdcl1_noea attributes
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $1),
-                                       build_tree_list (prefix_attributes,
-                                                        $2)); }
+                                       chainon ($2, all_prefix_attributes)); }
        ;
 
 absdcl1:  /* a nonempty absolute declarator */
@@ -1991,20 +1945,20 @@ absdcl1:  /* a nonempty absolute declarator */
 
 absdcl1_noea:
          direct_absdcl1
-       | '*' maybe_type_quals_setattrs absdcl1_noea
+       | '*' maybe_type_quals_attrs absdcl1_noea
                { $$ = make_pointer_declarator ($2, $3); }
        ;
 
 absdcl1_ea:
-         '*' maybe_type_quals_setattrs
+         '*' maybe_type_quals_attrs
                { $$ = make_pointer_declarator ($2, NULL_TREE); }
-       | '*' maybe_type_quals_setattrs absdcl1_ea
+       | '*' maybe_type_quals_attrs absdcl1_ea
                { $$ = make_pointer_declarator ($2, $3); }
        ;
 
 direct_absdcl1:
-         '(' maybe_setattrs absdcl1 ')'
-               { $$ = $3; }
+         '(' maybe_attribute absdcl1 ')'
+               { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
        | direct_absdcl1 '(' parmlist
                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
        | direct_absdcl1 array_declarator
@@ -2295,7 +2249,7 @@ lineno_stmt:
                      /* ??? 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 ocurr when
+                        but I suspect that problems will occur when
                         doing inlining at the tree level.  */
                    }
                }
@@ -2454,7 +2408,7 @@ label:      CASE expr_no_commas ':'
                  stmt_count++;
                  if (label)
                    {
-                     decl_attributes (label, $5, NULL_TREE);
+                     decl_attributes (&label, $5, 0);
                      $$ = add_stmt (build_stmt (LABEL_STMT, label));
                    }
                  else
@@ -2493,7 +2447,9 @@ nonnull_asm_operands:
 
 asm_operand:
          STRING '(' expr ')'
-               { $$ = build_tree_list ($1, $3); }
+               { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
+       | '[' identifier ']' STRING '(' expr ')'
+               { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
        ;
 
 asm_clobbers:
@@ -2571,38 +2527,25 @@ parm:
          declspecs_ts setspecs parm_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4));
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes));
+                 POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4)); 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes)); 
+                 POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs absdcl_maybe_attribute
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4));
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes));
+                 POP_DECLSPEC_STACK; }
 
        | declspecs_nots setspecs absdcl_maybe_attribute
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        ;
 
 /* The first parm, which must suck attributes from off the top of the parser
@@ -2611,43 +2554,31 @@ firstparm:
          declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4));
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes));
+                 POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4)); 
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes)); 
+                 POP_DECLSPEC_STACK; }
        | declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $3),
-                                       build_tree_list (prefix_attributes,
-                                                        $4));
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                                       chainon ($4, all_prefix_attributes));
+                 POP_DECLSPEC_STACK; }
 
        | declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        ;
 
 setspecs_fp:
          setspecs
-               { prefix_attributes = chainon (prefix_attributes, $<ttype>-2); }
+               { prefix_attributes = chainon (prefix_attributes, $<ttype>-2);
+                 all_prefix_attributes = prefix_attributes; }
        ;
 
 /* This is used in a function definition
@@ -2874,6 +2805,13 @@ protocoldef:
                  finish_protocol(objc_interface_context);
                  objc_interface_context = NULL_TREE;
                }
+       /* 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 ';'
+               {
+                 objc_declare_protocols ($2);
+               }
        ;
 
 protocolrefs:
@@ -2931,14 +2869,10 @@ ivar_decls:
 ivar_decl:
        declspecs_nosc_ts setspecs ivars
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | declspecs_nosc_nots setspecs ivars
                { $$ = $3;
-                 current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+                 POP_DECLSPEC_STACK; }
        | error
                { $$ = NULL_TREE; }
        ;
@@ -2947,7 +2881,7 @@ ivars:
          /* empty */
                { $$ = NULL_TREE; }
        | ivar_declarator
-       | ivars ',' maybe_setattrs ivar_declarator
+       | ivars ',' maybe_resetattrs ivar_declarator
        ;
 
 ivar_declarator:
@@ -2995,7 +2929,6 @@ methoddef:
                  else
                    add_instance_method (objc_implementation_context, $3);
                  start_method_def ($3);
-                 objc_method_context = $3;
                }
          optarglist
                {
@@ -3004,7 +2937,6 @@ methoddef:
          compstmt_or_error
                {
                  finish_method_def ();
-                 objc_method_context = NULL_TREE;
                }
        ;
 
@@ -3094,9 +3026,7 @@ mydecls:
 
 mydecl:
        declspecs_ts setspecs myparms ';'
-               { current_declspecs = TREE_VALUE (declspec_stack);
-                 prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack); }
+               { POP_DECLSPEC_STACK; }
        | declspecs_ts ';'
                { shadow_tag ($1); }
        | declspecs_nots ';'
@@ -3117,13 +3047,11 @@ myparm:
          parm_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $1),
-                                       build_tree_list (prefix_attributes,
-                                                        $2)); }
+                                       chainon ($2, all_prefix_attributes)); }
        | notype_declarator maybe_attribute
                { $$ = build_tree_list (build_tree_list (current_declspecs,
                                                         $1),
-                                       build_tree_list (prefix_attributes,
-                                                        $2)); }
+                                       chainon ($2, all_prefix_attributes)); }
        | absdcl_maybe_attribute
                { $$ = $1; }
        ;
@@ -3165,8 +3093,9 @@ keywordselector:
 
 selector:
          IDENTIFIER
-        | TYPENAME
-       | OBJECTNAME
+       | TYPENAME
+       | CLASSNAME
+       | OBJECTNAME
        | reservedwords
        ;
 
@@ -3340,6 +3269,8 @@ static const struct resword reswords[] =
   { "__attribute__",   RID_ATTRIBUTE,  0 },
   { "__bounded",       RID_BOUNDED,    0 },
   { "__bounded__",     RID_BOUNDED,    0 },
+  { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+  { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
   { "__builtin_va_arg",        RID_VA_ARG,     0 },
   { "__complex",       RID_COMPLEX,    0 },
   { "__complex__",     RID_COMPLEX,    0 },
@@ -3407,19 +3338,25 @@ static const struct resword reswords[] =
   { "volatile",                RID_VOLATILE,   D_TRAD },
   { "while",           RID_WHILE,      0 },
 ifobjc
-  { "@class",          RID_AT_CLASS,           D_OBJC },
-  { "@compatibility_alias", RID_AT_ALIAS,      D_OBJC },
-  { "@defs",           RID_AT_DEFS,            D_OBJC },
-  { "@encode",         RID_AT_ENCODE,          D_OBJC },
-  { "@end",            RID_AT_END,             D_OBJC },
-  { "@implementation", RID_AT_IMPLEMENTATION,  D_OBJC },
-  { "@interface",      RID_AT_INTERFACE,       D_OBJC },
-  { "@private",                RID_AT_PRIVATE,         D_OBJC },
-  { "@protected",      RID_AT_PROTECTED,       D_OBJC },
-  { "@protocol",       RID_AT_PROTOCOL,        D_OBJC },
-  { "@public",         RID_AT_PUBLIC,          D_OBJC },
-  { "@selector",       RID_AT_SELECTOR,        D_OBJC },
   { "id",              RID_ID,                 D_OBJC },
+
+  /* These objc keywords are recognized only immediately after
+     an '@'.  */
+  { "class",           RID_AT_CLASS,           D_OBJC },
+  { "compatibility_alias", RID_AT_ALIAS,       D_OBJC },
+  { "defs",            RID_AT_DEFS,            D_OBJC },
+  { "encode",          RID_AT_ENCODE,          D_OBJC },
+  { "end",             RID_AT_END,             D_OBJC },
+  { "implementation",  RID_AT_IMPLEMENTATION,  D_OBJC },
+  { "interface",       RID_AT_INTERFACE,       D_OBJC },
+  { "private",         RID_AT_PRIVATE,         D_OBJC },
+  { "protected",       RID_AT_PROTECTED,       D_OBJC },
+  { "protocol",                RID_AT_PROTOCOL,        D_OBJC },
+  { "public",          RID_AT_PUBLIC,          D_OBJC },
+  { "selector",                RID_AT_SELECTOR,        D_OBJC },
+
+  /* These are recognized only in protocol-qualifier context
+     (see above) */
   { "bycopy",          RID_BYCOPY,             D_OBJC },
   { "byref",           RID_BYREF,              D_OBJC },
   { "in",              RID_IN,                 D_OBJC },
@@ -3506,6 +3443,9 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_PTREXTENT */  PTR_EXTENT,
   /* RID_PTRVALUE */   PTR_VALUE,
 
+  /* 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,
@@ -3568,13 +3508,6 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_AT_IMPLEMENTATION */  IMPLEMENTATION
 };
 
-ifobjc
-/* Lookup table for ObjC keywords beginning with '@'.  Crude but
-   hopefully effective.  */
-#define N_at_reswords ((int) RID_AT_IMPLEMENTATION - (int)RID_AT_ENCODE + 1)
-static tree objc_rid_sans_at[N_at_reswords];
-end ifobjc
-
 static void
 init_reswords ()
 {
@@ -3602,42 +3535,9 @@ init_reswords ()
       C_RID_CODE (id) = reswords[i].rid;
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) reswords[i].rid] = id;
-
-ifobjc
-      /* Enter ObjC @-prefixed keywords into the "sans" table
-        _without_ their leading at-sign.  Again, all these
-        identifiers are reachable by the get_identifer table, so it's
-        not necessary to make objc_rid_sans_at a GC root.  */
-      if (reswords[i].word[0] == '@')
-       objc_rid_sans_at[(int) reswords[i].rid - (int) RID_AT_ENCODE]
-         = get_identifier (reswords[i].word + 1);
-end ifobjc
     }
 }
 
-const char *
-init_parse (filename)
-     const char *filename;
-{
-  add_c_tree_codes ();
-
-  /* Make identifier nodes long enough for the language-specific slots.  */
-  set_identifier_size (sizeof (struct lang_identifier));
-
-  init_reswords ();
-  init_pragma ();
-
-  return init_c_lex (filename);
-}
-
-void
-finish_parse ()
-{
-  cpp_finish (parse_in);
-  /* Call to cpp_destroy () omitted for performance reasons.  */
-  errorcount += cpp_errors (parse_in);
-}
-
 #define NAME(type) cpp_type2name (type)
 
 static void
@@ -3651,7 +3551,7 @@ yyerror (msgid)
   else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
     {
       unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
-      const char *ell = (last_token == CPP_CHAR) ? "" : "L";
+      const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
       if (val <= UCHAR_MAX && ISGRAPH (val))
        error ("%s before %s'%c'", string, ell, val);
       else
@@ -3660,9 +3560,7 @@ yyerror (msgid)
   else if (last_token == CPP_STRING
           || last_token == CPP_WSTRING)
     error ("%s before string constant", string);
-  else if (last_token == CPP_NUMBER
-          || last_token == CPP_INT
-          || last_token == CPP_FLOAT)
+  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));
@@ -3674,14 +3572,28 @@ static int
 yylexname ()
 {
   tree decl;
-
+  
+ifobjc
+  int objc_force_identifier = objc_need_raw_identifier;
+  OBJC_NEED_RAW_IDENTIFIER (0);
+end ifobjc
+  
   if (C_IS_RESERVED_WORD (yylval.ttype))
     {
       enum rid rid_code = C_RID_CODE (yylval.ttype);
 
 ifobjc
-      if (!((unsigned int) rid_code - (unsigned int) RID_FIRST_PQ < 6)
-         || objc_pq_context)
+      /* Turn non-typedefed refs to "id" into plain identifiers; this
+        allows constructs like "void foo(id id);" to work.  */
+      if (rid_code == RID_ID)
+      {
+       decl = lookup_name (yylval.ttype);
+       if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL)
+         return IDENTIFIER;
+      }
+
+      if (!OBJC_IS_AT_KEYWORD (rid_code)
+         && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
 end ifobjc
       {
        int yycode = rid_to_yy[(int) rid_code];
@@ -3692,6 +3604,7 @@ end ifobjc
            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;
          }
@@ -3712,8 +3625,11 @@ ifobjc
   else
     {
       tree objc_interface_decl = is_class_name (yylval.ttype);
-
-      if (objc_interface_decl)
+      /* ObjC class names are in the same namespace as variables and
+        typedefs, and hence are shadowed by local declarations.  */
+      if (objc_interface_decl 
+         && (global_bindings_p () 
+             || (!objc_force_identifier && !decl)))
        {
          yylval.ttype = objc_interface_decl;
          return CLASSNAME;
@@ -3730,9 +3646,6 @@ _yylex ()
 {
  get_next:
   last_token = c_lex (&yylval.ttype);
-ifobjc
- reconsider:
-end ifobjc
   switch (last_token)
     {
     case CPP_EQ:                                       return '=';
@@ -3754,10 +3667,7 @@ end ifobjc
     case CPP_AND_AND:                                  return ANDAND;
     case CPP_OR_OR:                                    return OROR;
     case CPP_QUERY:                                    return '?';
-    case CPP_COLON:                                    return ':';
-    case CPP_COMMA:                                    return ',';
     case CPP_OPEN_PAREN:                               return '(';
-    case CPP_CLOSE_PAREN:                              return ')';
     case CPP_EQ_EQ:    yylval.code = EQ_EXPR;          return EQCOMPARE;
     case CPP_NOT_EQ:   yylval.code = NE_EXPR;          return EQCOMPARE;
     case CPP_GREATER_EQ:yylval.code = GE_EXPR;         return ARITHCOMPARE;
@@ -3778,7 +3688,6 @@ end ifobjc
     case CPP_CLOSE_SQUARE:                             return ']';
     case CPP_OPEN_BRACE:                               return '{';
     case CPP_CLOSE_BRACE:                              return '}';
-    case CPP_SEMICOLON:                                        return ';';
     case CPP_ELLIPSIS:                                 return ELLIPSIS;
 
     case CPP_PLUS_PLUS:                                        return PLUSPLUS;
@@ -3786,16 +3695,19 @@ end ifobjc
     case CPP_DEREF:                                    return POINTSAT;
     case CPP_DOT:                                      return '.';
 
+      /* The following tokens may affect the interpretation of any
+        identifiers following, if doing Objective-C.  */
+    case CPP_COLON:            OBJC_NEED_RAW_IDENTIFIER (0);   return ':';
+    case CPP_COMMA:            OBJC_NEED_RAW_IDENTIFIER (0);   return ',';
+    case CPP_CLOSE_PAREN:      OBJC_NEED_RAW_IDENTIFIER (0);   return ')';
+    case CPP_SEMICOLON:                OBJC_NEED_RAW_IDENTIFIER (0);   return ';';
+
     case CPP_EOF:
-      if (cpp_pop_buffer (parse_in) == 0)
-       return 0;
-      goto get_next;
+      return 0;
 
     case CPP_NAME:
       return yylexname ();
 
-    case CPP_INT:
-    case CPP_FLOAT:
     case CPP_NUMBER:
     case CPP_CHAR:
     case CPP_WCHAR:
@@ -3805,27 +3717,29 @@ end ifobjc
     case CPP_WSTRING:
       return STRING;
       
-      /* This token is Objective-C specific.  It gives the next
-        token special significance.  */
+      /* This token is Objective-C specific.  It gives the next token
+        special significance.  */
     case CPP_ATSIGN:
 ifobjc
-      last_token = c_lex (&yylval.ttype);
-      if (last_token == CPP_STRING)
-       return OBJC_STRING;
-      else if (last_token == CPP_NAME)
-       {
-         int i;
-         for (i = 0; i < N_at_reswords; i++)
-           if (objc_rid_sans_at[i] == yylval.ttype)
-             {
-               int rid_code = i + (int) RID_AT_ENCODE;
-               yylval.ttype = ridpointers[rid_code];
-               return rid_to_yy[rid_code];
-             }
-       }
-      error ("syntax error at '@' token");
-      goto reconsider;
+      {
+       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
+
       /* These tokens are C++ specific (and will not be generated
          in C mode, but let's be cautious).  */
     case CPP_SCOPE:
@@ -3862,13 +3776,13 @@ yylex()
    in order to build the compiler.  */
 
 void
-set_yydebug (value)
+c_set_yydebug (value)
      int value;
 {
 #if YYDEBUG != 0
   yydebug = value;
 #else
-  warning ("YYDEBUG not defined.");
+  warning ("YYDEBUG not defined");
 #endif
 }
 
@@ -3927,15 +3841,21 @@ yyprint (file, yychar, yyl)
 
 /* Return something to represent absolute declarators containing a *.
    TARGET is the absolute declarator that the * contains.
-   TYPE_QUALS is a list of modifiers such as const or volatile
-   to apply to the pointer type, represented as identifiers.
+   TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
+   to apply to the pointer type, represented as identifiers, possible mixed
+   with attributes.
 
-   We return an INDIRECT_REF whose "contents" are TARGET
-   and whose type is the modifier list.  */
+   We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
+   if attributes are present) and whose type is the modifier list.  */
 
 tree
-make_pointer_declarator (type_quals, target)
-     tree type_quals, target;
+make_pointer_declarator (type_quals_attrs, target)
+     tree type_quals_attrs, target;
 {
-  return build1 (INDIRECT_REF, type_quals, target);
+  tree quals, attrs;
+  tree itarget = target;
+  split_specs_attrs (type_quals_attrs, &quals, &attrs);
+  if (attrs != NULL_TREE)
+    itarget = tree_cons (attrs, target, NULL_TREE);
+  return build1 (INDIRECT_REF, quals, itarget);
 }