aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2005-02-25 23:20:48 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2005-02-25 23:20:48 +0000
commit27bf414caa1a1d61601b0255020df9c4ae765e9c (patch)
tree3583a41269ae0a4769801c5116794c092decdc2a
parent29231b752cbc105c3158b4b45b97f8374f87cbac (diff)
downloadgcc-27bf414caa1a1d61601b0255020df9c4ae765e9c.zip
gcc-27bf414caa1a1d61601b0255020df9c4ae765e9c.tar.gz
gcc-27bf414caa1a1d61601b0255020df9c4ae765e9c.tar.bz2
c-parser.c: New file.
* c-parser.c: New file. * c-parse.in: Remove. * Makefile.in (c-parse.o-warn, c-parse.o, c-parse.c, c-parse.y): Remove. (c-parser.o): Add dependencies. (C_AND_OBJC_OBJC, C_OBJS, gcc.srcextra, GTFILES, distclean, maintainer-clean, TAGS): Update. * c-config-lang.in (gtfiles): Update. * gengtype-lex.l: Don't handle "@@". * stub-objc.c (objc_get_class_ivars, objc_build_throw_stmt, objc_build_synchronized, objc_begin_try_stmt, objc_begin_catch_clause, objc_finish_catch_clause, objc_build_finally_clause, objc_finish_try_stmt): New. * c-tree.h (struct c_declspecs): Add declspecs_seen_p and type_seen_p. (c_parse_init): Update comment. * c-decl.c (c_init_decl_processing): Update comment. (build_null_declspecs, declspecs_add_qual, declspecs_add_type, declspecs_add_scspec, declspecs_add_attrs): Initialize and update new c_declspecs members. objc: * Make-lang.in (objc/objc-parse.o-warn, objc/objc-parse.o, objc/objc-parse.c, objc/objc-parse.y): Remove (OBJC_OBJS, objc.srcextra, objc.tags, objc.mostlyclean, objc.distclean, objc.maintainer-clean): Update for new parser. * config-lang.in (gtfiles): Update for new parser. testsuite: * gcc.dg/cpp/separate-1.c, gcc.dg/noncompile/971104-1.c, gcc.dg/noncompile/990416-1.c: Adjust expected messages for new parser. From-SVN: r95558
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/Makefile.in29
-rw-r--r--gcc/c-config-lang.in4
-rw-r--r--gcc/c-decl.c9
-rw-r--r--gcc/c-parse.in3588
-rw-r--r--gcc/c-parser.c6219
-rw-r--r--gcc/c-tree.h6
-rw-r--r--gcc/gengtype-lex.l4
-rw-r--r--gcc/objc/ChangeLog8
-rw-r--r--gcc/objc/Make-lang.in29
-rw-r--r--gcc/objc/config-lang.in4
-rw-r--r--gcc/stub-objc.c46
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/separate-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/971104-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/990416-1.c2
16 files changed, 6335 insertions, 3646 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eebeac4..bc843db 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,26 @@
+2005-02-25 Joseph S. Myers <joseph@codesourcery.com>
+
+ * c-parser.c: New file.
+ * c-parse.in: Remove.
+ * Makefile.in (c-parse.o-warn, c-parse.o, c-parse.c, c-parse.y):
+ Remove.
+ (c-parser.o): Add dependencies.
+ (C_AND_OBJC_OBJC, C_OBJS, gcc.srcextra, GTFILES, distclean,
+ maintainer-clean, TAGS): Update.
+ * c-config-lang.in (gtfiles): Update.
+ * gengtype-lex.l: Don't handle "@@".
+ * stub-objc.c (objc_get_class_ivars, objc_build_throw_stmt,
+ objc_build_synchronized, objc_begin_try_stmt,
+ objc_begin_catch_clause, objc_finish_catch_clause,
+ objc_build_finally_clause, objc_finish_try_stmt): New.
+ * c-tree.h (struct c_declspecs): Add declspecs_seen_p and
+ type_seen_p.
+ (c_parse_init): Update comment.
+ * c-decl.c (c_init_decl_processing): Update comment.
+ (build_null_declspecs, declspecs_add_qual, declspecs_add_type,
+ declspecs_add_scspec, declspecs_add_attrs): Initialize and update
+ new c_declspecs members.
+
2005-02-25 Julian Brown <julian@codesourcery.com>
* config/elfos.h (MAKE_DECL_ONE_ONLY): Redefined to stop DECL_WEAK
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 93c3399..1be15cd 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -193,7 +193,6 @@ gcc.o-warn = -Wno-error
build/insn-conditions.o-warn = -Wno-error
# Bison-1.75 output often yields (harmless) -Wtraditional warnings
build/gengtype-yacc.o-warn = -Wno-error
-c-parse.o-warn = -Wno-error
# flex output may yield harmless "no previous prototype" warnings
build/gengtype-lex.o-warn = -Wno-error
# SYSCALLS.c misses prototypes
@@ -884,11 +883,11 @@ CXX_TARGET_OBJS=@cxx_target_objs@
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
- c-objc-common.o c-dump.o c-pch.o $(C_TARGET_OBJS) \
+ c-objc-common.o c-dump.o c-pch.o c-parser.o $(C_TARGET_OBJS) \
c-gimplify.o tree-mudflap.o c-pretty-print.o
# Language-specific object files for C.
-C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
+C_OBJS = c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
# Language-independent object files.
OBJS-common = \
@@ -1347,24 +1346,15 @@ s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
-c-parse.o : c-parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) intl.h $(C_TREE_H) input.h $(FLAGS_H) toplev.h output.h \
- $(CPPLIB_H) varray.h gt-c-parse.h langhooks.h $(C_COMMON_H) $(C_PRAGMA_H)
+ $(CPPLIB_H) varray.h gt-c-parser.h langhooks.h $(C_COMMON_H) $(C_PRAGMA_H)
srcextra: gcc.srcextra lang.srcextra
-gcc.srcextra: c-parse.y c-parse.c gengtype-lex.c gengtype-yacc.c gengtype-yacc.h
+gcc.srcextra: gengtype-lex.c gengtype-yacc.c gengtype-yacc.h
-cp -p $^ $(srcdir)
-c-parse.c: c-parse.y
- -$(BISON) $(BISONFLAGS) -o $@ $<
-
-c-parse.y: c-parse.in
- echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y
- sed -e "/^@@ifobjc.*/,/^@@end_ifobjc.*/d" \
- -e "/^@@ifc.*/d" -e "/^@@end_ifc.*/d" $< >>tmp-c-parse.y
- $(SHELL) $(srcdir)/../move-if-change tmp-c-parse.y $@
-
c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \
$(MACHMODE_H)
@@ -2427,7 +2417,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
$(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
$(srcdir)/tree-mudflap.c $(srcdir)/tree-flow.h \
- $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parse.in \
+ $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parser.c \
$(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c \
$(srcdir)/tree-phinodes.c $(srcdir)/tree-cfg.c \
$(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-propagate.c \
@@ -2449,7 +2439,7 @@ gt-emit-rtl.h gt-explow.h gt-stor-layout.h gt-regclass.h \
gt-lists.h gt-alias.h gt-cselib.h gt-gcse.h \
gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dojump.h \
gt-dwarf2out.h gt-reg-stack.h gt-dwarf2asm.h \
-gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parse.h \
+gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parser.h \
gt-c-pragma.h gtype-c.h gt-cfglayout.h \
gt-tree-mudflap.h gt-tree-complex.h \
gt-tree-eh.h \
@@ -3166,7 +3156,7 @@ distclean: clean lang.distclean
-rm -f Makefile *.oaux
-rm -f gthr-default.h
-rm -f */stage1 */stage2 */stage3 */stage4 */include */stageprofile */stagefeedback
- -rm -f c-parse.y c-parse.c c-parse.output TAGS */TAGS
+ -rm -f TAGS */TAGS
-rm -f *.asm
-rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
-rm -f testsuite/*.log testsuite/*.sum
@@ -3186,7 +3176,6 @@ maintainer-clean:
@echo 'This command is intended for maintainers to use; it'
@echo 'deletes files that may need special tools to rebuild.'
$(MAKE) lang.maintainer-clean distclean
- -rm -f $(srcdir)/c-parse.y $(srcdir)/c-parse.c
-rm -f cpp.??s cpp.*aux
-rm -f gcc.??s gcc.*aux
-rm -f $(docdir)/*.info $(docdir)/*.1 $(docdir)/*.7 $(docdir)/*.dvi
@@ -3648,7 +3637,7 @@ TAGS: lang.tags
incs="$$incs --include $$dir/TAGS.sub"; \
fi; \
done; \
- etags -o TAGS.sub *.y *.h *.c -l yacc c-parse.in; \
+ etags -o TAGS.sub *.y *.h *.c; \
etags --include TAGS.sub $$incs)
# ------------------------------------------------------
diff --git a/gcc/c-config-lang.in b/gcc/c-config-lang.in
index c0a786f..6b5edc2 100644
--- a/gcc/c-config-lang.in
+++ b/gcc/c-config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU C - C language.
-# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -23,4 +23,4 @@
# files used by C that have garbage collection GTY macros in them
# which therefore need to be scanned by gengtype.c.
-gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-parse.in \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c"
+gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c"
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 0b7b97e..690d3b3 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2581,7 +2581,7 @@ c_init_decl_processing (void)
tree ptr_ftype_void, ptr_ftype_ptr;
location_t save_loc = input_location;
- /* Adds some ggc roots, and reserved words for c-parse.in. */
+ /* Initialize reserved words for parser. */
c_parse_init ();
current_function_decl = 0;
@@ -6746,6 +6746,8 @@ build_null_declspecs (void)
ret->attrs = 0;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
+ ret->declspecs_seen_p = false;
+ ret->type_seen_p = false;
ret->non_sc_seen_p = false;
ret->typedef_p = false;
ret->tag_defined_p = false;
@@ -6775,6 +6777,7 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
enum rid i;
bool dupe = false;
specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (qual));
i = C_RID_CODE (qual);
@@ -6808,6 +6811,8 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
{
tree type = spec.spec;
specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+ specs->type_seen_p = true;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
@@ -7102,6 +7107,7 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
enum rid i;
enum c_storage_class n = csc_none;
bool dupe = false;
+ specs->declspecs_seen_p = true;
gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (scspec));
i = C_RID_CODE (scspec);
@@ -7184,6 +7190,7 @@ struct c_declspecs *
declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
{
specs->attrs = chainon (attrs, specs->attrs);
+ specs->declspecs_seen_p = true;
return specs;
}
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
deleted file mode 100644
index fe0d517..0000000
--- a/gcc/c-parse.in
+++ /dev/null
@@ -1,3588 +0,0 @@
-/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-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.
-
-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 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.
- @@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. */
-
-@@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"
-#include "timevar.h"
-#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"
-#include "c-common.h"
-
-#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
-
-/* Like the default stack expander, except (1) use realloc when possible,
- (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
-
- Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
- give malloced_yyvs its proper type. This is ok since all we need from
- it is to be able to free it. */
-
-static short *malloced_yyss;
-static void *malloced_yyvs;
-
-#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ) \
-do { \
- size_t newsize; \
- short *newss; \
- YYSTYPE *newvs; \
- newsize = *(YYSSZ) *= 2; \
- if (malloced_yyss) \
- { \
- newss = really_call_realloc (*(SS), newsize * sizeof (short)); \
- newvs = really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
- } \
- else \
- { \
- newss = really_call_malloc (newsize * sizeof (short)); \
- newvs = really_call_malloc (newsize * sizeof (YYSTYPE)); \
- if (newss) \
- memcpy (newss, *(SS), (SSSIZE)); \
- if (newvs) \
- memcpy (newvs, *(VS), (VSSIZE)); \
- } \
- if (!newss || !newvs) \
- { \
- yyerror (MSG); \
- return 2; \
- } \
- *(SS) = newss; \
- *(VS) = newvs; \
- malloced_yyss = newss; \
- malloced_yyvs = (void *) newvs; \
-} while (0)
-%}
-
-%start program
-
-%union {long itype; tree ttype; void *otype; struct c_expr exprtype;
- struct c_arg_info *arginfotype; struct c_declarator *dtrtype;
- struct c_type_name *typenametype; struct c_parm *parmtype;
- struct c_declspecs *dsptype; struct c_typespec tstype;
- enum tree_code code; location_t location; }
-
-/* All identifiers that are not reserved words
- and are not declared typedefs in the current block */
-%token IDENTIFIER
-
-/* All identifiers that are declared typedefs in the current block.
- In some contexts, they are treated just like IDENTIFIER,
- but they can also serve as typespecs in declarations. */
-%token TYPENAME
-
-/* Reserved words that specify storage class.
- yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token SCSPEC /* Storage class other than static. */
-%token STATIC /* Static storage class. */
-
-/* Reserved words that specify type.
- yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token TYPESPEC
-
-/* Reserved words that qualify type: "const", "volatile", or "restrict".
- 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. */
-%token ELLIPSIS
-
-/* the reserved words */
-/* SCO include files test "ASM", so use something else. */
-%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 CHOOSE_EXPR TYPES_COMPATIBLE_P
-%token FUNC_NAME OFFSETOF
-
-/* Add precedence rules to solve dangling else s/r conflict */
-%nonassoc IF
-%nonassoc ELSE
-
-/* Define the operator tokens and their precedences.
- The value is an integer because, if used, it is the tree code
- to use in the expression made from the operator. */
-
-%right <code> ASSIGN '='
-%right <code> '?' ':'
-%left <code> OROR
-%left <code> ANDAND
-%left <code> '|'
-%left <code> '^'
-%left <code> '&'
-%left <code> EQCOMPARE
-%left <code> ARITHCOMPARE
-%left <code> LSHIFT RSHIFT
-%left <code> '+' '-'
-%left <code> '*' '/' '%'
-%right <code> UNARY PLUSPLUS MINUSMINUS
-%left HYPERUNARY
-%left <code> POINTSAT '.' '(' '['
-
-/* The Objective-C keywords. These are included in C and in
- Objective C, so that the token codes are the same in both. */
-%token AT_INTERFACE AT_IMPLEMENTATION AT_END AT_SELECTOR AT_DEFS AT_ENCODE
-%token CLASSNAME AT_PUBLIC AT_PRIVATE AT_PROTECTED AT_PROTOCOL
-%token 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 STRING FUNC_NAME
-%type <ttype> nonnull_exprlist exprlist
-%type <exprtype> expr expr_no_commas cast_expr unary_expr primary
-%type <dsptype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
-%type <dsptype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
-%type <dsptype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
-%type <dsptype> declspecs_nosc_ts_sa_noea declspecs_nosc_ts_sa_ea
-%type <dsptype> declspecs_sc_nots_nosa_noea declspecs_sc_nots_nosa_ea
-%type <dsptype> declspecs_sc_nots_sa_noea declspecs_sc_nots_sa_ea
-%type <dsptype> declspecs_sc_ts_nosa_noea declspecs_sc_ts_nosa_ea
-%type <dsptype> declspecs_sc_ts_sa_noea declspecs_sc_ts_sa_ea
-%type <dsptype> declspecs_ts declspecs_nots
-%type <dsptype> declspecs_ts_nosa declspecs_nots_nosa
-%type <dsptype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
-%type <dsptype> maybe_type_quals_attrs
-%type <tstype> typespec_nonattr typespec_attr
-%type <tstype> typespec_reserved_nonattr typespec_reserved_attr
-%type <tstype> typespec_nonreserved_nonattr
-%type <ttype> offsetof_member_designator
-
-%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
-%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
-%type <exprtype> init
-%type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument asm_string
-%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
-%type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word
-
-%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_lineno_labeled_stmt
-%type <ttype> if_statement_1 if_statement_2
-%type <dtrtype> declarator
-%type <dtrtype> notype_declarator after_type_declarator
-%type <dtrtype> parm_declarator
-%type <dtrtype> parm_declarator_starttypename parm_declarator_nostarttypename
-%type <dtrtype> array_declarator
-
-%type <tstype> structsp_attr structsp_nonattr
-%type <ttype> component_decl_list component_decl_list2
-%type <ttype> component_decl components components_notype component_declarator
-%type <ttype> component_notype_declarator
-%type <ttype> enumlist enumerator
-%type <ttype> struct_head union_head enum_head
-%type <typenametype> typename
-%type <dtrtype> absdcl absdcl1 absdcl1_ea absdcl1_noea direct_absdcl1
-%type <parmtype> absdcl_maybe_attribute
-%type <ttype> condition xexpr for_cond_expr for_incr_expr
-%type <parmtype> parm firstparm
-%type <ttype> identifiers
-
-%type <arginfotype> parms parmlist parmlist_1 parmlist_2
-%type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1
-%type <ttype> identifiers_or_typenames
-
-%type <itype> setspecs setspecs_fp extension
-
-%type <location> save_location
-
-%type <otype> save_obstack_position
-
-@@ifobjc
-/* the Objective-C nonterminals */
-
-%type <ttype> methoddecl unaryselector keywordselector selector
-%type <code> methodtype
-%type <ttype> keyworddecl receiver objcmessageexpr messageargs
-%type <ttype> keywordexpr keywordarglist keywordarg
-%type <ttype> optparmlist optparms reservedwords objcselectorexpr
-%type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
-%type <ttype> non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
-
-%type <ttype> CLASSNAME OBJC_STRING OBJC_TYPE_QUAL
-
-%type <ttype> superclass objc_quals objc_qual objc_typename
-%type <itype> objc_try_catch_stmt optellipsis
-@@end_ifobjc
-
-%{
-/* Declaration specifiers of the current declaration. */
-static struct c_declspecs *current_declspecs;
-static GTY(()) tree prefix_attributes;
-
-/* List of all the attributes applying to the identifier currently being
- declared; includes prefix_attributes and possibly some more attributes
- just after a comma. */
-static GTY(()) tree all_prefix_attributes;
-
-/* Structure to save declaration specifiers. */
-struct c_declspec_stack {
- /* Saved value of current_declspecs. */
- struct c_declspecs *current_declspecs;
- /* Saved value of prefix_attributes. */
- tree prefix_attributes;
- /* Saved value of all_prefix_attributes. */
- tree all_prefix_attributes;
- /* Next level of stack. */
- struct c_declspec_stack *next;
-};
-
-/* Stack of saved values of current_declspecs, prefix_attributes and
- all_prefix_attributes. */
-static struct c_declspec_stack *declspec_stack;
-
-/* INDIRECT_REF with a TREE_TYPE of the type being queried for offsetof. */
-static tree offsetof_base;
-
-/* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
- should be called from the productions making use of setspecs. */
-#define PUSH_DECLSPEC_STACK \
- do { \
- struct c_declspec_stack *t = XOBNEW (&parser_obstack, \
- struct c_declspec_stack); \
- t->current_declspecs = current_declspecs; \
- t->prefix_attributes = prefix_attributes; \
- t->all_prefix_attributes = all_prefix_attributes; \
- t->next = declspec_stack; \
- declspec_stack = t; \
- } while (0)
-
-#define POP_DECLSPEC_STACK \
- do { \
- current_declspecs = declspec_stack->current_declspecs; \
- prefix_attributes = declspec_stack->prefix_attributes; \
- all_prefix_attributes = declspec_stack->all_prefix_attributes; \
- declspec_stack = declspec_stack->next; \
- } while (0)
-
-/* For __extension__, save/restore the warning flags which are
- controlled by __extension__. */
-#define SAVE_EXT_FLAGS() \
- (pedantic \
- | (warn_pointer_arith << 1) \
- | (warn_traditional << 2) \
- | (flag_iso << 3))
-
-#define RESTORE_EXT_FLAGS(val) \
- do { \
- pedantic = val & 1; \
- warn_pointer_arith = (val >> 1) & 1; \
- warn_traditional = (val >> 2) & 1; \
- flag_iso = (val >> 3) & 1; \
- } while (0)
-
-@@ifobjc
-/* Objective-C specific parser/lexer information */
-
-static int objc_pq_context = 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)
-
-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);
-
- /* Initialization routine for this file. */
-void
-c_parse_init (void)
-{
- init_reswords ();
-}
-
-%}
-
-%%
-program: /* empty */
- { if (pedantic)
- pedwarn ("ISO C forbids an empty source file");
- }
- | extdefs
- ;
-
-/* the reason for the strange actions in this rule
- is so that notype_initdecls when reached via datadef
- can find valid declaration specifiers in $0. */
-
-extdefs:
- save_obstack_position { $<dsptype>$ = NULL; } extdef
- { obstack_free (&parser_obstack, $1); }
- | extdefs save_obstack_position
- { $<dsptype>$ = NULL; ggc_collect (); } extdef
- { obstack_free (&parser_obstack, $2); }
- ;
-
-extdef:
- fndef
- | datadef
- | asmdef
- | extension extdef
- { RESTORE_EXT_FLAGS ($1); }
-@@ifobjc
- | objcdef
-@@end_ifobjc
- ;
-
-/* Record the current position of parser_obstack before a
- declaration to restore it afterwards. */
-save_obstack_position:
- { $$ = obstack_alloc (&parser_obstack, 0); }
- ;
-
-datadef:
- setspecs notype_initdecls ';'
- { pedwarn ("data definition has no type or storage class");
- POP_DECLSPEC_STACK; }
- | declspecs_nots setspecs notype_initdecls ';'
- { POP_DECLSPEC_STACK; }
- | declspecs_ts setspecs initdecls ';'
- { POP_DECLSPEC_STACK; }
- | declspecs ';'
- { shadow_tag (finish_declspecs ($1)); }
- | error ';'
- | error '}'
- | ';'
- { if (pedantic)
- pedwarn ("ISO C does not allow extra %<;%> outside of a function"); }
- ;
-
-fndef:
- declspecs_ts setspecs declarator
- { if (!start_function (current_declspecs, $3,
- all_prefix_attributes))
- YYERROR1;
- }
- 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; }
- | declspecs_nots setspecs notype_declarator
- { if (!start_function (current_declspecs, $3,
- all_prefix_attributes))
- YYERROR1;
- }
- 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; }
- | setspecs notype_declarator
- { if (!start_function (current_declspecs, $2,
- all_prefix_attributes))
- YYERROR1;
- }
- 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; }
- ;
-
-identifier:
- IDENTIFIER
- | TYPENAME
-@@ifobjc
- | CLASSNAME
-@@end_ifobjc
- ;
-
-unop: '&'
- { $$ = ADDR_EXPR; }
- | '-'
- { $$ = NEGATE_EXPR; }
- | '+'
- { $$ = CONVERT_EXPR;
-@@ifc
- if (warn_traditional && !in_system_header)
- warning ("traditional C rejects the unary plus operator");
-@@end_ifc
- }
- | PLUSPLUS
- { $$ = PREINCREMENT_EXPR; }
- | MINUSMINUS
- { $$ = PREDECREMENT_EXPR; }
- | '~'
- { $$ = BIT_NOT_EXPR; }
- | '!'
- { $$ = TRUTH_NOT_EXPR; }
- ;
-
-expr: expr_no_commas
- | expr ',' expr_no_commas
- { $$.value = build_compound_expr ($1.value, $3.value);
- $$.original_code = COMPOUND_EXPR; }
- ;
-
-exprlist:
- /* empty */
- { $$ = NULL_TREE; }
- | nonnull_exprlist
- ;
-
-nonnull_exprlist:
- expr_no_commas
- { $$ = build_tree_list (NULL_TREE, $1.value); }
- | nonnull_exprlist ',' expr_no_commas
- { chainon ($1, build_tree_list (NULL_TREE, $3.value)); }
- ;
-
-unary_expr:
- primary
- | '*' cast_expr %prec 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
- { $$.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
- { $$.value = finish_label_address_expr ($2);
- $$.original_code = ERROR_MARK; }
- | sizeof unary_expr %prec UNARY
- { skip_evaluation--;
- in_sizeof--;
- if (TREE_CODE ($2.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
- error ("%<sizeof%> applied to a bit-field");
- $$ = c_expr_sizeof_expr ($2); }
- | sizeof '(' typename ')' %prec HYPERUNARY
- { skip_evaluation--;
- in_sizeof--;
- $$ = c_expr_sizeof_type ($3); }
- | alignof unary_expr %prec UNARY
- { skip_evaluation--;
- in_alignof--;
- $$.value = c_alignof_expr ($2.value);
- $$.original_code = ERROR_MARK; }
- | alignof '(' typename ')' %prec HYPERUNARY
- { skip_evaluation--;
- in_alignof--;
- $$.value = c_alignof (groktypename ($3));
- $$.original_code = ERROR_MARK; }
- | REALPART cast_expr %prec UNARY
- { $$.value = build_unary_op (REALPART_EXPR, $2.value, 0);
- $$.original_code = ERROR_MARK; }
- | IMAGPART cast_expr %prec UNARY
- { $$.value = build_unary_op (IMAGPART_EXPR, $2.value, 0);
- $$.original_code = ERROR_MARK; }
- ;
-
-sizeof:
- SIZEOF { skip_evaluation++; in_sizeof++; }
- ;
-
-alignof:
- ALIGNOF { skip_evaluation++; in_alignof++; }
- ;
-
-typeof:
- TYPEOF { skip_evaluation++; in_typeof++; }
- ;
-
-cast_expr:
- unary_expr
- | '(' typename ')' cast_expr %prec UNARY
- { $$.value = c_cast_expr ($2, $4.value);
- $$.original_code = ERROR_MARK; }
- ;
-
-expr_no_commas:
- cast_expr
- | expr_no_commas '+' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '-' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '*' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '/' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '%' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas LSHIFT expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas RSHIFT expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas ARITHCOMPARE expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas EQCOMPARE expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '&' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '|' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas '^' expr_no_commas
- { $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas ANDAND
- { $1.value = lang_hooks.truthvalue_conversion
- (default_conversion ($1.value));
- skip_evaluation += $1.value == truthvalue_false_node; }
- expr_no_commas
- { skip_evaluation -= $1.value == truthvalue_false_node;
- $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
- | expr_no_commas OROR
- { $1.value = lang_hooks.truthvalue_conversion
- (default_conversion ($1.value));
- skip_evaluation += $1.value == truthvalue_true_node; }
- expr_no_commas
- { skip_evaluation -= $1.value == truthvalue_true_node;
- $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
- | expr_no_commas '?'
- { $1.value = lang_hooks.truthvalue_conversion
- (default_conversion ($1.value));
- skip_evaluation += $1.value == truthvalue_false_node; }
- expr ':'
- { skip_evaluation += (($1.value == truthvalue_true_node)
- - ($1.value == truthvalue_false_node)); }
- expr_no_commas
- { 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 (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.value == truthvalue_true_node;
- $$.value = build_conditional_expr ($1.value, $<ttype>2,
- $5.value);
- $$.original_code = ERROR_MARK; }
- | expr_no_commas '=' expr_no_commas
- { $$.value = build_modify_expr ($1.value, NOP_EXPR, $3.value);
- $$.original_code = MODIFY_EXPR;
- }
- | expr_no_commas ASSIGN expr_no_commas
- { $$.value = build_modify_expr ($1.value, $2, $3.value);
- TREE_NO_WARNING ($$.value) = 1;
- $$.original_code = ERROR_MARK;
- }
- ;
-
-primary:
- IDENTIFIER
- {
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- $$.value = build_external_ref ($1, yychar == '(');
- $$.original_code = ERROR_MARK;
- }
- | CONSTANT
- { $$.value = $1; $$.original_code = ERROR_MARK; }
- | STRING
- { $$.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);
- $<ttype>$ = groktypename ($2);
- if (C_TYPE_VARIABLE_SIZE ($<ttype>$))
- {
- error ("compound literal has variable size");
- $<ttype>$ = error_mark_node;
- }
- really_start_incremental_init ($<ttype>$); }
- initlist_maybe_comma '}' %prec UNARY
- { struct c_expr init = pop_init_level (0);
- tree constructor = init.value;
- tree type = $<ttype>5;
- finish_init ();
- maybe_warn_string_init (type, init);
-
- if (pedantic && !flag_isoc99)
- pedwarn ("ISO C90 forbids compound literals");
- $$.value = build_compound_literal (type, constructor);
- $$.original_code = ERROR_MARK;
- }
- | '(' expr ')'
- { $$.value = $2.value;
- if (TREE_CODE ($$.value) == MODIFY_EXPR)
- TREE_NO_WARNING ($$.value) = 1;
- $$.original_code = ERROR_MARK; }
- | '(' error ')'
- { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
- | compstmt_primary_start compstmt_nostart ')'
- { if (pedantic)
- pedwarn ("ISO C forbids braced-groups within expressions");
- $$.value = c_finish_stmt_expr ($1);
- $$.original_code = ERROR_MARK;
- }
- | compstmt_primary_start error ')'
- { c_finish_stmt_expr ($1);
- $$.value = error_mark_node;
- $$.original_code = ERROR_MARK;
- }
- | primary '(' exprlist ')' %prec '.'
- { $$.value = build_function_call ($1.value, $3);
- $$.original_code = ERROR_MARK; }
- | VA_ARG '(' expr_no_commas ',' typename ')'
- { $$.value = build_va_arg ($3.value, groktypename ($5));
- $$.original_code = ERROR_MARK; }
-
- | 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.value);
- STRIP_NOPS (c);
- if (TREE_CODE (c) != INTEGER_CST)
- error ("first argument to %<__builtin_choose_expr%> not"
- " a constant");
- $$ = integer_zerop (c) ? $7 : $5;
- }
- | 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));
-
- $$.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 '.'
- { $$.value = build_array_ref ($1.value, $3.value);
- $$.original_code = ERROR_MARK; }
- | primary '.' identifier
- { $$.value = build_component_ref ($1.value, $3);
- $$.original_code = ERROR_MARK; }
- | primary POINTSAT identifier
- {
- tree expr = build_indirect_ref ($1.value, "->");
- $$.value = build_component_ref (expr, $3);
- $$.original_code = ERROR_MARK;
- }
- | primary PLUSPLUS
- { $$.value = build_unary_op (POSTINCREMENT_EXPR, $1.value, 0);
- $$.original_code = ERROR_MARK; }
- | primary MINUSMINUS
- { $$.value = build_unary_op (POSTDECREMENT_EXPR, $1.value, 0);
- $$.original_code = ERROR_MARK; }
-@@ifobjc
- | objcmessageexpr
- { $$.value = objc_build_message_expr ($1);
- $$.original_code = ERROR_MARK; }
- | objcselectorexpr
- { $$.value = objc_build_selector_expr ($1);
- $$.original_code = ERROR_MARK; }
- | objcprotocolexpr
- { $$.value = objc_build_protocol_expr ($1);
- $$.original_code = ERROR_MARK; }
- | objcencodeexpr
- { $$.value = objc_build_encode_expr ($1);
- $$.original_code = ERROR_MARK; }
- | OBJC_STRING
- { $$.value = objc_build_string_object ($1);
- $$.original_code = ERROR_MARK; }
-@@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. */
-
-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:
- /* empty */
- | datadecls
- ;
-
-/* The following are analogous to lineno_decl, decls and decl
- except that they do not allow nested functions.
- They are used for old-style parm decls. */
-lineno_datadecl:
- save_location datadecl
- { }
- ;
-
-datadecls:
- lineno_datadecl
- | errstmt
- | datadecls lineno_datadecl
- | lineno_datadecl errstmt
- ;
-
-/* We don't allow prefix attributes here because they cause reduce/reduce
- conflicts: we can't know whether we're parsing a function decl with
- attribute suffix, or function defn with attribute prefix on first old
- style parm. */
-datadecl:
- declspecs_ts_nosa setspecs initdecls ';'
- { POP_DECLSPEC_STACK; }
- | declspecs_nots_nosa setspecs notype_initdecls ';'
- { POP_DECLSPEC_STACK; }
- | declspecs_ts_nosa ';'
- { shadow_tag_warned (finish_declspecs ($1), 1);
- pedwarn ("empty declaration"); }
- | declspecs_nots_nosa ';'
- { pedwarn ("empty declaration"); }
- ;
-
-/* This combination which saves a lineno before a decl
- is the normal thing to use, rather than decl itself.
- This is to avoid shift/reduce conflicts in contexts
- where statement labels are allowed. */
-lineno_decl:
- save_location decl
- { }
- ;
-
-/* records the type and storage class specs to use for processing
- the declarators that follow.
- Maintains a stack of outer-level values of current_declspecs,
- for the sake of parm declarations nested in function declarators. */
-setspecs: /* empty */
- { pending_xref_error ();
- PUSH_DECLSPEC_STACK;
- if ($<dsptype>0)
- {
- prefix_attributes = $<dsptype>0->attrs;
- $<dsptype>0->attrs = NULL_TREE;
- current_declspecs = $<dsptype>0;
- }
- else
- {
- prefix_attributes = NULL_TREE;
- current_declspecs = build_null_declspecs ();
- }
- current_declspecs = finish_declspecs (current_declspecs);
- all_prefix_attributes = prefix_attributes; }
- ;
-
-/* 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 ';'
- { POP_DECLSPEC_STACK; }
- | declspecs_nots setspecs notype_initdecls ';'
- { POP_DECLSPEC_STACK; }
- | declspecs_ts setspecs nested_function
- { POP_DECLSPEC_STACK; }
- | declspecs_nots setspecs notype_nested_function
- { POP_DECLSPEC_STACK; }
- | declspecs ';'
- { shadow_tag (finish_declspecs ($1)); }
- | extension decl
- { RESTORE_EXT_FLAGS ($1); }
- ;
-
-/* A list of declaration specifiers. These are:
-
- - Storage class specifiers (scspec), which for GCC currently includes
- function specifiers ("inline").
-
- - Type specifiers (typespec_*).
-
- - Type qualifiers (TYPE_QUAL).
-
- - Attribute specifier lists (attributes).
-
- The various cases below are classified according to:
-
- (a) Whether a storage class specifier is included or not; some
- places in the grammar disallow storage class specifiers (_sc or _nosc).
-
- (b) Whether a type specifier has been seen; after a type specifier,
- a typedef name is an identifier to redeclare (_ts or _nots).
-
- (c) Whether the list starts with an attribute; in certain places,
- the grammar requires specifiers that don't start with an attribute
- (_sa or _nosa).
-
- (d) Whether the list ends with an attribute (or a specifier such that
- any following attribute would have been parsed as part of that specifier);
- this avoids shift-reduce conflicts in the parsing of attributes
- (_ea or _noea).
-
- TODO:
-
- (i) Distinguish between function specifiers and storage class specifiers,
- at least for the purpose of warnings about obsolescent usage.
-
- (ii) Halve the number of productions here by eliminating the _sc/_nosc
- distinction and instead checking where required that storage class
- specifiers aren't present. */
-
-/* Declspecs which contain at least one type specifier or typedef name.
- (Just `const' or `volatile' is not enough.)
- A typedef'd name following these is taken as a name to be declared. */
-
-declspecs_nosc_nots_nosa_noea:
- TYPE_QUAL
- { $$ = declspecs_add_qual (build_null_declspecs (), $1); }
- | declspecs_nosc_nots_nosa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_nots_nosa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- ;
-
-declspecs_nosc_nots_nosa_ea:
- declspecs_nosc_nots_nosa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- ;
-
-declspecs_nosc_nots_sa_noea:
- declspecs_nosc_nots_sa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_nots_sa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- ;
-
-declspecs_nosc_nots_sa_ea:
- attributes
- { $$ = declspecs_add_attrs (build_null_declspecs (), $1); }
- | declspecs_nosc_nots_sa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- ;
-
-declspecs_nosc_ts_nosa_noea:
- typespec_nonattr
- { $$ = declspecs_add_type (build_null_declspecs (), $1); }
- | declspecs_nosc_ts_nosa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_ts_nosa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_ts_nosa_noea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_nosa_ea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_nosa_noea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_nosa_ea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-declspecs_nosc_ts_nosa_ea:
- typespec_attr
- { $$ = declspecs_add_type (build_null_declspecs (), $1); }
- | declspecs_nosc_ts_nosa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- | declspecs_nosc_ts_nosa_noea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_nosa_ea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_nosa_noea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_nosa_ea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-declspecs_nosc_ts_sa_noea:
- declspecs_nosc_ts_sa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_ts_sa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_ts_sa_noea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_sa_ea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_sa_noea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_sa_ea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-declspecs_nosc_ts_sa_ea:
- declspecs_nosc_ts_sa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- | declspecs_nosc_ts_sa_noea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_sa_ea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_sa_noea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_nots_sa_ea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-declspecs_sc_nots_nosa_noea:
- scspec
- { $$ = declspecs_add_scspec (build_null_declspecs (), $1); }
- | declspecs_sc_nots_nosa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_nots_nosa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_nots_nosa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_nosc_nots_nosa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_nots_nosa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_nots_nosa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- ;
-
-declspecs_sc_nots_nosa_ea:
- declspecs_sc_nots_nosa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- ;
-
-declspecs_sc_nots_sa_noea:
- declspecs_sc_nots_sa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_nots_sa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_nosc_nots_sa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_nosc_nots_sa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_nots_sa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_nots_sa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- ;
-
-declspecs_sc_nots_sa_ea:
- declspecs_sc_nots_sa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- ;
-
-declspecs_sc_ts_nosa_noea:
- declspecs_sc_ts_nosa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_ts_nosa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_ts_nosa_noea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_ts_nosa_ea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_nosa_noea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_nosa_ea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_nosa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_nosc_ts_nosa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_ts_nosa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_ts_nosa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- ;
-
-declspecs_sc_ts_nosa_ea:
- declspecs_sc_ts_nosa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- | declspecs_sc_ts_nosa_noea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_ts_nosa_ea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_nosa_noea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_nosa_ea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-declspecs_sc_ts_sa_noea:
- declspecs_sc_ts_sa_noea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_ts_sa_ea TYPE_QUAL
- { $$ = declspecs_add_qual ($1, $2); }
- | declspecs_sc_ts_sa_noea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_ts_sa_ea typespec_reserved_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_sa_noea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_sa_ea typespec_nonattr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_nosc_ts_sa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_nosc_ts_sa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_ts_sa_noea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- | declspecs_sc_ts_sa_ea scspec
- { $$ = declspecs_add_scspec ($1, $2); }
- ;
-
-declspecs_sc_ts_sa_ea:
- declspecs_sc_ts_sa_noea attributes
- { $$ = declspecs_add_attrs ($1, $2); }
- | declspecs_sc_ts_sa_noea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_ts_sa_ea typespec_reserved_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_sa_noea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- | declspecs_sc_nots_sa_ea typespec_attr
- { $$ = declspecs_add_type ($1, $2); }
- ;
-
-/* Particular useful classes of declspecs. */
-declspecs_ts:
- declspecs_nosc_ts_nosa_noea
- | declspecs_nosc_ts_nosa_ea
- | declspecs_nosc_ts_sa_noea
- | declspecs_nosc_ts_sa_ea
- | declspecs_sc_ts_nosa_noea
- | declspecs_sc_ts_nosa_ea
- | declspecs_sc_ts_sa_noea
- | declspecs_sc_ts_sa_ea
- ;
-
-declspecs_nots:
- declspecs_nosc_nots_nosa_noea
- | declspecs_nosc_nots_nosa_ea
- | declspecs_nosc_nots_sa_noea
- | declspecs_nosc_nots_sa_ea
- | declspecs_sc_nots_nosa_noea
- | declspecs_sc_nots_nosa_ea
- | declspecs_sc_nots_sa_noea
- | declspecs_sc_nots_sa_ea
- ;
-
-declspecs_ts_nosa:
- declspecs_nosc_ts_nosa_noea
- | declspecs_nosc_ts_nosa_ea
- | declspecs_sc_ts_nosa_noea
- | declspecs_sc_ts_nosa_ea
- ;
-
-declspecs_nots_nosa:
- declspecs_nosc_nots_nosa_noea
- | declspecs_nosc_nots_nosa_ea
- | declspecs_sc_nots_nosa_noea
- | declspecs_sc_nots_nosa_ea
- ;
-
-declspecs_nosc_ts:
- declspecs_nosc_ts_nosa_noea
- | declspecs_nosc_ts_nosa_ea
- | declspecs_nosc_ts_sa_noea
- | declspecs_nosc_ts_sa_ea
- ;
-
-declspecs_nosc_nots:
- declspecs_nosc_nots_nosa_noea
- | declspecs_nosc_nots_nosa_ea
- | declspecs_nosc_nots_sa_noea
- | declspecs_nosc_nots_sa_ea
- ;
-
-declspecs_nosc:
- declspecs_nosc_ts_nosa_noea
- | declspecs_nosc_ts_nosa_ea
- | declspecs_nosc_ts_sa_noea
- | declspecs_nosc_ts_sa_ea
- | declspecs_nosc_nots_nosa_noea
- | declspecs_nosc_nots_nosa_ea
- | declspecs_nosc_nots_sa_noea
- | declspecs_nosc_nots_sa_ea
- ;
-
-declspecs:
- declspecs_nosc_nots_nosa_noea
- | declspecs_nosc_nots_nosa_ea
- | declspecs_nosc_nots_sa_noea
- | declspecs_nosc_nots_sa_ea
- | declspecs_nosc_ts_nosa_noea
- | declspecs_nosc_ts_nosa_ea
- | declspecs_nosc_ts_sa_noea
- | declspecs_nosc_ts_sa_ea
- | declspecs_sc_nots_nosa_noea
- | declspecs_sc_nots_nosa_ea
- | declspecs_sc_nots_sa_noea
- | declspecs_sc_nots_sa_ea
- | declspecs_sc_ts_nosa_noea
- | declspecs_sc_ts_nosa_ea
- | declspecs_sc_ts_sa_noea
- | declspecs_sc_ts_sa_ea
- ;
-
-/* A (possibly empty) sequence of type qualifiers and attributes. */
-maybe_type_quals_attrs:
- /* empty */
- { $$ = NULL; }
- | declspecs_nosc_nots
- { $$ = $1; }
- ;
-
-/* A type specifier (but not a type qualifier).
- Once we have seen one of these in a declaration,
- if a typedef name appears then it is being redeclared.
-
- The _reserved versions start with a reserved word and may appear anywhere
- in the declaration specifiers; the _nonreserved versions may only
- appear before any other type specifiers, and after that are (if names)
- being redeclared.
-
- FIXME: should the _nonreserved version be restricted to names being
- redeclared only? The other entries there relate only the GNU extensions
- and Objective C, and are historically parsed thus, and don't make sense
- after other type specifiers, but it might be cleaner to count them as
- _reserved.
-
- _attr means: specifiers that either end with attributes,
- or are such that any following attributes would
- be parsed as part of the specifier.
-
- _nonattr: other specifiers not ending with attributes. */
-
-typespec_nonattr:
- typespec_reserved_nonattr
- | typespec_nonreserved_nonattr
- ;
-
-typespec_attr:
- typespec_reserved_attr
- ;
-
-typespec_reserved_nonattr:
- TYPESPEC
- { OBJC_NEED_RAW_IDENTIFIER (1);
- $$.kind = ctsk_resword;
- $$.spec = $1; }
- | structsp_nonattr
- ;
-
-typespec_reserved_attr:
- structsp_attr
- ;
-
-typespec_nonreserved_nonattr:
- TYPENAME
- { /* For a typedef name, record the meaning, not the name.
- In case of `foo foo, bar;'. */
- $$.kind = ctsk_typedef;
- $$.spec = lookup_name ($1); }
-@@ifobjc
- | CLASSNAME protocolrefs
- { $$.kind = ctsk_objc;
- $$.spec = objc_get_protocol_qualified_type ($1, $2); }
- | TYPENAME non_empty_protocolrefs
- { $$.kind = ctsk_objc;
- $$.spec = objc_get_protocol_qualified_type ($1, $2); }
-
-/* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
- - nisse@lysator.liu.se */
- | non_empty_protocolrefs
- { $$.kind = ctsk_objc;
- $$.spec = objc_get_protocol_qualified_type (NULL_TREE, $1); }
-@@end_ifobjc
- | typeof '(' expr ')'
- { skip_evaluation--;
- in_typeof--;
- if (TREE_CODE ($3.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND ($3.value, 1)))
- error ("%<typeof%> applied to a bit-field");
- $$.kind = ctsk_typeof;
- $$.spec = TREE_TYPE ($3.value);
- pop_maybe_used (variably_modified_type_p ($$.spec,
- NULL_TREE)); }
- | typeof '(' typename ')'
- { skip_evaluation--;
- in_typeof--;
- $$.kind = ctsk_typeof;
- $$.spec = groktypename ($3);
- pop_maybe_used (variably_modified_type_p ($$.spec,
- NULL_TREE)); }
- ;
-
-/* typespec_nonreserved_attr does not exist. */
-
-initdecls:
- initdcl
- | initdecls ',' maybe_resetattrs initdcl
- ;
-
-notype_initdecls:
- notype_initdcl
- | notype_initdecls ',' maybe_resetattrs notype_initdcl
- ;
-
-initdcl:
- declarator maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($1, current_declspecs, true,
- chainon ($3, all_prefix_attributes));
- if (!$<ttype>$)
- $<ttype>$ = error_mark_node;
- start_init ($<ttype>$, $2, global_bindings_p ()); }
- init
-/* Note how the declaration of the variable is in effect while its init is parsed! */
- { finish_init ();
- if ($<ttype>5 != error_mark_node)
- {
- maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
- finish_decl ($<ttype>5, $6.value, $2);
- }
- }
- | declarator maybeasm maybe_attribute
- { tree d = start_decl ($1, current_declspecs, false,
- chainon ($3, all_prefix_attributes));
- if (d)
- finish_decl (d, NULL_TREE, $2);
- }
- ;
-
-notype_initdcl:
- notype_declarator maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($1, current_declspecs, true,
- chainon ($3, all_prefix_attributes));
- if (!$<ttype>$)
- $<ttype>$ = error_mark_node;
- start_init ($<ttype>$, $2, global_bindings_p ()); }
- init
-/* Note how the declaration of the variable is in effect while its init is parsed! */
- { finish_init ();
- if ($<ttype>5 != error_mark_node)
- {
- maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
- finish_decl ($<ttype>5, $6.value, $2);
- }
- }
- | notype_declarator maybeasm maybe_attribute
- { tree d = start_decl ($1, current_declspecs, false,
- chainon ($3, all_prefix_attributes));
- if (d)
- finish_decl (d, NULL_TREE, $2); }
- ;
-/* the * rules are dummies to accept the Apollo extended syntax
- so that the header files compile. */
-maybe_attribute:
- /* empty */
- { $$ = NULL_TREE; }
- | attributes
- { $$ = $1; }
- ;
-
-attributes:
- attribute
- { $$ = $1; }
- | attributes attribute
- { $$ = chainon ($1, $2); }
- ;
-
-attribute:
- ATTRIBUTE stop_string_translation
- '(' '(' attribute_list ')' ')' start_string_translation
- { $$ = $5; }
- | ATTRIBUTE error start_string_translation
- { $$ = NULL_TREE; }
- ;
-
-attribute_list:
- attrib
- { $$ = $1; }
- | attribute_list ',' attrib
- { $$ = chainon ($1, $3); }
- ;
-
-attrib:
- /* empty */
- { $$ = NULL_TREE; }
- | any_word
- { $$ = build_tree_list ($1, NULL_TREE); }
- | any_word '(' IDENTIFIER ')'
- { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); }
- | any_word '(' IDENTIFIER ',' nonnull_exprlist ')'
- { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); }
- | any_word '(' exprlist ')'
- { $$ = build_tree_list ($1, $3); }
- ;
-
-/* This still leaves out most reserved keywords,
- shouldn't we include them? */
-
-any_word:
- identifier
- | scspec
- | TYPESPEC
- | TYPE_QUAL
- ;
-
-scspec:
- STATIC
- | SCSPEC
- ;
-
-/* Initializers. `init' is the entry point. */
-
-init:
- expr_no_commas
- { $$ = $1; }
- | '{'
- { really_start_incremental_init (NULL_TREE); }
- initlist_maybe_comma '}'
- { $$ = pop_init_level (0); }
- | error
- { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
- ;
-
-/* `initlist_maybe_comma' is the guts of an initializer in braces. */
-initlist_maybe_comma:
- /* empty */
- { if (pedantic)
- pedwarn ("ISO C forbids empty initializer braces"); }
- | initlist1 maybecomma
- ;
-
-initlist1:
- initelt
- | initlist1 ',' initelt
- ;
-
-/* `initelt' is a single element of an initializer.
- It may use braces. */
-initelt:
- designator_list '=' initval
- { if (pedantic && !flag_isoc99)
- pedwarn ("ISO C90 forbids specifying subobject to initialize"); }
- | array_designator initval
- { if (pedantic)
- pedwarn ("obsolete use of designated initializer without %<=%>"); }
- | identifier ':'
- { set_init_label ($1);
- if (pedantic)
- pedwarn ("obsolete use of designated initializer with %<:%>"); }
- initval
- {}
- | initval
- ;
-
-initval:
- '{'
- { push_init_level (0); }
- initlist_maybe_comma '}'
- { process_init_element (pop_init_level (0)); }
- | expr_no_commas
- { process_init_element ($1); }
- | error
- ;
-
-designator_list:
- designator
- | designator_list designator
- ;
-
-designator:
- '.' identifier
- { set_init_label ($2); }
- | array_designator
- ;
-
-array_designator:
- '[' expr_no_commas ELLIPSIS expr_no_commas ']'
- { set_init_index ($2.value, $4.value);
- if (pedantic)
- pedwarn ("ISO C forbids specifying range of elements to initialize"); }
- | '[' expr_no_commas ']'
- { set_init_index ($2.value, NULL_TREE); }
- ;
-
-nested_function:
- declarator
- { if (pedantic)
- pedwarn ("ISO C forbids nested functions");
-
- push_function_context ();
- if (!start_function (current_declspecs, $1,
- all_prefix_attributes))
- {
- pop_function_context ();
- YYERROR1;
- }
- }
- old_style_parm_decls save_location
- { tree decl = current_function_decl;
- 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_stmt (build_stmt (DECL_EXPR, decl)); }
- ;
-
-notype_nested_function:
- notype_declarator
- { if (pedantic)
- pedwarn ("ISO C forbids nested functions");
-
- push_function_context ();
- if (!start_function (current_declspecs, $1,
- all_prefix_attributes))
- {
- pop_function_context ();
- YYERROR1;
- }
- }
- old_style_parm_decls save_location
- { tree decl = current_function_decl;
- 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_stmt (build_stmt (DECL_EXPR, decl)); }
- ;
-
-/* Any kind of declarator (thus, all declarators allowed
- after an explicit typespec). */
-
-declarator:
- after_type_declarator
- | notype_declarator
- ;
-
-/* A declarator that is allowed only after an explicit typespec. */
-
-after_type_declarator:
- '(' maybe_attribute after_type_declarator ')'
- { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
- | after_type_declarator '(' parmlist_or_identifiers %prec '.'
- { $$ = build_function_declarator ($3, $1); }
- | after_type_declarator array_declarator %prec '.'
- { $$ = set_array_declarator_inner ($2, $1, false); }
- | '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
- { $$ = make_pointer_declarator ($2, $3); }
- | TYPENAME
- { $$ = build_id_declarator ($1); }
- ;
-
-/* Kinds of declarator that can appear in a parameter list
- in addition to notype_declarator. This is like after_type_declarator
- but does not allow a typedef name in parentheses as an identifier
- (because it would conflict with a function with that typedef as arg). */
-parm_declarator:
- parm_declarator_starttypename
- | parm_declarator_nostarttypename
- ;
-
-parm_declarator_starttypename:
- parm_declarator_starttypename '(' parmlist_or_identifiers %prec '.'
- { $$ = build_function_declarator ($3, $1); }
- | parm_declarator_starttypename array_declarator %prec '.'
- { $$ = set_array_declarator_inner ($2, $1, false); }
- | TYPENAME
- { $$ = build_id_declarator ($1); }
- ;
-
-parm_declarator_nostarttypename:
- parm_declarator_nostarttypename '(' parmlist_or_identifiers %prec '.'
- { $$ = build_function_declarator ($3, $1); }
- | parm_declarator_nostarttypename array_declarator %prec '.'
- { $$ = 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 ? build_attrs_declarator ($2, $3) : $3; }
- ;
-
-/* A declarator allowed whether or not there has been
- an explicit typespec. These cannot redeclare a typedef-name. */
-
-notype_declarator:
- notype_declarator '(' parmlist_or_identifiers %prec '.'
- { $$ = build_function_declarator ($3, $1); }
- | '(' maybe_attribute notype_declarator ')'
- { $$ = $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_inner ($2, $1, false); }
- | IDENTIFIER
- { $$ = build_id_declarator ($1); }
- ;
-
-struct_head:
- STRUCT
- { $$ = NULL_TREE; }
- | STRUCT attributes
- { $$ = $2; }
- ;
-
-union_head:
- UNION
- { $$ = NULL_TREE; }
- | UNION attributes
- { $$ = $2; }
- ;
-
-enum_head:
- ENUM
- { $$ = NULL_TREE; }
- | ENUM attributes
- { $$ = $2; }
- ;
-
-/* structsp_attr: struct/union/enum specifiers that either
- end with attributes, or are such that any following attributes would
- be parsed as part of the struct/union/enum specifier.
-
- structsp_nonattr: other struct/union/enum specifiers. */
-
-structsp_attr:
- struct_head identifier '{'
- { $<ttype>$ = start_struct (RECORD_TYPE, $2);
- /* Start scope of tag before parsing components. */
- }
- component_decl_list '}' maybe_attribute
- { $$.spec = finish_struct ($<ttype>4, nreverse ($5),
- chainon ($1, $7));
- $$.kind = ctsk_tagdef; }
- | struct_head '{' component_decl_list '}' maybe_attribute
- { $$.spec = finish_struct (start_struct (RECORD_TYPE,
- NULL_TREE),
- nreverse ($3), chainon ($1, $5));
- $$.kind = ctsk_tagdef;
- }
- | union_head identifier '{'
- { $<ttype>$ = start_struct (UNION_TYPE, $2); }
- component_decl_list '}' maybe_attribute
- { $$.spec = finish_struct ($<ttype>4, nreverse ($5),
- chainon ($1, $7));
- $$.kind = ctsk_tagdef; }
- | union_head '{' component_decl_list '}' maybe_attribute
- { $$.spec = finish_struct (start_struct (UNION_TYPE,
- NULL_TREE),
- nreverse ($3), chainon ($1, $5));
- $$.kind = ctsk_tagdef;
- }
- | enum_head identifier '{'
- { $<ttype>$ = start_enum ($2); }
- enumlist maybecomma_warn '}' maybe_attribute
- { $$.spec = finish_enum ($<ttype>4, nreverse ($5),
- chainon ($1, $8));
- $$.kind = ctsk_tagdef; }
- | enum_head '{'
- { $<ttype>$ = start_enum (NULL_TREE); }
- enumlist maybecomma_warn '}' maybe_attribute
- { $$.spec = finish_enum ($<ttype>3, nreverse ($4),
- chainon ($1, $7));
- $$.kind = ctsk_tagdef; }
- ;
-
-structsp_nonattr:
- struct_head identifier
- { $$ = parser_xref_tag (RECORD_TYPE, $2); }
- | union_head identifier
- { $$ = parser_xref_tag (UNION_TYPE, $2); }
- | enum_head identifier
- { $$ = parser_xref_tag (ENUMERAL_TYPE, $2);
- /* In ISO C, enumerated types can be referred to
- only if already defined. */
- if (pedantic && !COMPLETE_TYPE_P ($$.spec))
- pedwarn ("ISO C forbids forward references to %<enum%> types"); }
- ;
-
-maybecomma:
- /* empty */
- | ','
- ;
-
-maybecomma_warn:
- /* empty */
- | ','
- { if (pedantic && !flag_isoc99)
- 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 ($2, $1);
- pedwarn ("no semicolon at end of struct or union"); }
- ;
-
-component_decl_list2: /* empty */
- { $$ = NULL_TREE; }
- | component_decl_list2 component_decl ';'
- { $$ = chainon ($2, $1); }
- | component_decl_list2 ';'
- { if (pedantic)
- pedwarn ("extra semicolon in struct or union specified"); }
-@@ifobjc
- /* foo(sizeof(struct{ @defs(ClassName)})); */
- | 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
- {
- /* Support for unnamed structs or unions as members of
- structs or unions (which is [a] useful and [b] supports
- MS P-SDK). */
- $$ = grokfield (build_id_declarator (NULL_TREE),
- current_declspecs, NULL_TREE);
- POP_DECLSPEC_STACK; }
- | declspecs_nosc_nots setspecs components_notype
- { $$ = $3;
- POP_DECLSPEC_STACK; }
- | declspecs_nosc_nots
- { if (pedantic)
- pedwarn ("ISO C forbids member declarations with no members");
- shadow_tag_warned (finish_declspecs ($1), pedantic);
- $$ = NULL_TREE; }
- | error
- { $$ = NULL_TREE; }
- | extension component_decl
- { $$ = $2;
- RESTORE_EXT_FLAGS ($1); }
- ;
-
-components:
- component_declarator
- | components ',' maybe_resetattrs component_declarator
- { TREE_CHAIN ($4) = $1; $$ = $4; }
- ;
-
-components_notype:
- component_notype_declarator
- | components_notype ',' maybe_resetattrs component_notype_declarator
- { TREE_CHAIN ($4) = $1; $$ = $4; }
- ;
-
-component_declarator:
- 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 (build_id_declarator (NULL_TREE),
- current_declspecs, $2.value);
- decl_attributes (&$$,
- chainon ($3, all_prefix_attributes), 0); }
- ;
-
-component_notype_declarator:
- 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 (build_id_declarator (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 in structsp_attr. */
-
-enumlist:
- enumerator
- | enumlist ',' enumerator
- { if ($1 == error_mark_node)
- $$ = $1;
- else
- TREE_CHAIN ($3) = $1, $$ = $3; }
- | error
- { $$ = error_mark_node; }
- ;
-
-
-enumerator:
- identifier
- { $$ = build_enumerator ($1, NULL_TREE); }
- | identifier '=' expr_no_commas
- { $$ = build_enumerator ($1, $3.value); }
- ;
-
-typename:
- declspecs_nosc
- { pending_xref_error ();
- $<dsptype>$ = finish_declspecs ($1); }
- absdcl
- { $$ = XOBNEW (&parser_obstack, struct c_type_name);
- $$->specs = $<dsptype>2;
- $$->declarator = $3; }
- ;
-
-absdcl: /* an absolute declarator */
- /* empty */
- { $$ = build_id_declarator (NULL_TREE); }
- | absdcl1
- ;
-
-absdcl_maybe_attribute: /* absdcl maybe_attribute, but not just attributes */
- /* empty */
- { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
- build_id_declarator (NULL_TREE)); }
- | absdcl1
- { $$ = build_c_parm (current_declspecs, all_prefix_attributes,
- $1); }
- | absdcl1_noea attributes
- { $$ = build_c_parm (current_declspecs,
- chainon ($2, all_prefix_attributes),
- $1); }
- ;
-
-absdcl1: /* a nonempty absolute declarator */
- absdcl1_ea
- | absdcl1_noea
- ;
-
-absdcl1_noea:
- direct_absdcl1
- | '*' maybe_type_quals_attrs absdcl1_noea
- { $$ = make_pointer_declarator ($2, $3); }
- ;
-
-absdcl1_ea:
- '*' maybe_type_quals_attrs
- { $$ = make_pointer_declarator
- ($2, build_id_declarator (NULL_TREE)); }
- | '*' maybe_type_quals_attrs absdcl1_ea
- { $$ = make_pointer_declarator ($2, $3); }
- ;
-
-direct_absdcl1:
- '(' maybe_attribute absdcl1 ')'
- { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; }
- | direct_absdcl1 '(' parmlist
- { $$ = build_function_declarator ($3, $1); }
- | direct_absdcl1 array_declarator
- { $$ = set_array_declarator_inner ($2, $1, true); }
- | '(' parmlist
- { $$ = build_function_declarator
- ($2, build_id_declarator (NULL_TREE)); }
- | array_declarator
- { $$ = set_array_declarator_inner
- ($1, build_id_declarator (NULL_TREE), true); }
- ;
-
-/* The [...] part of a declarator for an array type. */
-
-array_declarator:
- '[' 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, false, false); }
- | '[' maybe_type_quals_attrs '*' ']'
- { $$ = 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_no_commas ']'
- { $$ = build_array_declarator ($4.value, $2, true, false); }
- ;
-
-/* A nonempty series of declarations and statements (possibly followed by
- some labels) that can form the body of a compound statement.
- NOTE: we don't allow labels on declarations; this might seem like a
- natural extension, but there would be a conflict between attributes
- on the label and prefix attributes on the declaration. */
-
-stmts_and_decls:
- lineno_stmt_decl_or_labels_ending_stmt
- | lineno_stmt_decl_or_labels_ending_decl
- | lineno_stmt_decl_or_labels_ending_label
- {
- error ("label at end of compound statement");
- }
- | lineno_stmt_decl_or_labels_ending_error
- ;
-
-lineno_stmt_decl_or_labels_ending_stmt:
- lineno_stmt
- | lineno_stmt_decl_or_labels_ending_stmt lineno_stmt
- | lineno_stmt_decl_or_labels_ending_decl lineno_stmt
- | lineno_stmt_decl_or_labels_ending_label lineno_stmt
- | lineno_stmt_decl_or_labels_ending_error lineno_stmt
- ;
-
-lineno_stmt_decl_or_labels_ending_decl:
- lineno_decl
- | lineno_stmt_decl_or_labels_ending_stmt lineno_decl
- {
- 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
- ;
-
-lineno_stmt_decl_or_labels_ending_label:
- lineno_label
- | lineno_stmt_decl_or_labels_ending_stmt lineno_label
- | lineno_stmt_decl_or_labels_ending_decl lineno_label
- | lineno_stmt_decl_or_labels_ending_label lineno_label
- | lineno_stmt_decl_or_labels_ending_error lineno_label
- ;
-
-lineno_stmt_decl_or_labels_ending_error:
- errstmt
- | lineno_stmt_decl_or_labels errstmt
- ;
-
-lineno_stmt_decl_or_labels:
- lineno_stmt_decl_or_labels_ending_stmt
- | lineno_stmt_decl_or_labels_ending_decl
- | lineno_stmt_decl_or_labels_ending_label
- | lineno_stmt_decl_or_labels_ending_error
- ;
-
-errstmt: error ';'
- ;
-
-/* Start and end blocks created for the new scopes of C99. */
-c99_block_start: /* empty */
- { $$ = c_begin_compound_stmt (flag_isoc99); }
- ;
-
-/* Read zero or more forward-declarations for labels
- that nested functions can jump to. */
-maybe_label_decls:
- /* empty */
- | label_decls
- { if (pedantic)
- pedwarn ("ISO C forbids label declarations"); }
- ;
-
-label_decls:
- label_decl
- | label_decls label_decl
- ;
-
-label_decl:
- LABEL identifiers_or_typenames ';'
- { tree link;
- for (link = $2; link; link = TREE_CHAIN (link))
- {
- tree label = declare_label (TREE_VALUE (link));
- C_DECLARED_LABEL_FLAG (label) = 1;
- add_stmt (build_stmt (DECL_EXPR, label));
- }
- }
- ;
-
-/* This is the body of a function definition.
- It causes syntax errors to ignore to the next openbrace. */
-compstmt_or_error:
- compstmt
- { add_stmt ($1); }
- | error compstmt
- ;
-
-compstmt_start: '{' { $$ = c_begin_compound_stmt (true); }
- ;
-
-compstmt_nostart: '}'
- | maybe_label_decls compstmt_contents_nonempty '}'
- ;
-
-compstmt_contents_nonempty:
- stmts_and_decls
- | error
- ;
-
-compstmt_primary_start:
- '(' '{'
- { if (cur_stmt_list == NULL)
- {
- error ("braced-group within expression allowed "
- "only inside a function");
- YYERROR;
- }
- $$ = c_begin_stmt_expr ();
- }
- ;
-
-compstmt: compstmt_start compstmt_nostart
- { $$ = 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_location:
- { if (yychar == YYEMPTY)
- yychar = YYLEX;
- $$ = input_location; }
- ;
-
-lineno_labels:
- /* empty */
- | lineno_labels lineno_label
- ;
-
-/* A labeled statement. In C99 it also generates an implicit block. */
-c99_block_lineno_labeled_stmt:
- c99_block_start lineno_labels lineno_stmt
- { $$ = c_end_compound_stmt ($1, flag_isoc99); }
- ;
-
-lineno_stmt:
- save_location stmt
- {
- /* Two cases cannot and do not have line numbers associated:
- If stmt is degenerate, such as "2;", then stmt is an
- 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_location label
- { if ($2) SET_EXPR_LOCATION ($2, $1); }
- ;
-
-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 ';'
- { c_finish_expr_stmt ($1); }
- | decl
- { check_for_loop_decls (); }
- ;
-
-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 ';'
- { $$ = c_finish_bc_stmt (&c_break_label, true); }
- | CONTINUE ';'
- { $$ = c_finish_bc_stmt (&c_cont_label, false); }
- | RETURN ';'
- { $$ = c_finish_return (NULL_TREE); }
- | RETURN expr ';'
- { $$ = c_finish_return ($2.value); }
- | asm_stmt
- | GOTO identifier ';'
- { $$ = c_finish_goto_label ($2); }
- | GOTO '*' expr ';'
- { $$ = 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 (grokparm ($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.
- ANSI C accepts labels only before statements, but we allow them
- also at the end of a compound statement. */
-
-label: CASE expr_no_commas ':'
- { $$ = do_case ($2.value, NULL_TREE); }
- | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
- { $$ = do_case ($2.value, $4.value); }
- | DEFAULT ':'
- { $$ = do_case (NULL_TREE, NULL_TREE); }
- | identifier save_location ':' maybe_attribute
- { tree label = define_label ($2, $1);
- if (label)
- {
- decl_attributes (&label, $4, 0);
- $$ = add_stmt (build_stmt (LABEL_EXPR, label));
- }
- else
- $$ = NULL_TREE;
- }
- ;
-
-/* Asm expressions and statements */
-
-/* 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
- '(' asm_string ')' start_string_translation
- { $$ = $4; }
- ;
-
-/* maybeasm: used for assembly names for declarations */
-maybeasm:
- /* empty */
- { $$ = NULL_TREE; }
- | 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 */
- asm_string
- { $$ = build_asm_expr ($1, 0, 0, 0, true); }
- /* output operands */
- | asm_string ':' asm_operands
- { $$ = build_asm_expr ($1, $3, 0, 0, false); }
- /* output and input operands */
- | asm_string ':' asm_operands ':' asm_operands
- { $$ = build_asm_expr ($1, $3, $5, 0, false); }
- /* output and input operands and clobbers */
- | asm_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
- in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
-asm_operands: /* empty */
- { $$ = NULL_TREE; }
- | nonnull_asm_operands
- ;
-
-nonnull_asm_operands:
- asm_operand
- | nonnull_asm_operands ',' asm_operand
- { $$ = chainon ($1, $3); }
- ;
-
-asm_operand:
- asm_string start_string_translation '(' expr ')'
- stop_string_translation
- { $$ = build_tree_list (build_tree_list (NULL_TREE, $1),
- $4.value); }
- | '[' identifier ']' asm_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), $7.value); }
- ;
-
-asm_clobbers:
- asm_string
- { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
- | asm_clobbers ',' asm_string
- { $$ = tree_cons (NULL_TREE, $3, $1); }
- ;
-
-/* Strings in 'asm' must be narrow strings. */
-asm_string:
- STRING
- { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE ($1)))
- != char_type_node)
- {
- error ("wide string literal in %<asm%>");
- $$ = build_string (1, "");
- }
- else
- $$ = $1; }
- ;
-
-stop_string_translation:
- { c_lex_string_translate = 0; }
- ;
-
-start_string_translation:
- { c_lex_string_translate = 1; }
- ;
-
-
-/* This is what appears inside the parens in a function declarator.
- Its value is a list of ..._TYPE nodes. Attributes must appear here
- to avoid a conflict with their appearance after an open parenthesis
- in an abstract declarator, as in
- "void bar (int (__attribute__((__mode__(SI))) int foo));". */
-parmlist:
- maybe_attribute
- { push_scope ();
- declare_parm_level (); }
- parmlist_1
- { $$ = $3;
- pop_scope (); }
- ;
-
-parmlist_1:
- parmlist_2 ')'
- | parms ';'
- { mark_forward_parm_decls (); }
- maybe_attribute
- { /* Dummy action so attributes are in known place
- on parser stack. */ }
- parmlist_1
- { $$ = $6; }
- | error ')'
- { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
- $$->parms = 0;
- $$->tags = 0;
- $$->types = 0;
- $$->others = 0; }
- ;
-
-/* This is what appears inside the parens in a function declarator.
- Its value is represented in the format that grokdeclarator expects. */
-parmlist_2: /* empty */
- { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
- $$->parms = 0;
- $$->tags = 0;
- $$->types = 0;
- $$->others = 0; }
- | ELLIPSIS
- { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
- $$->parms = 0;
- $$->tags = 0;
- $$->others = 0;
- /* Suppress -Wold-style-definition for this case. */
- $$->types = error_mark_node;
- error ("ISO C requires a named argument before %<...%>");
- }
- | parms
- { $$ = get_parm_info (/*ellipsis=*/false); }
- | parms ',' ELLIPSIS
- { $$ = get_parm_info (/*ellipsis=*/true); }
- ;
-
-parms:
- firstparm
- { push_parm_decl ($1); }
- | parms ',' parm
- { push_parm_decl ($3); }
- ;
-
-/* A single parameter declaration or parameter type name,
- as found in a parmlist. */
-parm:
- declspecs_ts setspecs parm_declarator maybe_attribute
- { $$ = build_c_parm (current_declspecs,
- chainon ($4, all_prefix_attributes), $3);
- POP_DECLSPEC_STACK; }
- | declspecs_ts setspecs notype_declarator maybe_attribute
- { $$ = 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_c_parm (current_declspecs,
- chainon ($4, all_prefix_attributes), $3);
- POP_DECLSPEC_STACK; }
-
- | declspecs_nots setspecs absdcl_maybe_attribute
- { $$ = $3;
- POP_DECLSPEC_STACK; }
- ;
-
-/* The first parm, which must suck attributes from off the top of the parser
- stack. */
-firstparm:
- declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
- { $$ = build_c_parm (current_declspecs,
- chainon ($4, all_prefix_attributes), $3);
- POP_DECLSPEC_STACK; }
- | declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
- { $$ = 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_c_parm (current_declspecs,
- chainon ($4, all_prefix_attributes), $3);
- POP_DECLSPEC_STACK; }
-
- | declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
- { $$ = $3;
- POP_DECLSPEC_STACK; }
- ;
-
-setspecs_fp:
- setspecs
- { prefix_attributes = chainon (prefix_attributes, $<ttype>-2);
- all_prefix_attributes = prefix_attributes; }
- ;
-
-/* This is used in a function definition
- where either a parmlist or an identifier list is ok.
- Its value is a list of ..._TYPE nodes or a list of identifiers. */
-parmlist_or_identifiers:
- maybe_attribute
- { push_scope ();
- declare_parm_level (); }
- parmlist_or_identifiers_1
- { $$ = $3;
- pop_scope (); }
- ;
-
-parmlist_or_identifiers_1:
- parmlist_1
- | identifiers ')'
- { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
- $$->parms = 0;
- $$->tags = 0;
- $$->types = $1;
- $$->others = 0;
-
- /* Make sure we have a parmlist after attributes. */
- if ($<ttype>-1 != 0)
- YYERROR1;
- }
- ;
-
-/* A nonempty list of identifiers. */
-identifiers:
- IDENTIFIER
- { $$ = build_tree_list (NULL_TREE, $1); }
- | identifiers ',' IDENTIFIER
- { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
- ;
-
-/* A nonempty list of identifiers, including typenames. */
-identifiers_or_typenames:
- identifier
- { $$ = build_tree_list (NULL_TREE, $1); }
- | identifiers_or_typenames ',' identifier
- { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
- ;
-
-extension:
- EXTENSION
- { $$ = SAVE_EXT_FLAGS ();
- pedantic = 0;
- warn_pointer_arith = 0;
- warn_traditional = 0;
- flag_iso = 0; }
- ;
-
-@@ifobjc
-/* Objective-C productions. */
-
-objcdef:
- classdef
- | classdecl
- | aliasdecl
- | protocoldef
- | methoddef
- | AT_END
- {
- objc_finish_implementation ();
- }
- ;
-
-/* A nonempty list of identifiers. */
-identifier_list:
- identifier
- { $$ = build_tree_list (NULL_TREE, $1); }
- | identifier_list ',' identifier
- { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
- ;
-
-classdecl:
- AT_CLASS identifier_list ';'
- {
- objc_declare_class ($2);
- }
- ;
-
-aliasdecl:
- AT_ALIAS identifier identifier ';'
- {
- objc_declare_alias ($2, $3);
- }
- ;
-
-superclass:
- ':' identifier { $$ = $2; }
- | /* NULL */ %prec HYPERUNARY { $$ = NULL_TREE; }
- ;
-
-class_ivars:
- '{' ivar_decl_list '}'
- | /* NULL */
- ;
-
-classdef:
- AT_INTERFACE identifier superclass protocolrefs
- {
- objc_start_class_interface ($2, $3, $4);
- }
- class_ivars
- {
- objc_continue_interface ();
- }
- methodprotolist AT_END
- {
- objc_finish_interface ();
- }
-
- | AT_IMPLEMENTATION identifier superclass
- {
- objc_start_class_implementation ($2, $3);
- }
- class_ivars
- {
- objc_continue_implementation ();
- }
-
- | AT_INTERFACE identifier '(' identifier ')' protocolrefs
- {
- objc_start_category_interface ($2, $4, $6);
- }
- methodprotolist AT_END
- {
- objc_finish_interface ();
- }
-
- | AT_IMPLEMENTATION identifier '(' identifier ')'
- {
- objc_start_category_implementation ($2, $4);
- }
- ;
-
-protocoldef:
- AT_PROTOCOL identifier protocolrefs
- {
- objc_pq_context = 1;
- objc_start_protocol ($2, $3);
- }
- methodprotolist AT_END
- {
- objc_pq_context = 0;
- objc_finish_interface ();
- }
- /* The @protocol forward-declaration production introduces a
- reduce/reduce conflict on ';', which should be resolved in
- favor of the production 'identifier_list -> identifier'. */
- | AT_PROTOCOL identifier_list ';'
- {
- objc_declare_protocols ($2);
- }
- ;
-
-protocolrefs:
- /* empty */
- {
- $$ = NULL_TREE;
- }
- | non_empty_protocolrefs
- ;
-
-non_empty_protocolrefs:
- ARITHCOMPARE identifier_list ARITHCOMPARE
- {
- if ($1 == LT_EXPR && $3 == GT_EXPR)
- $$ = $2;
- else
- YYERROR1;
- }
- ;
-
-ivar_decl_list:
- /* empty */
- | ivar_decl_list visibility_spec ivar_decls
- ;
-
-visibility_spec:
- /* empty */
- | AT_PRIVATE { objc_set_visibility (2); }
- | AT_PROTECTED { objc_set_visibility (0); }
- | AT_PUBLIC { objc_set_visibility (1); }
- ;
-
-ivar_decls:
- /* empty */
- | ivar_decls ivar_decl ';'
- | ivar_decls ';'
- {
- if (pedantic)
- pedwarn ("extra semicolon in struct or union specified");
- }
- ;
-
-ivar_decl:
- component_decl
- {
- /* Comma-separated ivars are chained together in
- reverse order; add them one by one. */
- tree ivar = nreverse ($1);
-
- for (; ivar; ivar = TREE_CHAIN (ivar))
- objc_add_instance_variable (copy_node (ivar));
- }
- ;
-
-opt_semi:
- /* NULL */
- | ';'
- {
- if (pedantic)
- pedwarn ("extra semicolon in method definition specified");
- }
- ;
-
-methodtype:
- '+'
- | '-'
- ;
-
-methoddef:
- methodtype
- {
- objc_set_method_type ($1);
- objc_pq_context = 1;
- }
- methoddecl opt_semi
- {
- objc_pq_context = 0;
- objc_start_method_definition ($3);
- }
- compstmt_or_error
- {
- objc_finish_method_definition (current_function_decl);
- }
- ;
-
-/* the reason for the strange actions in this rule
- is so that notype_initdecls when reached via datadef
- can find a valid list of type and sc specs in $0. */
-
-methodprotolist:
- /* empty */
- | methodprotolist methodproto
- | methodprotolist { $<ttype>$ = NULL_TREE; } datadef
- ;
-
-semi_or_error:
- ';'
- | error
- ;
-
-methodproto:
- methodtype
- {
- objc_set_method_type ($1);
- /* Remember protocol qualifiers in prototypes. */
- objc_pq_context = 1;
- }
- methoddecl
- {
- /* Forget protocol qualifiers here. */
- objc_pq_context = 0;
- objc_add_method_declaration ($3);
- }
- semi_or_error
- ;
-
-methoddecl:
- '(' objc_typename ')' unaryselector
- {
- $$ = objc_build_method_signature ($2, $4, NULL_TREE);
- }
-
- | unaryselector
- {
- $$ = objc_build_method_signature (NULL_TREE, $1, NULL_TREE);
- }
-
- | '(' objc_typename ')' keywordselector optparmlist
- {
- $$ = objc_build_method_signature ($2, $4, $5);
- }
-
- | keywordselector optparmlist
- {
- $$ = objc_build_method_signature (NULL_TREE, $1, $2);
- }
- ;
-
-/* Optional ObjC method parameters follow the C syntax, and may include '...'
- to denote a variable number of arguments. */
-
-optparmlist:
- optparms optellipsis
- {
- TREE_OVERFLOW ($$) = $2;
- }
- ;
-
-optparms:
- /* NULL */
- {
- $$ = make_node (TREE_LIST);
- }
- | optparms ',' parm
- {
- $$ = chainon ($1, build_tree_list (NULL_TREE,
- grokparm ($3)));
- }
- ;
-
-optellipsis:
- /* NULL */
- {
- $$ = 0;
- }
- | ',' ELLIPSIS
- {
- $$ = 1;
- }
- ;
-
-unaryselector:
- selector
- ;
-
-keywordselector:
- keyworddecl
-
- | keywordselector keyworddecl
- {
- $$ = chainon ($1, $2);
- }
- ;
-
-selector:
- IDENTIFIER
- | TYPENAME
- | CLASSNAME
- | reservedwords
- ;
-
-reservedwords:
- ENUM | STRUCT | UNION | IF | ELSE | WHILE | DO | FOR
- | SWITCH | CASE | DEFAULT | BREAK | CONTINUE | RETURN
- | GOTO | ASM_KEYWORD | SIZEOF | TYPEOF | ALIGNOF
- | TYPESPEC | TYPE_QUAL | OBJC_TYPE_QUAL
- ;
-
-objc_qual:
- OBJC_TYPE_QUAL
- ;
-
-objc_quals:
- objc_quals objc_qual
- {
- $$ = chainon ($1, build_tree_list (NULL_TREE, $2));
- }
- | /* NULL */
- {
- $$ = NULL_TREE;
- }
- ;
-
-objc_typename:
- objc_quals typename
- {
- $$ = build_tree_list ($1, groktypename ($2));
- }
- | objc_quals
- {
- $$ = build_tree_list ($1, NULL_TREE);
- }
- ;
-
-keyworddecl:
- selector ':' '(' objc_typename ')' identifier
- {
- $$ = objc_build_keyword_decl ($1, $4, $6);
- }
-
- | selector ':' identifier
- {
- $$ = objc_build_keyword_decl ($1, NULL_TREE, $3);
- }
-
- | ':' '(' objc_typename ')' identifier
- {
- $$ = objc_build_keyword_decl (NULL_TREE, $3, $5);
- }
-
- | ':' identifier
- {
- $$ = objc_build_keyword_decl (NULL_TREE, NULL_TREE, $2);
- }
- ;
-
-messageargs:
- selector
- | keywordarglist
- ;
-
-keywordarglist:
- keywordarg
- | keywordarglist keywordarg
- {
- $$ = chainon ($1, $2);
- }
- ;
-
-
-keywordexpr:
- nonnull_exprlist
- {
- if (TREE_CHAIN ($1) == NULL_TREE)
- /* just return the expr., remove a level of indirection */
- $$ = TREE_VALUE ($1);
- else
- /* we have a comma expr., we will collapse later */
- $$ = $1;
- }
- ;
-
-keywordarg:
- selector ':' keywordexpr
- {
- $$ = build_tree_list ($1, $3);
- }
- | ':' keywordexpr
- {
- $$ = build_tree_list (NULL_TREE, $2);
- }
- ;
-
-receiver:
- expr
- { $$ = $1.value; }
- | CLASSNAME
- {
- $$ = objc_get_class_reference ($1);
- }
- | TYPENAME
- {
- $$ = objc_get_class_reference ($1);
- }
- ;
-
-objcmessageexpr:
- '[' receiver messageargs ']'
- { $$ = build_tree_list ($2, $3); }
- ;
-
-selectorarg:
- selector
- | keywordnamelist
- ;
-
-keywordnamelist:
- keywordname
- | keywordnamelist keywordname
- {
- $$ = chainon ($1, $2);
- }
- ;
-
-keywordname:
- selector ':'
- {
- $$ = build_tree_list ($1, NULL_TREE);
- }
- | ':'
- {
- $$ = build_tree_list (NULL_TREE, NULL_TREE);
- }
- ;
-
-objcselectorexpr:
- AT_SELECTOR '(' selectorarg ')'
- {
- $$ = $3;
- }
- ;
-
-objcprotocolexpr:
- AT_PROTOCOL '(' identifier ')'
- {
- $$ = $3;
- }
- ;
-
-/* extension to support C-structures in the archiver */
-
-objcencodeexpr:
- AT_ENCODE '(' typename ')'
- {
- $$ = groktypename ($3);
- }
- ;
-
-@@end_ifobjc
-%%
-
-/* yylex() is a thin wrapper around c_lex(), all it does is translate
- cpplib.h's token codes into yacc's token codes. */
-
-static enum cpp_ttype last_token;
-
-/* The reserved keyword table. */
-struct resword
-{
- const char *word;
- ENUM_BITFIELD(rid) rid : 16;
- unsigned int disable : 16;
-};
-
-/* Disable mask. Keywords are disabled if (reswords[i].disable & mask) is
- _true_. */
-#define D_C89 0x01 /* not in C89 */
-#define D_EXT 0x02 /* GCC extension */
-#define D_EXT89 0x04 /* GCC extension incorporated in C99 */
-#define D_OBJC 0x08 /* Objective C only */
-
-static const struct resword reswords[] =
-{
- { "_Bool", RID_BOOL, 0 },
- { "_Complex", RID_COMPLEX, 0 },
- { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
- { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
- { "__alignof", RID_ALIGNOF, 0 },
- { "__alignof__", RID_ALIGNOF, 0 },
- { "__asm", RID_ASM, 0 },
- { "__asm__", RID_ASM, 0 },
- { "__attribute", RID_ATTRIBUTE, 0 },
- { "__attribute__", RID_ATTRIBUTE, 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 },
- { "__complex__", RID_COMPLEX, 0 },
- { "__const", RID_CONST, 0 },
- { "__const__", RID_CONST, 0 },
- { "__extension__", RID_EXTENSION, 0 },
- { "__func__", RID_C99_FUNCTION_NAME, 0 },
- { "__imag", RID_IMAGPART, 0 },
- { "__imag__", RID_IMAGPART, 0 },
- { "__inline", RID_INLINE, 0 },
- { "__inline__", RID_INLINE, 0 },
- { "__label__", RID_LABEL, 0 },
- { "__real", RID_REALPART, 0 },
- { "__real__", RID_REALPART, 0 },
- { "__restrict", RID_RESTRICT, 0 },
- { "__restrict__", RID_RESTRICT, 0 },
- { "__signed", RID_SIGNED, 0 },
- { "__signed__", RID_SIGNED, 0 },
- { "__thread", RID_THREAD, 0 },
- { "__typeof", RID_TYPEOF, 0 },
- { "__typeof__", RID_TYPEOF, 0 },
- { "__volatile", RID_VOLATILE, 0 },
- { "__volatile__", RID_VOLATILE, 0 },
- { "asm", RID_ASM, D_EXT },
- { "auto", RID_AUTO, 0 },
- { "break", RID_BREAK, 0 },
- { "case", RID_CASE, 0 },
- { "char", RID_CHAR, 0 },
- { "const", RID_CONST, 0 },
- { "continue", RID_CONTINUE, 0 },
- { "default", RID_DEFAULT, 0 },
- { "do", RID_DO, 0 },
- { "double", RID_DOUBLE, 0 },
- { "else", RID_ELSE, 0 },
- { "enum", RID_ENUM, 0 },
- { "extern", RID_EXTERN, 0 },
- { "float", RID_FLOAT, 0 },
- { "for", RID_FOR, 0 },
- { "goto", RID_GOTO, 0 },
- { "if", RID_IF, 0 },
- { "inline", RID_INLINE, D_EXT89 },
- { "int", RID_INT, 0 },
- { "long", RID_LONG, 0 },
- { "register", RID_REGISTER, 0 },
- { "restrict", RID_RESTRICT, D_C89 },
- { "return", RID_RETURN, 0 },
- { "short", RID_SHORT, 0 },
- { "signed", RID_SIGNED, 0 },
- { "sizeof", RID_SIZEOF, 0 },
- { "static", RID_STATIC, 0 },
- { "struct", RID_STRUCT, 0 },
- { "switch", RID_SWITCH, 0 },
- { "typedef", RID_TYPEDEF, 0 },
- { "typeof", RID_TYPEOF, D_EXT },
- { "union", RID_UNION, 0 },
- { "unsigned", RID_UNSIGNED, 0 },
- { "void", RID_VOID, 0 },
- { "volatile", RID_VOLATILE, 0 },
- { "while", RID_WHILE, 0 },
-
-@@ifobjc
-
- /* 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 },
- { "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 },
- { "byref", RID_BYREF, D_OBJC },
- { "in", RID_IN, D_OBJC },
- { "inout", RID_INOUT, D_OBJC },
- { "oneway", RID_ONEWAY, D_OBJC },
- { "out", RID_OUT, D_OBJC },
-@@end_ifobjc
-};
-#define N_reswords (sizeof reswords / sizeof (struct resword))
-
-/* Table mapping from RID_* constants to yacc token numbers.
- Unfortunately we have to have entries for all the keywords in all
- three languages. */
-static const short rid_to_yy[RID_MAX] =
-{
- /* RID_STATIC */ STATIC,
- /* RID_UNSIGNED */ TYPESPEC,
- /* RID_LONG */ TYPESPEC,
- /* RID_CONST */ TYPE_QUAL,
- /* RID_EXTERN */ SCSPEC,
- /* RID_REGISTER */ SCSPEC,
- /* RID_TYPEDEF */ SCSPEC,
- /* RID_SHORT */ TYPESPEC,
- /* RID_INLINE */ SCSPEC,
- /* RID_VOLATILE */ TYPE_QUAL,
- /* RID_SIGNED */ TYPESPEC,
- /* RID_AUTO */ SCSPEC,
- /* RID_RESTRICT */ TYPE_QUAL,
-
- /* C extensions */
- /* RID_COMPLEX */ TYPESPEC,
- /* RID_THREAD */ SCSPEC,
-
- /* C++ */
- /* RID_FRIEND */ 0,
- /* RID_VIRTUAL */ 0,
- /* RID_EXPLICIT */ 0,
- /* RID_EXPORT */ 0,
- /* RID_MUTABLE */ 0,
-
- /* ObjC */
- /* RID_IN */ OBJC_TYPE_QUAL,
- /* RID_OUT */ OBJC_TYPE_QUAL,
- /* RID_INOUT */ OBJC_TYPE_QUAL,
- /* RID_BYCOPY */ OBJC_TYPE_QUAL,
- /* RID_BYREF */ OBJC_TYPE_QUAL,
- /* RID_ONEWAY */ OBJC_TYPE_QUAL,
-
- /* C */
- /* RID_INT */ TYPESPEC,
- /* RID_CHAR */ TYPESPEC,
- /* RID_FLOAT */ TYPESPEC,
- /* RID_DOUBLE */ TYPESPEC,
- /* RID_VOID */ TYPESPEC,
- /* RID_ENUM */ ENUM,
- /* RID_STRUCT */ STRUCT,
- /* RID_UNION */ UNION,
- /* RID_IF */ IF,
- /* RID_ELSE */ ELSE,
- /* RID_WHILE */ WHILE,
- /* RID_DO */ DO,
- /* RID_FOR */ FOR,
- /* RID_SWITCH */ SWITCH,
- /* RID_CASE */ CASE,
- /* RID_DEFAULT */ DEFAULT,
- /* RID_BREAK */ BREAK,
- /* RID_CONTINUE */ CONTINUE,
- /* RID_RETURN */ RETURN,
- /* RID_GOTO */ GOTO,
- /* RID_SIZEOF */ SIZEOF,
-
- /* C extensions */
- /* RID_ASM */ ASM_KEYWORD,
- /* RID_TYPEOF */ TYPEOF,
- /* RID_ALIGNOF */ ALIGNOF,
- /* RID_ATTRIBUTE */ ATTRIBUTE,
- /* RID_VA_ARG */ VA_ARG,
- /* RID_EXTENSION */ EXTENSION,
- /* RID_IMAGPART */ IMAGPART,
- /* RID_REALPART */ REALPART,
- /* RID_LABEL */ LABEL,
-
- /* RID_CHOOSE_EXPR */ CHOOSE_EXPR,
- /* RID_TYPES_COMPATIBLE_P */ TYPES_COMPATIBLE_P,
-
- /* RID_FUNCTION_NAME */ FUNC_NAME,
- /* RID_PRETTY_FUNCTION_NAME */ FUNC_NAME,
- /* RID_C99_FUNCTION_NAME */ FUNC_NAME,
-
- /* C++ */
- /* RID_BOOL */ TYPESPEC,
- /* RID_WCHAR */ 0,
- /* RID_CLASS */ 0,
- /* RID_PUBLIC */ 0,
- /* RID_PRIVATE */ 0,
- /* RID_PROTECTED */ 0,
- /* RID_TEMPLATE */ 0,
- /* RID_NULL */ 0,
- /* RID_CATCH */ 0,
- /* RID_DELETE */ 0,
- /* RID_FALSE */ 0,
- /* RID_NAMESPACE */ 0,
- /* RID_NEW */ 0,
- /* RID_OFFSETOF */ OFFSETOF,
- /* RID_OPERATOR */ 0,
- /* RID_THIS */ 0,
- /* RID_THROW */ 0,
- /* RID_TRUE */ 0,
- /* RID_TRY */ 0,
- /* RID_TYPENAME */ 0,
- /* RID_TYPEID */ 0,
- /* RID_USING */ 0,
-
- /* casts */
- /* RID_CONSTCAST */ 0,
- /* RID_DYNCAST */ 0,
- /* RID_REINTCAST */ 0,
- /* RID_STATCAST */ 0,
-
- /* Objective C */
- /* 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 (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 (!c_dialect_objc ())
- mask |= D_OBJC;
-
- 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
- and so create a canonical spelling that isn't a keyword. */
- if (reswords[i].disable & mask)
- continue;
-
- id = get_identifier (reswords[i].word);
- C_RID_CODE (id) = reswords[i].rid;
- C_IS_RESERVED_WORD (id) = 1;
- ridpointers [(int) reswords[i].rid] = id;
- }
-}
-
-#define NAME(type) cpp_type2name (type)
-
-static void
-yyerror (const char *msgid)
-{
- c_parse_error (msgid, last_token, yylval.ttype);
-}
-
-static int
-yylexname (void)
-{
- 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 (!OBJC_IS_AT_KEYWORD (rid_code)
- && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
-@@end_ifobjc
- {
- /* Return the canonical spelling for this keyword. */
- yylval.ttype = ridpointers[(int) rid_code];
- return rid_to_yy[(int) rid_code];
- }
- }
-
- decl = lookup_name (yylval.ttype);
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- return TYPENAME;
- }
-@@ifobjc
- else
- {
- 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
- && (global_bindings_p ()
- || (!objc_force_identifier && !decl)))
- {
- yylval.ttype = objc_interface_decl;
- return CLASSNAME;
- }
- }
-@@end_ifobjc
-
- return IDENTIFIER;
-}
-
-static inline int
-_yylex (void)
-{
- get_next:
- last_token = c_lex (&yylval.ttype);
- switch (last_token)
- {
- case CPP_EQ: return '=';
- case CPP_NOT: return '!';
- case CPP_GREATER: yylval.code = GT_EXPR; return ARITHCOMPARE;
- case CPP_LESS: yylval.code = LT_EXPR; return ARITHCOMPARE;
- case CPP_PLUS: yylval.code = PLUS_EXPR; return '+';
- case CPP_MINUS: yylval.code = MINUS_EXPR; return '-';
- case CPP_MULT: yylval.code = MULT_EXPR; return '*';
- case CPP_DIV: yylval.code = TRUNC_DIV_EXPR; return '/';
- case CPP_MOD: yylval.code = TRUNC_MOD_EXPR; return '%';
- case CPP_AND: yylval.code = BIT_AND_EXPR; return '&';
- case CPP_OR: yylval.code = BIT_IOR_EXPR; return '|';
- case CPP_XOR: yylval.code = BIT_XOR_EXPR; return '^';
- case CPP_RSHIFT: yylval.code = RSHIFT_EXPR; return RSHIFT;
- case CPP_LSHIFT: yylval.code = LSHIFT_EXPR; return LSHIFT;
-
- case CPP_COMPL: return '~';
- case CPP_AND_AND: return ANDAND;
- case CPP_OR_OR: return OROR;
- case CPP_QUERY: return '?';
- case CPP_OPEN_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;
- case CPP_LESS_EQ: yylval.code = LE_EXPR; return ARITHCOMPARE;
-
- case CPP_PLUS_EQ: yylval.code = PLUS_EXPR; return ASSIGN;
- case CPP_MINUS_EQ: yylval.code = MINUS_EXPR; return ASSIGN;
- case CPP_MULT_EQ: yylval.code = MULT_EXPR; return ASSIGN;
- case CPP_DIV_EQ: yylval.code = TRUNC_DIV_EXPR; return ASSIGN;
- case CPP_MOD_EQ: yylval.code = TRUNC_MOD_EXPR; return ASSIGN;
- case CPP_AND_EQ: yylval.code = BIT_AND_EXPR; return ASSIGN;
- case CPP_OR_EQ: yylval.code = BIT_IOR_EXPR; return ASSIGN;
- case CPP_XOR_EQ: yylval.code = BIT_XOR_EXPR; return ASSIGN;
- case CPP_RSHIFT_EQ: yylval.code = RSHIFT_EXPR; return ASSIGN;
- case CPP_LSHIFT_EQ: yylval.code = LSHIFT_EXPR; return ASSIGN;
-
- case CPP_OPEN_SQUARE: return '[';
- case CPP_CLOSE_SQUARE: return ']';
- case CPP_OPEN_BRACE: return '{';
- case CPP_CLOSE_BRACE: return '}';
- case CPP_ELLIPSIS: return ELLIPSIS;
-
- case CPP_PLUS_PLUS: return PLUSPLUS;
- case CPP_MINUS_MINUS: return MINUSMINUS;
- 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:
- return 0;
-
- case CPP_NAME:
- 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:
- case CPP_WCHAR:
- return CONSTANT;
-
- case CPP_STRING:
- case CPP_WSTRING:
- return STRING;
-
- 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). */
- case CPP_SCOPE:
- case CPP_DEREF_STAR:
- case CPP_DOT_STAR:
- case CPP_MIN_EQ:
- case CPP_MAX_EQ:
- case CPP_MIN:
- case CPP_MAX:
- /* These tokens should not survive translation phase 4. */
- case CPP_HASH:
- case CPP_PASTE:
- error ("syntax error at %qs token", NAME(last_token));
- goto get_next;
-
- default:
- abort ();
- }
- /* NOTREACHED */
-}
-
-static int
-yylex (void)
-{
- int r;
- timevar_push (TV_LEX);
- r = _yylex();
- timevar_pop (TV_LEX);
- return r;
-}
-
-/* Function used when yydebug is set, to print a token in more detail. */
-
-static void
-yyprint (FILE *file, int yychar, YYSTYPE yyl)
-{
- tree t = yyl.ttype;
-
- fprintf (file, " [%s]", NAME(last_token));
-
- switch (yychar)
- {
- case IDENTIFIER:
- case TYPENAME:
- case TYPESPEC:
- case TYPE_QUAL:
- case SCSPEC:
- case STATIC:
- if (IDENTIFIER_POINTER (t))
- fprintf (file, " '%s'", IDENTIFIER_POINTER (t));
- break;
-
- case CONSTANT:
- fprintf (file, " %s", GET_MODE_NAME (TYPE_MODE (TREE_TYPE (t))));
- if (TREE_CODE (t) == INTEGER_CST)
- {
- fputs (" ", file);
- fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
- }
- break;
- }
-}
-
-/* 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
-c_parse_file (void)
-{
- yyparse ();
-
- if (malloced_yyss)
- {
- free (malloced_yyss);
- free (malloced_yyvs);
- malloced_yyss = 0;
- }
-}
-
-#ifdef __XGETTEXT__
-/* Depending on the version of Bison used to compile this grammar,
- it may issue generic diagnostics spelled "syntax error" or
- "parse error". To prevent this from changing the translation
- template randomly, we list all the variants of this particular
- diagnostic here. Translators: there is no fine distinction
- between diagnostics with "syntax error" in them, and diagnostics
- with "parse error" in them. It's okay to give them both the same
- translation. */
-const char d1[] = N_("syntax error");
-const char d2[] = N_("parse error");
-const char d3[] = N_("syntax error; also virtual memory exhausted");
-const char d4[] = N_("parse error; also virtual memory exhausted");
-const char d5[] = N_("syntax error: cannot back up");
-const char d6[] = N_("parse error: cannot back up");
-#endif
-
-#include "gt-c-parse.h"
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
new file mode 100644
index 0000000..adebfd2
--- /dev/null
+++ b/gcc/c-parser.c
@@ -0,0 +1,6219 @@
+/* Parser for C and Objective-C.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+ Parser actions based on the old Bison parser; structure somewhat
+ influenced by and fragments based on the C++ parser.
+
+This file is part of GCC.
+
+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.
+
+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 GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* TODO:
+
+ Make sure all relevant comments, and all relevant code from all
+ actions, brought over from old parser. Verify exact correspondence
+ of syntax accepted.
+
+ Add testcases covering every input symbol in every state in old and
+ new parsers.
+
+ Include full syntax for GNU C, including erroneous cases accepted
+ with error messages, in syntax productions in comments.
+
+ Make more diagnostics in the front end generally take an explicit
+ location rather than implicitly using input_location. */
+
+#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 "timevar.h"
+#include "c-pragma.h"
+#include "c-tree.h"
+#include "flags.h"
+#include "output.h"
+#include "toplev.h"
+#include "ggc.h"
+#include "c-common.h"
+
+
+/* Miscellaneous data and functions needed for the parser. */
+
+int yydebug;
+
+/* Objective-C specific parser/lexer information. */
+
+static int objc_pq_context = 0;
+
+/* The following flag is needed to contextualize Objective-C lexical
+ analysis. In some cases (e.g., 'int NSObject;'), it is undesirable
+ to bind an identifier to an Objective-C class, even if a class with
+ that name exists. */
+static int objc_need_raw_identifier = 0;
+#define OBJC_NEED_RAW_IDENTIFIER(VAL) \
+ do { \
+ if (c_dialect_objc ()) \
+ objc_need_raw_identifier = VAL; \
+ } while (0)
+
+/* The reserved keyword table. */
+struct resword
+{
+ const char *word;
+ ENUM_BITFIELD(rid) rid : 16;
+ unsigned int disable : 16;
+};
+
+/* Disable mask. Keywords are disabled if (reswords[i].disable &
+ mask) is _true_. */
+#define D_C89 0x01 /* not in C89 */
+#define D_EXT 0x02 /* GCC extension */
+#define D_EXT89 0x04 /* GCC extension incorporated in C99 */
+#define D_OBJC 0x08 /* Objective C only */
+
+static const struct resword reswords[] =
+{
+ { "_Bool", RID_BOOL, 0 },
+ { "_Complex", RID_COMPLEX, 0 },
+ { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
+ { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
+ { "__alignof", RID_ALIGNOF, 0 },
+ { "__alignof__", RID_ALIGNOF, 0 },
+ { "__asm", RID_ASM, 0 },
+ { "__asm__", RID_ASM, 0 },
+ { "__attribute", RID_ATTRIBUTE, 0 },
+ { "__attribute__", RID_ATTRIBUTE, 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 },
+ { "__complex__", RID_COMPLEX, 0 },
+ { "__const", RID_CONST, 0 },
+ { "__const__", RID_CONST, 0 },
+ { "__extension__", RID_EXTENSION, 0 },
+ { "__func__", RID_C99_FUNCTION_NAME, 0 },
+ { "__imag", RID_IMAGPART, 0 },
+ { "__imag__", RID_IMAGPART, 0 },
+ { "__inline", RID_INLINE, 0 },
+ { "__inline__", RID_INLINE, 0 },
+ { "__label__", RID_LABEL, 0 },
+ { "__real", RID_REALPART, 0 },
+ { "__real__", RID_REALPART, 0 },
+ { "__restrict", RID_RESTRICT, 0 },
+ { "__restrict__", RID_RESTRICT, 0 },
+ { "__signed", RID_SIGNED, 0 },
+ { "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
+ { "__typeof", RID_TYPEOF, 0 },
+ { "__typeof__", RID_TYPEOF, 0 },
+ { "__volatile", RID_VOLATILE, 0 },
+ { "__volatile__", RID_VOLATILE, 0 },
+ { "asm", RID_ASM, D_EXT },
+ { "auto", RID_AUTO, 0 },
+ { "break", RID_BREAK, 0 },
+ { "case", RID_CASE, 0 },
+ { "char", RID_CHAR, 0 },
+ { "const", RID_CONST, 0 },
+ { "continue", RID_CONTINUE, 0 },
+ { "default", RID_DEFAULT, 0 },
+ { "do", RID_DO, 0 },
+ { "double", RID_DOUBLE, 0 },
+ { "else", RID_ELSE, 0 },
+ { "enum", RID_ENUM, 0 },
+ { "extern", RID_EXTERN, 0 },
+ { "float", RID_FLOAT, 0 },
+ { "for", RID_FOR, 0 },
+ { "goto", RID_GOTO, 0 },
+ { "if", RID_IF, 0 },
+ { "inline", RID_INLINE, D_EXT89 },
+ { "int", RID_INT, 0 },
+ { "long", RID_LONG, 0 },
+ { "register", RID_REGISTER, 0 },
+ { "restrict", RID_RESTRICT, D_C89 },
+ { "return", RID_RETURN, 0 },
+ { "short", RID_SHORT, 0 },
+ { "signed", RID_SIGNED, 0 },
+ { "sizeof", RID_SIZEOF, 0 },
+ { "static", RID_STATIC, 0 },
+ { "struct", RID_STRUCT, 0 },
+ { "switch", RID_SWITCH, 0 },
+ { "typedef", RID_TYPEDEF, 0 },
+ { "typeof", RID_TYPEOF, D_EXT },
+ { "union", RID_UNION, 0 },
+ { "unsigned", RID_UNSIGNED, 0 },
+ { "void", RID_VOID, 0 },
+ { "volatile", RID_VOLATILE, 0 },
+ { "while", RID_WHILE, 0 },
+ /* These Objective-C 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 },
+ { "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 },
+ { "byref", RID_BYREF, D_OBJC },
+ { "in", RID_IN, D_OBJC },
+ { "inout", RID_INOUT, D_OBJC },
+ { "oneway", RID_ONEWAY, D_OBJC },
+ { "out", RID_OUT, D_OBJC },
+};
+#define N_reswords (sizeof reswords / sizeof (struct resword))
+
+/* Initialization routine for this file. */
+
+void
+c_parse_init (void)
+{
+ /* The only initialization required is of the reserved word
+ identifiers. */
+ 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 (!c_dialect_objc ())
+ mask |= D_OBJC;
+
+ 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
+ and so create a canonical spelling that isn't a keyword. */
+ if (reswords[i].disable & mask)
+ continue;
+
+ id = get_identifier (reswords[i].word);
+ C_RID_CODE (id) = reswords[i].rid;
+ C_IS_RESERVED_WORD (id) = 1;
+ ridpointers [(int) reswords[i].rid] = id;
+ }
+}
+
+/* The C lexer intermediates between the lexer in cpplib and c-lex.c
+ and the C parser. Unlike the C++ lexer, the parser structure
+ stores the lexer information instead of using a separate structure.
+ Identifiers are separated into ordinary identifiers, type names,
+ keywords and some other Objective-C types of identifiers, and some
+ look-ahead is maintained.
+
+ ??? It might be a good idea to lex the whole file up front (as for
+ C++). It would then be possible to share more of the C and C++
+ lexer code, if desired. */
+
+/* The following local token type is used. */
+
+/* A keyword. */
+#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
+
+/* The number of token types, including C-specific ones. */
+#define N_C_TTYPES ((int) (CPP_KEYWORD + 1))
+
+/* More information about the type of a CPP_NAME token. */
+typedef enum c_id_kind {
+ /* An ordinary identifier. */
+ C_ID_ID,
+ /* An identifier declared as a typedef name. */
+ C_ID_TYPENAME,
+ /* An identifier declared as an Objective-C class name. */
+ C_ID_CLASSNAME,
+ /* Not an identifier. */
+ C_ID_NONE
+} c_id_kind;
+
+/* A single C token after string literal concatenation and conversion
+ of preprocessing tokens to tokens. */
+typedef struct c_token GTY (())
+{
+ /* The kind of token. */
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ /* If this token is a CPP_NAME, this value indicates whether also
+ declared as some kind of type. Otherwise, it is C_ID_NONE. */
+ ENUM_BITFIELD (c_id_kind) id_kind : 8;
+ /* If this token is a keyword, this value indicates which keyword.
+ Otherwise, this value is RID_MAX. */
+ ENUM_BITFIELD (rid) keyword : 8;
+ /* True if this token is from a system header. */
+ BOOL_BITFIELD in_system_header : 1;
+ /* The value associated with this token, if any. */
+ tree value;
+ /* The location at which this token was found. */
+ location_t location;
+} c_token;
+
+/* A parser structure recording information about the state and
+ context of parsing. Includes lexer information with up to two
+ tokens of look-ahead; more are not needed for C. */
+typedef struct c_parser GTY(())
+{
+ /* The look-ahead tokens. */
+ c_token tokens[2];
+ /* How many look-ahead tokens are available (0, 1 or 2). */
+ short tokens_avail;
+ /* True if a syntax error is being recovered from; false otherwise.
+ c_parser_error sets this flag. It should clear this flag when
+ enough tokens have been consumed to recover from the error. */
+ BOOL_BITFIELD error : 1;
+} c_parser;
+
+/* Read in and lex a single token, storing it in *TOKEN. */
+
+static void
+c_lex_one_token (c_token *token)
+{
+ timevar_push (TV_LEX);
+ token->type = c_lex (&token->value);
+ token->location = input_location;
+ token->in_system_header = in_system_header;
+ switch (token->type)
+ {
+ case CPP_NAME:
+ token->id_kind = C_ID_NONE;
+ token->keyword = RID_MAX;
+ {
+ tree decl;
+
+ int objc_force_identifier = objc_need_raw_identifier;
+ OBJC_NEED_RAW_IDENTIFIER (0);
+
+ if (C_IS_RESERVED_WORD (token->value))
+ {
+ enum rid rid_code = C_RID_CODE (token->value);
+
+ if (c_dialect_objc ())
+ {
+ if (!OBJC_IS_AT_KEYWORD (rid_code)
+ && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
+ {
+ /* Return the canonical spelling for this keyword. */
+ token->value = ridpointers[(int) rid_code];
+ token->type = CPP_KEYWORD;
+ token->keyword = rid_code;
+ break;
+ }
+ }
+ else
+ {
+ /* Return the canonical spelling for this keyword. */
+ token->value = ridpointers[(int) rid_code];
+ token->type = CPP_KEYWORD;
+ token->keyword = rid_code;
+ break;
+ }
+ }
+
+ decl = lookup_name (token->value);
+ if (decl)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ token->id_kind = C_ID_TYPENAME;
+ break;
+ }
+ }
+ else if (c_dialect_objc ())
+ {
+ tree objc_interface_decl = objc_is_class_name (token->value);
+ /* Objective-C 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)))
+ {
+ token->value = objc_interface_decl;
+ token->id_kind = C_ID_CLASSNAME;
+ break;
+ }
+ }
+ }
+ token->id_kind = C_ID_ID;
+ break;
+ case CPP_AT_NAME:
+ /* This only happens in Objective-C; it must be a keyword. */
+ token->type = CPP_KEYWORD;
+ token->id_kind = C_ID_NONE;
+ token->keyword = C_RID_CODE (token->value);
+ break;
+ case CPP_COLON:
+ case CPP_COMMA:
+ case CPP_CLOSE_PAREN:
+ case CPP_SEMICOLON:
+ /* These tokens may affect the interpretation of any identifiers
+ following, if doing Objective-C. */
+ OBJC_NEED_RAW_IDENTIFIER (0);
+ token->id_kind = C_ID_NONE;
+ token->keyword = RID_MAX;
+ break;
+ default:
+ token->id_kind = C_ID_NONE;
+ token->keyword = RID_MAX;
+ break;
+ }
+ timevar_pop (TV_LEX);
+}
+
+/* Return a pointer to the next token from PARSER, reading it in if
+ necessary. */
+
+static inline c_token *
+c_parser_peek_token (c_parser *parser)
+{
+ if (parser->tokens_avail == 0)
+ {
+ c_lex_one_token (&parser->tokens[0]);
+ parser->tokens_avail = 1;
+ }
+ return &parser->tokens[0];
+}
+
+/* Return true if the next token from PARSER has the indicated
+ TYPE. */
+
+static inline bool
+c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
+{
+ return c_parser_peek_token (parser)->type == type;
+}
+
+/* Return true if the next token from PARSER does not have the
+ indicated TYPE. */
+
+static inline bool
+c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
+{
+ return !c_parser_next_token_is (parser, type);
+}
+
+/* Return true if the next token from PARSER is the indicated
+ KEYWORD. */
+
+static inline bool
+c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
+{
+ c_token *token;
+
+ /* Peek at the next token. */
+ token = c_parser_peek_token (parser);
+ /* Check to see if it is the indicated keyword. */
+ return token->keyword == keyword;
+}
+
+/* Return true if TOKEN can start a type name,
+ false otherwise. */
+static bool
+c_token_starts_typename (c_token *token)
+{
+ switch (token->type)
+ {
+ case CPP_NAME:
+ switch (token->id_kind)
+ {
+ case C_ID_ID:
+ return false;
+ case C_ID_TYPENAME:
+ return true;
+ case C_ID_CLASSNAME:
+ gcc_assert (c_dialect_objc ());
+ return true;
+ default:
+ gcc_unreachable ();
+ }
+ case CPP_KEYWORD:
+ switch (token->keyword)
+ {
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ case RID_COMPLEX:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_BOOL:
+ case RID_ENUM:
+ case RID_STRUCT:
+ case RID_UNION:
+ case RID_TYPEOF:
+ case RID_CONST:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ case RID_ATTRIBUTE:
+ return true;
+ default:
+ return false;
+ }
+ case CPP_LESS:
+ if (c_dialect_objc ())
+ return true;
+ return false;
+ default:
+ return false;
+ }
+}
+
+/* Return true if the next token from PARSER can start a type name,
+ false otherwise. */
+static inline bool
+c_parser_next_token_starts_typename (c_parser *parser)
+{
+ c_token *token = c_parser_peek_token (parser);
+ return c_token_starts_typename (token);
+}
+
+/* Return true if TOKEN can start declaration specifiers, false
+ otherwise. */
+static bool
+c_token_starts_declspecs (c_token *token)
+{
+ switch (token->type)
+ {
+ case CPP_NAME:
+ switch (token->id_kind)
+ {
+ case C_ID_ID:
+ return false;
+ case C_ID_TYPENAME:
+ return true;
+ case C_ID_CLASSNAME:
+ gcc_assert (c_dialect_objc ());
+ return true;
+ default:
+ gcc_unreachable ();
+ }
+ case CPP_KEYWORD:
+ switch (token->keyword)
+ {
+ case RID_STATIC:
+ case RID_EXTERN:
+ case RID_REGISTER:
+ case RID_TYPEDEF:
+ case RID_INLINE:
+ case RID_AUTO:
+ case RID_THREAD:
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ case RID_COMPLEX:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_BOOL:
+ case RID_ENUM:
+ case RID_STRUCT:
+ case RID_UNION:
+ case RID_TYPEOF:
+ case RID_CONST:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ case RID_ATTRIBUTE:
+ return true;
+ default:
+ return false;
+ }
+ case CPP_LESS:
+ if (c_dialect_objc ())
+ return true;
+ return false;
+ default:
+ return false;
+ }
+}
+
+/* Return true if the next token from PARSER can start declaration
+ specifiers, false otherwise. */
+static inline bool
+c_parser_next_token_starts_declspecs (c_parser *parser)
+{
+ c_token *token = c_parser_peek_token (parser);
+ return c_token_starts_declspecs (token);
+}
+
+/* Return a pointer to the next-but-one token from PARSER, reading it
+ in if necessary. The next token is already read in. */
+
+static c_token *
+c_parser_peek_2nd_token (c_parser *parser)
+{
+ if (parser->tokens_avail >= 2)
+ return &parser->tokens[1];
+ gcc_assert (parser->tokens_avail == 1);
+ gcc_assert (parser->tokens[0].type != CPP_EOF);
+ c_lex_one_token (&parser->tokens[1]);
+ parser->tokens_avail = 2;
+ return &parser->tokens[1];
+}
+
+/* Consume the next token from PARSER. */
+
+static void
+c_parser_consume_token (c_parser *parser)
+{
+ if (parser->tokens_avail == 2)
+ parser->tokens[0] = parser->tokens[1];
+ else
+ {
+ gcc_assert (parser->tokens_avail == 1);
+ gcc_assert (parser->tokens[0].type != CPP_EOF);
+ }
+ parser->tokens_avail--;
+}
+
+/* Update the globals input_location and in_system_header from
+ TOKEN. */
+static inline void
+c_parser_set_source_position_from_token (c_token *token)
+{
+ if (token->type != CPP_EOF)
+ {
+ input_location = token->location;
+ in_system_header = token->in_system_header;
+ }
+}
+
+/* Allocate a new parser. */
+
+static c_parser *
+c_parser_new (void)
+{
+ /* Use local storage to lex the first token because loading a PCH
+ file may cause garbage collection. */
+ c_parser tparser;
+ c_parser *ret;
+ memset (&tparser, 0, sizeof tparser);
+ c_lex_one_token (&tparser.tokens[0]);
+ tparser.tokens_avail = 1;
+ ret = GGC_NEW (c_parser);
+ memcpy (ret, &tparser, sizeof tparser);
+ return ret;
+}
+
+/* Issue a diagnostic of the form
+ FILE:LINE: MESSAGE before TOKEN
+ where TOKEN is the next token in the input stream of PARSER.
+ MESSAGE (specified by the caller) is usually of the form "expected
+ OTHER-TOKEN".
+
+ Do not issue a diagnostic if still recovering from an error.
+
+ ??? This is taken from the C++ parser, but building up messages in
+ this way is not i18n-friendly and some other approach should be
+ used. */
+
+static void
+c_parser_error (c_parser *parser, const char *msgid)
+{
+ c_token *token = c_parser_peek_token (parser);
+ if (parser->error)
+ return;
+ parser->error = true;
+ if (!msgid)
+ return;
+ /* This diagnostic makes more sense if it is tagged to the line of
+ the token we just peeked at. */
+ c_parser_set_source_position_from_token (token);
+ c_parse_error (msgid,
+ /* Because c_parse_error does not understand
+ CPP_KEYWORD, keywords are treated like
+ identifiers. */
+ (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
+ token->value);
+}
+
+/* If the next token is of the indicated TYPE, consume it. Otherwise,
+ issue the error MSGID. If MSGID is NULL then a message has already
+ been produced and no message will be produced this time. Returns
+ true if found, false otherwise. */
+
+static bool
+c_parser_require (c_parser *parser,
+ enum cpp_ttype type,
+ const char *msgid)
+{
+ if (c_parser_next_token_is (parser, type))
+ {
+ c_parser_consume_token (parser);
+ return true;
+ }
+ else
+ {
+ c_parser_error (parser, msgid);
+ return false;
+ }
+}
+
+/* If the next token is the indicated keyword, consume it. Otherwise,
+ issue the error MSGID. Returns true if found, false otherwise. */
+
+static bool
+c_parser_require_keyword (c_parser *parser,
+ enum rid keyword,
+ const char *msgid)
+{
+ if (c_parser_next_token_is_keyword (parser, keyword))
+ {
+ c_parser_consume_token (parser);
+ return true;
+ }
+ else
+ {
+ c_parser_error (parser, msgid);
+ return false;
+ }
+}
+
+/* Like c_parser_require, except that tokens will be skipped until the
+ desired token is found. An error message is still produced if the
+ next token is not as expected. If MSGID is NULL then a message has
+ already been produced and no message will be produced this
+ time. */
+
+static void
+c_parser_skip_until_found (c_parser *parser,
+ enum cpp_ttype type,
+ const char *msgid)
+{
+ unsigned nesting_depth = 0;
+
+ if (c_parser_require (parser, type, msgid))
+ return;
+
+ /* Skip tokens until the desired token is found. */
+ while (true)
+ {
+ /* Peek at the next token. */
+ c_token *token = c_parser_peek_token (parser);
+ /* If we've reached the token we want, consume it and stop. */
+ if (token->type == type && !nesting_depth)
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* If we've run out of tokens, stop. */
+ if (token->type == CPP_EOF)
+ return;
+ if (token->type == CPP_OPEN_BRACE
+ || token->type == CPP_OPEN_PAREN
+ || token->type == CPP_OPEN_SQUARE)
+ ++nesting_depth;
+ else if (token->type == CPP_CLOSE_BRACE
+ || token->type == CPP_CLOSE_PAREN
+ || token->type == CPP_CLOSE_SQUARE)
+ {
+ if (nesting_depth-- == 0)
+ break;
+ }
+ /* Consume this token. */
+ c_parser_consume_token (parser);
+ }
+ parser->error = false;
+}
+
+/* Skip tokens until the end of a parameter is found, but do not
+ consume the comma, semicolon or closing delimiter. */
+
+static void
+c_parser_skip_to_end_of_parameter (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
+ && !nesting_depth)
+ break;
+ /* If we've run out of tokens, stop. */
+ if (token->type == CPP_EOF)
+ return;
+ if (token->type == CPP_OPEN_BRACE
+ || token->type == CPP_OPEN_PAREN
+ || token->type == CPP_OPEN_SQUARE)
+ ++nesting_depth;
+ else if (token->type == CPP_CLOSE_BRACE
+ || token->type == CPP_CLOSE_PAREN
+ || token->type == CPP_CLOSE_SQUARE)
+ {
+ if (nesting_depth-- == 0)
+ break;
+ }
+ /* Consume this token. */
+ c_parser_consume_token (parser);
+ }
+ parser->error = false;
+}
+
+/* Skip tokens until we have consumed an entire block, or until we
+ have consumed a non-nested ';'. */
+
+static void
+c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+
+ while (true)
+ {
+ c_token *token;
+
+ /* Peek at the next token. */
+ token = c_parser_peek_token (parser);
+ /* If we've run out of tokens, stop. */
+ if (token->type == CPP_EOF)
+ return;
+ /* If the next token is a ';', we have reached the end of the
+ statement. */
+ if (token->type == CPP_SEMICOLON && !nesting_depth)
+ {
+ /* Consume the ';'. */
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* If the next token is a non-nested '}', then we have reached
+ the end of the current block. */
+ if (token->type == CPP_CLOSE_BRACE
+ && (nesting_depth == 0 || --nesting_depth == 0))
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* If it the next token is a '{', then we are entering a new
+ block. Consume the entire block. */
+ if (token->type == CPP_OPEN_BRACE)
+ ++nesting_depth;
+ c_parser_consume_token (parser);
+ }
+ parser->error = false;
+}
+
+
+/* Save the warning flags which are controlled by __extension__. */
+
+static inline int
+disable_extension_diagnostics (void)
+{
+ int ret = (pedantic
+ | (warn_pointer_arith << 1)
+ | (warn_traditional << 2)
+ | (flag_iso << 3));
+ pedantic = 0;
+ warn_pointer_arith = 0;
+ warn_traditional = 0;
+ flag_iso = 0;
+ return ret;
+}
+
+/* Restore the warning flags which are controlled by __extension__.
+ FLAGS is the return value from disable_extension_diagnostics. */
+
+static inline void
+restore_extension_diagnostics (int flags)
+{
+ pedantic = flags & 1;
+ warn_pointer_arith = (flags >> 1) & 1;
+ warn_traditional = (flags >> 2) & 1;
+ flag_iso = (flags >> 3) & 1;
+}
+
+/* Possibly kinds of declarator to parse. */
+typedef enum c_dtr_syn {
+ /* A normal declarator with an identifier. */
+ C_DTR_NORMAL,
+ /* An abstract declarator (maybe empty). */
+ C_DTR_ABSTRACT,
+ /* A parameter declarator: may be either, but after a type name does
+ not redeclare a typedef name as an identifier if it can
+ alternatively be interpreted as a typedef name; see DR#009,
+ applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
+ following DR#249. For example, given a typedef T, "int T" and
+ "int *T" are valid parameter declarations redeclaring T, while
+ "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
+ abstract declarators rather than involving redundant parentheses;
+ the same applies with attributes inside the parentheses before
+ "T". */
+ C_DTR_PARM
+} c_dtr_syn;
+
+static void c_parser_external_declaration (c_parser *);
+static void c_parser_asm_definition (c_parser *);
+static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool);
+static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
+ bool);
+static struct c_typespec c_parser_enum_specifier (c_parser *);
+static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
+static tree c_parser_struct_declaration (c_parser *);
+static struct c_typespec c_parser_typeof_specifier (c_parser *);
+static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
+ bool *);
+static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
+ c_dtr_syn, bool *);
+static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
+ bool,
+ struct c_declarator *);
+static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
+static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree);
+static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
+static tree c_parser_simple_asm_expr (c_parser *);
+static tree c_parser_attributes (c_parser *);
+static struct c_type_name *c_parser_type_name (c_parser *);
+static struct c_expr c_parser_initializer (c_parser *);
+static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
+static void c_parser_initelt (c_parser *);
+static void c_parser_initval (c_parser *, struct c_expr *);
+static tree c_parser_compound_statement (c_parser *);
+static void c_parser_compound_statement_nostart (c_parser *);
+static void c_parser_label (c_parser *);
+static void c_parser_statement (c_parser *);
+static void c_parser_statement_after_labels (c_parser *);
+static void c_parser_if_statement (c_parser *);
+static void c_parser_switch_statement (c_parser *);
+static void c_parser_while_statement (c_parser *);
+static void c_parser_do_statement (c_parser *);
+static void c_parser_for_statement (c_parser *);
+static tree c_parser_asm_statement (c_parser *);
+static tree c_parser_asm_operands (c_parser *);
+static tree c_parser_asm_clobbers (c_parser *);
+static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
+static struct c_expr c_parser_conditional_expression (c_parser *,
+ struct c_expr *);
+static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_unary_expression (c_parser *);
+static struct c_expr c_parser_sizeof_expression (c_parser *);
+static struct c_expr c_parser_alignof_expression (c_parser *);
+static struct c_expr c_parser_postfix_expression (c_parser *);
+static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
+ struct c_type_name *);
+static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+ struct c_expr);
+static struct c_expr c_parser_expression (c_parser *);
+static tree c_parser_expr_list (c_parser *);
+
+/* These Objective-C parser functions are only ever called when
+ compiling Objective-C. */
+static void c_parser_objc_class_definition (c_parser *);
+static void c_parser_objc_class_instance_variables (c_parser *);
+static void c_parser_objc_class_declaration (c_parser *);
+static void c_parser_objc_alias_declaration (c_parser *);
+static void c_parser_objc_protocol_definition (c_parser *);
+static enum tree_code c_parser_objc_method_type (c_parser *);
+static void c_parser_objc_method_definition (c_parser *);
+static void c_parser_objc_methodprotolist (c_parser *);
+static void c_parser_objc_methodproto (c_parser *);
+static tree c_parser_objc_method_decl (c_parser *);
+static tree c_parser_objc_type_name (c_parser *);
+static tree c_parser_objc_protocol_refs (c_parser *);
+static void c_parser_objc_try_catch_statement (c_parser *);
+static void c_parser_objc_synchronized_statement (c_parser *);
+static tree c_parser_objc_selector (c_parser *);
+static tree c_parser_objc_selector_arg (c_parser *);
+static tree c_parser_objc_receiver (c_parser *);
+static tree c_parser_objc_message_args (c_parser *);
+static tree c_parser_objc_keywordexpr (c_parser *);
+
+/* Parse a translation unit (C90 6.7, C99 6.9).
+
+ translation-unit:
+ external-declarations
+
+ external-declarations:
+ external-declaration
+ external-declarations external-declaration
+
+ GNU extensions:
+
+ translation-unit:
+ empty
+*/
+
+static void
+c_parser_translation_unit (c_parser *parser)
+{
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ if (pedantic)
+ pedwarn ("ISO C forbids an empty source file");
+ }
+ else
+ {
+ void *obstack_position = obstack_alloc (&parser_obstack, 0);
+ do
+ {
+ ggc_collect ();
+ c_parser_external_declaration (parser);
+ obstack_free (&parser_obstack, obstack_position);
+ }
+ while (c_parser_next_token_is_not (parser, CPP_EOF));
+ }
+}
+
+/* Parse an external declaration (C90 6.7, C99 6.9).
+
+ external-declaration:
+ function-definition
+ declaration
+
+ GNU extensions:
+
+ external-declaration:
+ asm-definition
+ ;
+ __extension__ external-declaration
+
+ Objective-C:
+
+ external-declaration:
+ objc-class-definition
+ objc-class-declaration
+ objc-alias-declaration
+ objc-protocol-definition
+ objc-method-definition
+ @end
+*/
+
+static void
+c_parser_external_declaration (c_parser *parser)
+{
+ int ext;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_EXTENSION:
+ ext = disable_extension_diagnostics ();
+ c_parser_consume_token (parser);
+ c_parser_external_declaration (parser);
+ restore_extension_diagnostics (ext);
+ break;
+ case RID_ASM:
+ c_parser_asm_definition (parser);
+ break;
+ case RID_AT_INTERFACE:
+ case RID_AT_IMPLEMENTATION:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_class_definition (parser);
+ break;
+ case RID_AT_CLASS:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_class_declaration (parser);
+ break;
+ case RID_AT_ALIAS:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_alias_declaration (parser);
+ break;
+ case RID_AT_PROTOCOL:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_protocol_definition (parser);
+ break;
+ case RID_AT_END:
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ objc_finish_implementation ();
+ break;
+ default:
+ goto decl_or_fndef;
+ }
+ break;
+ case CPP_SEMICOLON:
+ if (pedantic)
+ pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+ c_parser_consume_token (parser);
+ break;
+ case CPP_PLUS:
+ case CPP_MINUS:
+ if (c_dialect_objc ())
+ {
+ c_parser_objc_method_definition (parser);
+ break;
+ }
+ /* Else fall through, and yield a syntax error trying to parse
+ as a declaration or function definition. */
+ default:
+ decl_or_fndef:
+ /* A declaration or a function definition. We can only tell
+ which after parsing the declaration specifiers, if any, and
+ the first declarator. */
+ c_parser_declaration_or_fndef (parser, true, true, false, true);
+ break;
+ }
+}
+
+/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
+ 6.7, 6.9.1). If FNDEF_OK is true, a function definition is
+ accepted; otherwise (old-style parameter declarations) only other
+ declarations are accepted. If NESTED is true, we are inside a
+ function or parsing old-style parameter declarations; any functions
+ encountered are nested functions and declaration specifiers are
+ required; otherwise we are at top level and functions are normal
+ functions and declaration specifiers may be optional. If EMPTY_OK
+ is true, empty declarations are OK (subject to all other
+ constraints); otherwise (old-style parameter declarations) they are
+ diagnosed. If START_ATTR_OK is true, the declaration specifiers
+ may start with attributes; otherwise they may not.
+
+ declaration:
+ declaration-specifiers init-declarator-list[opt] ;
+
+ function-definition:
+ declaration-specifiers[opt] declarator declaration-list[opt]
+ compound-statement
+
+ declaration-list:
+ declaration
+ declaration-list declaration
+
+ init-declarator-list:
+ init-declarator
+ init-declarator-list , init-declarator
+
+ init-declarator:
+ declarator simple-asm-expr[opt] attributes[opt]
+ declarator simple-asm-expr[opt] attributes[opt] = initializer
+
+ GNU extensions:
+
+ nested-function-definition:
+ declaration-specifiers declarator declaration-list[opt]
+ compound-statement
+
+ The simple-asm-expr and attributes are GNU extensions.
+
+ This function does not handle __extension__; that is handled in its
+ callers. ??? Following the old parser, __extension__ may start
+ external declarations, declarations in functions and declarations
+ at the start of "for" loops, but not old-style parameter
+ declarations.
+
+ C99 requires declaration specifiers in a function definition; the
+ absence is diagnosed through the diagnosis of implicit int. In GNU
+ C we also allow but diagnose declarations without declaration
+ specifiers, but only at top level (elsewhere they conflict with
+ other syntax). */
+
+static void
+c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
+ bool nested, bool start_attr_ok)
+{
+ struct c_declspecs *specs;
+ tree prefix_attrs;
+ tree all_prefix_attrs;
+ bool diagnosed_no_specs = false;
+ specs = build_null_declspecs ();
+ c_parser_declspecs (parser, specs, true, true, start_attr_ok);
+ if (parser->error)
+ {
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ if (nested && !specs->declspecs_seen_p)
+ {
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ finish_declspecs (specs);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ if (empty_ok)
+ shadow_tag (specs);
+ else
+ {
+ shadow_tag_warned (specs, 1);
+ pedwarn ("empty declaration");
+ }
+ c_parser_consume_token (parser);
+ return;
+ }
+ pending_xref_error ();
+ prefix_attrs = specs->attrs;
+ all_prefix_attrs = prefix_attrs;
+ specs->attrs = NULL_TREE;
+ while (true)
+ {
+ struct c_declarator *declarator;
+ bool dummy = false;
+ tree fnbody;
+ /* Declaring either one or more declarators (in which case we
+ should diagnose if there were no declaration specifiers) or a
+ function definition (in which case the diagnostic for
+ implicit int suffices). */
+ declarator = c_parser_declarator (parser, specs->type_seen_p,
+ C_DTR_NORMAL, &dummy);
+ if (declarator == NULL)
+ {
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ if (c_parser_next_token_is (parser, CPP_EQ)
+ || c_parser_next_token_is (parser, CPP_COMMA)
+ || c_parser_next_token_is (parser, CPP_SEMICOLON)
+ || c_parser_next_token_is_keyword (parser, RID_ASM)
+ || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ {
+ tree asm_name = NULL_TREE;
+ tree postfix_attrs = NULL_TREE;
+ if (!diagnosed_no_specs && !specs->declspecs_seen_p)
+ {
+ diagnosed_no_specs = true;
+ pedwarn ("data definition has no type or storage class");
+ }
+ /* Having seen a data definition, there cannot now be a
+ function definition. */
+ fndef_ok = false;
+ if (c_parser_next_token_is_keyword (parser, RID_ASM))
+ asm_name = c_parser_simple_asm_expr (parser);
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ postfix_attrs = c_parser_attributes (parser);
+ if (c_parser_next_token_is (parser, CPP_EQ))
+ {
+ tree d;
+ struct c_expr init;
+ c_parser_consume_token (parser);
+ /* The declaration of the variable is in effect while
+ its initializer is parsed. */
+ d = start_decl (declarator, specs, true,
+ chainon (postfix_attrs, all_prefix_attrs));
+ if (!d)
+ d = error_mark_node;
+ start_init (d, asm_name, global_bindings_p ());
+ init = c_parser_initializer (parser);
+ finish_init ();
+ if (d != error_mark_node)
+ {
+ maybe_warn_string_init (TREE_TYPE (d), init);
+ finish_decl (d, init.value, asm_name);
+ }
+ }
+ else
+ {
+ tree d = start_decl (declarator, specs, false,
+ chainon (postfix_attrs,
+ all_prefix_attrs));
+ if (d)
+ finish_decl (d, NULL_TREE, asm_name);
+ }
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ all_prefix_attrs = chainon (c_parser_attributes (parser),
+ prefix_attrs);
+ else
+ all_prefix_attrs = prefix_attrs;
+ continue;
+ }
+ else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_parser_consume_token (parser);
+ return;
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<,%> or %<;%>");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ }
+ else if (!fndef_ok)
+ {
+ c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
+ "%<asm%> or %<__attribute__%>");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ /* Function definition (nested or otherwise). */
+ if (nested)
+ {
+ if (pedantic)
+ pedwarn ("ISO C forbids nested functions");
+ push_function_context ();
+ }
+ if (!start_function (specs, declarator, all_prefix_attrs))
+ {
+ /* This can appear in many cases looking nothing like a
+ function definition, so we don't give a more specific
+ error suggesting there was one. */
+ c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
+ "or %<__attribute__%>");
+ if (nested)
+ pop_function_context ();
+ break;
+ }
+ /* Parse old-style parameter declarations. ??? Attributes are
+ not allowed to start declaration specifiers here because of a
+ syntax conflict between a function declaration with attribute
+ suffix and a function definition with an attribute prefix on
+ first old-style parameter declaration. Following the old
+ parser, they are not accepted on subsequent old-style
+ parameter declarations either. However, there is no
+ ambiguity after the first declaration, nor indeed on the
+ first as long as we don't allow postfix attributes after a
+ declarator with a nonempty identifier list in a definition;
+ and postfix attributes have never been accepted here in
+ function definitions either. */
+ while (c_parser_next_token_is_not (parser, CPP_EOF)
+ && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
+ c_parser_declaration_or_fndef (parser, false, false, true, false);
+ DECL_SOURCE_LOCATION (current_function_decl)
+ = c_parser_peek_token (parser)->location;
+ store_parm_decls ();
+ fnbody = c_parser_compound_statement (parser);
+ if (nested)
+ {
+ tree decl = current_function_decl;
+ add_stmt (fnbody);
+ finish_function ();
+ pop_function_context ();
+ add_stmt (build_stmt (DECL_EXPR, decl));
+ }
+ else
+ {
+ add_stmt (fnbody);
+ finish_function ();
+ }
+ break;
+ }
+}
+
+/* Parse an asm-definition (asm() outside a function body). This is a
+ GNU extension.
+
+ asm-definition:
+ simple-asm-expr ;
+*/
+
+static void
+c_parser_asm_definition (c_parser *parser)
+{
+ tree asm_str = c_parser_simple_asm_expr (parser);
+ /* ??? This only works sensibly in the presence of
+ -fno-unit-at-a-time; file-scope asms really need to be passed to
+ cgraph which needs to preserve the order of functions and
+ file-scope asms. */
+ if (asm_str)
+ assemble_asm (asm_str);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
+ 6.7), adding them to SPECS (which may already include some).
+ Storage class specifiers are accepted iff SCSPEC_OK; type
+ specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
+ the start iff START_ATTR_OK.
+
+ declaration-specifiers:
+ storage-class-specifier declaration-specifiers[opt]
+ type-specifier declaration-specifiers[opt]
+ type-qualifier declaration-specifiers[opt]
+ function-specifier declaration-specifiers[opt]
+
+ Function specifiers (inline) are from C99, and are currently
+ handled as storage class specifiers, as is __thread.
+
+ C90 6.5.1, C99 6.7.1:
+ storage-class-specifier:
+ typedef
+ extern
+ static
+ auto
+ register
+
+ C99 6.7.4:
+ function-specifier:
+ inline
+
+ C90 6.5.2, C99 6.7.2:
+ type-specifier:
+ void
+ char
+ short
+ int
+ long
+ float
+ double
+ signed
+ unsigned
+ _Bool
+ _Complex
+ [_Imaginary removed in C99 TC2]
+ struct-or-union-specifier
+ enum-specifier
+ typedef-name
+
+ (_Bool and _Complex are new in C99.)
+
+ C90 6.5.3, C99 6.7.3:
+
+ type-qualifier:
+ const
+ restrict
+ volatile
+
+ (restrict is new in C99.)
+
+ GNU extensions:
+
+ declaration-specifiers:
+ attributes declaration-specifiers[opt]
+
+ storage-class-specifier:
+ __thread
+
+ type-specifier:
+ typeof-specifier
+
+ Objective-C:
+
+ type-specifier:
+ class-name objc-protocol-refs[opt]
+ typedef-name objc-protocol-refs
+ objc-protocol-refs
+*/
+
+static void
+c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
+ bool scspec_ok, bool typespec_ok, bool start_attr_ok)
+{
+ bool attrs_ok = start_attr_ok;
+ bool seen_type = specs->type_seen_p;
+ while (c_parser_next_token_is (parser, CPP_NAME)
+ || c_parser_next_token_is (parser, CPP_KEYWORD)
+ || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
+ {
+ struct c_typespec t;
+ tree attrs;
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ tree value = c_parser_peek_token (parser)->value;
+ c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+ /* This finishes the specifiers unless a type name is OK, it
+ is declared as a type name and a type name hasn't yet
+ been seen. */
+ if (!typespec_ok || seen_type
+ || (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME))
+ break;
+ c_parser_consume_token (parser);
+ seen_type = true;
+ attrs_ok = true;
+ if (kind == C_ID_TYPENAME
+ && (!c_dialect_objc ()
+ || c_parser_next_token_is_not (parser, CPP_LESS)))
+ {
+ t.kind = ctsk_typedef;
+ /* For a typedef name, record the meaning, not the name.
+ In case of 'foo foo, bar;'. */
+ t.spec = lookup_name (value);
+ }
+ else
+ {
+ tree proto = NULL_TREE;
+ gcc_assert (c_dialect_objc ());
+ t.kind = ctsk_objc;
+ if (c_parser_next_token_is (parser, CPP_LESS))
+ proto = c_parser_objc_protocol_refs (parser);
+ t.spec = objc_get_protocol_qualified_type (value, proto);
+ }
+ declspecs_add_type (specs, t);
+ continue;
+ }
+ if (c_parser_next_token_is (parser, CPP_LESS))
+ {
+ /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
+ nisse@lysator.liu.se. */
+ tree proto;
+ gcc_assert (c_dialect_objc ());
+ if (!typespec_ok || seen_type)
+ break;
+ proto = c_parser_objc_protocol_refs (parser);
+ t.kind = ctsk_objc;
+ t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
+ declspecs_add_type (specs, t);
+ continue;
+ }
+ gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_STATIC:
+ case RID_EXTERN:
+ case RID_REGISTER:
+ case RID_TYPEDEF:
+ case RID_INLINE:
+ case RID_AUTO:
+ case RID_THREAD:
+ if (!scspec_ok)
+ goto out;
+ attrs_ok = true;
+ /* TODO: Distinguish between function specifiers (inline)
+ and storage class specifiers, either here or in
+ declspecs_add_scspec. */
+ declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ break;
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ case RID_COMPLEX:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_BOOL:
+ if (!typespec_ok)
+ goto out;
+ attrs_ok = true;
+ seen_type = true;
+ OBJC_NEED_RAW_IDENTIFIER (1);
+ t.kind = ctsk_resword;
+ t.spec = c_parser_peek_token (parser)->value;
+ declspecs_add_type (specs, t);
+ c_parser_consume_token (parser);
+ break;
+ case RID_ENUM:
+ if (!typespec_ok)
+ goto out;
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_enum_specifier (parser);
+ declspecs_add_type (specs, t);
+ break;
+ case RID_STRUCT:
+ case RID_UNION:
+ if (!typespec_ok)
+ goto out;
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_struct_or_union_specifier (parser);
+ declspecs_add_type (specs, t);
+ break;
+ case RID_TYPEOF:
+ /* ??? The old parser rejected typeof after other type
+ specifiers, but is a syntax error the best way of
+ handling this? */
+ if (!typespec_ok || seen_type)
+ goto out;
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_typeof_specifier (parser);
+ declspecs_add_type (specs, t);
+ break;
+ case RID_CONST:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ attrs_ok = true;
+ declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ break;
+ case RID_ATTRIBUTE:
+ if (!attrs_ok)
+ goto out;
+ attrs = c_parser_attributes (parser);
+ declspecs_add_attrs (specs, attrs);
+ break;
+ default:
+ goto out;
+ }
+ }
+ out: ;
+}
+
+/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
+
+ enum-specifier:
+ enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
+ enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
+ enum attributes[opt] identifier
+
+ The form with trailing comma is new in C99. The forms with
+ attributes are GNU extensions. In GNU C, we accept any expression
+ without commas in the syntax (assignment expressions, not just
+ conditional expressions); assignment expressions will be diagnosed
+ as non-constant.
+
+ enumerator-list:
+ enumerator
+ enumerator-list , enumerator
+
+ enumerator:
+ enumeration-constant
+ enumeration-constant = constant-expression
+*/
+
+static struct c_typespec
+c_parser_enum_specifier (c_parser *parser)
+{
+ struct c_typespec ret;
+ tree attrs;
+ tree ident = NULL_TREE;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+ c_parser_consume_token (parser);
+ attrs = c_parser_attributes (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ ident = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ {
+ /* Parse an enum definition. */
+ tree type = start_enum (ident);
+ tree postfix_attrs;
+ /* We chain the enumerators in reverse order, then put them in
+ forward order at the end. */
+ tree values = NULL_TREE;
+ c_parser_consume_token (parser);
+ while (true)
+ {
+ tree enum_id;
+ tree enum_value;
+ tree enum_decl;
+ bool seen_comma;
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ values = error_mark_node;
+ break;
+ }
+ enum_id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_EQ))
+ {
+ c_parser_consume_token (parser);
+ enum_value = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ else
+ enum_value = NULL_TREE;
+ enum_decl = build_enumerator (enum_id, enum_value);
+ TREE_CHAIN (enum_decl) = values;
+ values = enum_decl;
+ seen_comma = false;
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ seen_comma = true;
+ c_parser_consume_token (parser);
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ if (seen_comma && pedantic && !flag_isoc99)
+ pedwarn ("comma at end of enumerator list");
+ c_parser_consume_token (parser);
+ break;
+ }
+ if (!seen_comma)
+ {
+ c_parser_error (parser, "expected %<,%> or %<}%>");
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ values = error_mark_node;
+ break;
+ }
+ }
+ postfix_attrs = c_parser_attributes (parser);
+ ret.spec = finish_enum (type, nreverse (values),
+ chainon (attrs, postfix_attrs));
+ ret.kind = ctsk_tagdef;
+ return ret;
+ }
+ else if (!ident)
+ {
+ c_parser_error (parser, "expected %<{%>");
+ ret.spec = error_mark_node;
+ ret.kind = ctsk_tagref;
+ return ret;
+ }
+ ret = parser_xref_tag (ENUMERAL_TYPE, ident);
+ /* In ISO C, enumerated types can be referred to only if already
+ defined. */
+ if (pedantic && !COMPLETE_TYPE_P (ret.spec))
+ pedwarn ("ISO C forbids forward references to %<enum%> types");
+ return ret;
+}
+
+/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
+
+ struct-or-union-specifier:
+ struct-or-union attributes[opt] identifier[opt]
+ { struct-contents } attributes[opt]
+ struct-or-union attributes[opt] identifier
+
+ struct-contents:
+ struct-declaration-list
+
+ struct-declaration-list:
+ struct-declaration ;
+ struct-declaration-list struct-declaration ;
+
+ GNU extensions:
+
+ struct-contents:
+ empty
+ struct-declaration
+ struct-declaration-list struct-declaration
+
+ struct-declaration-list:
+ struct-declaration-list ;
+ ;
+
+ (Note that in the syntax here, unlike that in ISO C, the semicolons
+ are included here rather than in struct-declaration, in order to
+ describe the syntax with extra semicolons and missing semicolon at
+ end.)
+
+ Objective-C:
+
+ struct-declaration-list:
+ @defs ( class-name )
+
+ (Note this does not include a trailing semicolon, but can be
+ followed by further declarations, and gets a pedwarn-if-pedantic
+ when followed by a semicolon.) */
+
+static struct c_typespec
+c_parser_struct_or_union_specifier (c_parser *parser)
+{
+ struct c_typespec ret;
+ tree attrs;
+ tree ident = NULL_TREE;
+ enum tree_code code;
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_STRUCT:
+ code = RECORD_TYPE;
+ break;
+ case RID_UNION:
+ code = UNION_TYPE;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ c_parser_consume_token (parser);
+ attrs = c_parser_attributes (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ ident = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ {
+ /* Parse a struct or union definition. Start the scope of the
+ tag before parsing components. */
+ tree type = start_struct (code, ident);
+ tree postfix_attrs;
+ /* We chain the components in reverse order, then put them in
+ forward order at the end. Each struct-declaration may
+ declare multiple components (comma-separated), so we must use
+ chainon to join them, although when parsing each
+ struct-declaration we can use TREE_CHAIN directly.
+
+ 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. */
+ tree contents = NULL_TREE;
+ c_parser_consume_token (parser);
+ /* Handle the Objective-C @defs construct,
+ e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
+ if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
+ {
+ tree name;
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ goto end_at_defs;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
+ {
+ name = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ c_parser_error (parser, "expected class name");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ goto end_at_defs;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ contents = nreverse (objc_get_class_ivars (name));
+ }
+ end_at_defs:
+ /* Parse the struct-declarations and semicolons. Problems with
+ semicolons are diagnosed here; empty structures are diagnosed
+ elsewhere. */
+ while (true)
+ {
+ tree decls;
+ /* Parse any stray semicolon. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ if (pedantic)
+ pedwarn ("extra semicolon in struct or union specified");
+ c_parser_consume_token (parser);
+ continue;
+ }
+ /* Stop if at the end of the struct or union contents. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Parse some comma-separated declarations, but not the
+ trailing semicolon if any. */
+ decls = c_parser_struct_declaration (parser);
+ contents = chainon (decls, contents);
+ /* If no semicolon follows, either we have a parse error or
+ are at the end of the struct or union and should
+ pedwarn. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ c_parser_consume_token (parser);
+ else
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ pedwarn ("no semicolon at end of struct or union");
+ else
+ {
+ c_parser_error (parser, "expected %<;%>");
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ break;
+ }
+ }
+ }
+ postfix_attrs = c_parser_attributes (parser);
+ ret.spec = finish_struct (type, nreverse (contents),
+ chainon (attrs, postfix_attrs));
+ ret.kind = ctsk_tagdef;
+ return ret;
+ }
+ else if (!ident)
+ {
+ c_parser_error (parser, "expected %<{%>");
+ ret.spec = error_mark_node;
+ ret.kind = ctsk_tagref;
+ }
+ ret = parser_xref_tag (code, ident);
+ return ret;
+}
+
+/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
+ the trailing semicolon.
+
+ struct-declaration:
+ specifier-qualifier-list struct-declarator-list
+
+ specifier-qualifier-list:
+ type-specifier specifier-qualifier-list[opt]
+ type-qualifier specifier-qualifier-list[opt]
+ attributes specifier-qualifier-list[opt]
+
+ struct-declarator-list:
+ struct-declarator
+ struct-declarator-list , attributes[opt] struct-declarator
+
+ struct-declarator:
+ declarator attributes[opt]
+ declarator[opt] : constant-expression attributes[opt]
+
+ GNU extensions:
+
+ struct-declaration:
+ __extension__ struct-declaration
+ specifier-qualifier-list
+
+ Unlike the ISO C syntax, semicolons are handled elsewhere. The use
+ of attributes where shown is a GNU extension. In GNU C, we accept
+ any expression without commas in the syntax (assignment
+ expressions, not just conditional expressions); assignment
+ expressions will be diagnosed as non-constant. */
+
+static tree
+c_parser_struct_declaration (c_parser *parser)
+{
+ struct c_declspecs *specs;
+ tree prefix_attrs;
+ tree all_prefix_attrs;
+ tree decls;
+ if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+ {
+ int ext;
+ tree decl;
+ ext = disable_extension_diagnostics ();
+ c_parser_consume_token (parser);
+ decl = c_parser_struct_declaration (parser);
+ restore_extension_diagnostics (ext);
+ return decl;
+ }
+ specs = build_null_declspecs ();
+ c_parser_declspecs (parser, specs, false, true, true);
+ if (parser->error)
+ return error_mark_node;
+ if (!specs->declspecs_seen_p)
+ {
+ c_parser_error (parser, "expected specifier-qualifier-list");
+ return NULL_TREE;
+ }
+ finish_declspecs (specs);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree ret;
+ if (!specs->type_seen_p)
+ {
+ if (pedantic)
+ pedwarn ("ISO C forbids member declarations with no members");
+ shadow_tag_warned (specs, pedantic);
+ ret = NULL_TREE;
+ }
+ else
+ {
+ /* Support for unnamed structs or unions as members of
+ structs or unions (which is [a] useful and [b] supports
+ MS P-SDK). */
+ ret = grokfield (build_id_declarator (NULL_TREE), specs, NULL_TREE);
+ }
+ return ret;
+ }
+ pending_xref_error ();
+ prefix_attrs = specs->attrs;
+ all_prefix_attrs = prefix_attrs;
+ specs->attrs = NULL_TREE;
+ decls = NULL_TREE;
+ while (true)
+ {
+ /* Declaring one or more declarators or un-named bit-fields. */
+ struct c_declarator *declarator;
+ bool dummy = false;
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ declarator = build_id_declarator (NULL_TREE);
+ else
+ declarator = c_parser_declarator (parser, specs->type_seen_p,
+ C_DTR_NORMAL, &dummy);
+ if (declarator == NULL)
+ {
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ break;
+ }
+ if (c_parser_next_token_is (parser, CPP_COLON)
+ || c_parser_next_token_is (parser, CPP_COMMA)
+ || c_parser_next_token_is (parser, CPP_SEMICOLON)
+ || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
+ || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ {
+ tree postfix_attrs = NULL_TREE;
+ tree width = NULL_TREE;
+ tree d;
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ width = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ postfix_attrs = c_parser_attributes (parser);
+ d = grokfield (declarator, specs, width);
+ decl_attributes (&d, chainon (postfix_attrs,
+ all_prefix_attrs), 0);
+ TREE_CHAIN (d) = decls;
+ decls = d;
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ all_prefix_attrs = chainon (c_parser_attributes (parser),
+ prefix_attrs);
+ else
+ all_prefix_attrs = prefix_attrs;
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+ || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ /* Semicolon consumed in caller. */
+ break;
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
+ break;
+ }
+ }
+ else
+ {
+ c_parser_error (parser,
+ "expected %<:%>, %<,%>, %<;%>, %<}%> or "
+ "%<__attribute__%>");
+ break;
+ }
+ }
+ return decls;
+}
+
+/* Parse a typeof specifier (a GNU extension).
+
+ typeof-specifier:
+ typeof ( expression )
+ typeof ( type-name )
+*/
+
+static struct c_typespec
+c_parser_typeof_specifier (c_parser *parser)
+{
+ struct c_typespec ret;
+ ret.kind = ctsk_typeof;
+ ret.spec = error_mark_node;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
+ c_parser_consume_token (parser);
+ skip_evaluation++;
+ in_typeof++;
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ skip_evaluation--;
+ in_typeof--;
+ return ret;
+ }
+ if (c_parser_next_token_starts_typename (parser))
+ {
+ struct c_type_name *type = c_parser_type_name (parser);
+ skip_evaluation--;
+ in_typeof--;
+ if (type != NULL)
+ {
+ ret.spec = groktypename (type);
+ pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
+ }
+ }
+ else
+ {
+ struct c_expr expr = c_parser_expression (parser);
+ skip_evaluation--;
+ in_typeof--;
+ if (TREE_CODE (expr.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+ error ("%<typeof%> applied to a bit-field");
+ ret.spec = TREE_TYPE (expr.value);
+ pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return ret;
+}
+
+/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
+ 6.5.5, C99 6.7.5, 6.7.6). If TYPE_SEEN_P then a typedef name may
+ be redeclared; otherwise it may not. KIND indicates which kind of
+ declarator is wanted. Returns a valid declarator except in the
+ case of a syntax error in which case NULL is returned. *SEEN_ID is
+ set to true if an identifier being declared is seen; this is used
+ to diagnose bad forms of abstract array declarators and to
+ determine whether an identifier list is syntactically permitted.
+
+ declarator:
+ pointer[opt] direct-declarator
+
+ direct-declarator:
+ identifier
+ ( attributes[opt] declarator )
+ direct-declarator array-declarator
+ direct-declarator ( parameter-type-list )
+ direct-declarator ( identifier-list[opt] )
+
+ pointer:
+ * type-qualifier-list[opt]
+ * type-qualifier-list[opt] pointer
+
+ type-qualifier-list:
+ type-qualifier
+ attributes
+ type-qualifier-list type-qualifier
+ type-qualifier-list attributes
+
+ parameter-type-list:
+ parameter-list
+ parameter-list , ...
+
+ parameter-list:
+ parameter-declaration
+ parameter-list , parameter-declaration
+
+ parameter-declaration:
+ declaration-specifiers declarator attributes[opt]
+ declaration-specifiers abstract-declarator[opt] attributes[opt]
+
+ identifier-list:
+ identifier
+ identifier-list , identifier
+
+ abstract-declarator:
+ pointer
+ pointer[opt] direct-abstract-declarator
+
+ direct-abstract-declarator:
+ ( attributes[opt] abstract-declarator )
+ direct-abstract-declarator[opt] array-declarator
+ direct-abstract-declarator[opt] ( parameter-type-list[opt] )
+
+ GNU extensions:
+
+ direct-declarator:
+ direct-declarator ( parameter-forward-declarations
+ parameter-type-list[opt] )
+
+ direct-abstract-declarator:
+ direct-abstract-declarator[opt] ( parameter-forward-declarations
+ parameter-type-list[opt] )
+
+ parameter-forward-declarations:
+ parameter-list ;
+ parameter-forward-declarations parameter-list ;
+
+ The uses of attributes shown above are GNU extensions.
+
+ Some forms of array declarator are not included in C99 in the
+ syntax for abstract declarators; these are disallowed elsewhere.
+ This may be a defect (DR#289).
+
+ This function also accepts an omitted abstract declarator as being
+ an abstract declarator, although not part of the formal syntax. */
+
+static struct c_declarator *
+c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+ bool *seen_id)
+{
+ /* Parse any initial pointer part. */
+ if (c_parser_next_token_is (parser, CPP_MULT))
+ {
+ struct c_declspecs *quals_attrs = build_null_declspecs ();
+ struct c_declarator *inner;
+ c_parser_consume_token (parser);
+ c_parser_declspecs (parser, quals_attrs, false, false, true);
+ inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
+ if (inner == NULL)
+ return NULL;
+ else
+ return make_pointer_declarator (quals_attrs, inner);
+ }
+ /* Now we have a direct declarator, direct abstract declarator or
+ nothing (which counts as a direct abstract declarator here). */
+ return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
+}
+
+/* Parse a direct declarator or direct abstract declarator; arguments
+ as c_parser_declarator. */
+
+static struct c_declarator *
+c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+ bool *seen_id)
+{
+ /* The direct declarator must start with an identifier (possibly
+ omitted) or a parenthesized declarator (possibly abstract). In
+ an ordinary declarator, initial parentheses must start a
+ parenthesized declarator. In an abstract declarator or parameter
+ declarator, they could start a parenthesized declarator or a
+ parameter list. To tell which, the open parenthesis and any
+ following attributes must be read. If a declaration specifier
+ follows, then it is a parameter list; if the specifier is a
+ typedef name, there might be an ambiguity about redeclaring it,
+ which is resolved in the direction of treating it as a typedef
+ name. If a close parenthesis follows, it is also an empty
+ parameter list, as the syntax does not permit empty abstract
+ declarators. Otherwise, it is a parenthesised declarator (in
+ which case the analysis may be repeated inside it, recursively).
+
+ ??? There is an ambiguity in a parameter declaration "int
+ (__attribute__((foo)) x)", where x is not a typedef name: it
+ could be an abstract declarator for a function, or declare x with
+ parentheses. The proper resolution of this ambiguity needs
+ documenting. At present we follow an accident of the old
+ parser's implementation, whereby the first parameter must have
+ some declaration specifiers other than just attributes. Thus as
+ a parameter declaration it is treated as a parenthesised
+ parameter named x, and as an abstract declarator it is
+ rejected.
+
+ ??? Also following the old parser, attributes inside an empty
+ parameter list are ignored, making it a list not yielding a
+ prototype, rather than giving an error or making it have one
+ parameter with implicit type int.
+
+ ??? Also following the old parser, typedef names may be
+ redeclared in declarators, but not Objective-C class names. */
+
+ if (kind != C_DTR_ABSTRACT
+ && c_parser_next_token_is (parser, CPP_NAME)
+ && ((type_seen_p
+ && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME)
+ || c_parser_peek_token (parser)->id_kind == C_ID_ID))
+ {
+ struct c_declarator *inner
+ = build_id_declarator (c_parser_peek_token (parser)->value);
+ *seen_id = true;
+ c_parser_consume_token (parser);
+ return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+ }
+
+ if (kind != C_DTR_NORMAL
+ && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ {
+ struct c_declarator *inner = build_id_declarator (NULL_TREE);
+ return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+ }
+
+ /* Either we are at the end of an abstract declarator, or we have
+ parentheses. */
+
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree attrs;
+ struct c_declarator *inner;
+ c_parser_consume_token (parser);
+ attrs = c_parser_attributes (parser);
+ if (kind != C_DTR_NORMAL
+ && (c_parser_next_token_starts_declspecs (parser)
+ || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
+ {
+ struct c_arg_info *args
+ = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
+ attrs);
+ if (args == NULL)
+ return NULL;
+ else
+ {
+ inner
+ = build_function_declarator (args,
+ build_id_declarator (NULL_TREE));
+ return c_parser_direct_declarator_inner (parser, *seen_id,
+ inner);
+ }
+ }
+ /* A parenthesized declarator. */
+ inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
+ if (inner != NULL && attrs != NULL)
+ inner = build_attrs_declarator (attrs, inner);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_consume_token (parser);
+ if (inner == NULL)
+ return NULL;
+ else
+ return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+ }
+ else
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return NULL;
+ }
+ }
+ else
+ {
+ if (kind == C_DTR_NORMAL)
+ {
+ c_parser_error (parser, "expected identifier or %<(%>");
+ return NULL;
+ }
+ else
+ return build_id_declarator (NULL_TREE);
+ }
+}
+
+/* Parse part of a direct declarator or direct abstract declarator,
+ given that some (in INNER) has already been parsed; ID_PRESENT is
+ true if an identifier is present, false for an abstract
+ declarator. */
+
+static struct c_declarator *
+c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
+ struct c_declarator *inner)
+{
+ /* Parse a sequence of array declarators and parameter lists. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ {
+ struct c_declarator *declarator;
+ struct c_declspecs *quals_attrs = build_null_declspecs ();
+ bool static_seen;
+ bool star_seen;
+ tree dimen;
+ c_parser_consume_token (parser);
+ c_parser_declspecs (parser, quals_attrs, false, false, true);
+ static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
+ if (static_seen)
+ c_parser_consume_token (parser);
+ if (static_seen && !quals_attrs->declspecs_seen_p)
+ c_parser_declspecs (parser, quals_attrs, false, false, true);
+ if (!quals_attrs->declspecs_seen_p)
+ quals_attrs = NULL;
+ /* If "static" is present, there must be an array dimension.
+ Otherwise, there may be a dimension, "*", or no
+ dimension. */
+ if (static_seen)
+ {
+ star_seen = false;
+ dimen = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ else
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ {
+ dimen = NULL_TREE;
+ star_seen = false;
+ }
+ else if (c_parser_next_token_is (parser, CPP_MULT))
+ {
+ if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
+ {
+ dimen = NULL_TREE;
+ star_seen = true;
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ star_seen = false;
+ dimen = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ }
+ else
+ {
+ star_seen = false;
+ dimen = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ return NULL;
+ }
+ declarator = build_array_declarator (dimen, quals_attrs, static_seen,
+ star_seen);
+ inner = set_array_declarator_inner (declarator, inner, !id_present);
+ return c_parser_direct_declarator_inner (parser, id_present, inner);
+ }
+ else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree attrs;
+ struct c_arg_info *args;
+ c_parser_consume_token (parser);
+ attrs = c_parser_attributes (parser);
+ args = c_parser_parms_declarator (parser, id_present, attrs);
+ if (args == NULL)
+ return NULL;
+ else
+ {
+ inner = build_function_declarator (args, inner);
+ return c_parser_direct_declarator_inner (parser, id_present, inner);
+ }
+ }
+ return inner;
+}
+
+/* Parse a parameter list or identifier list, including the closing
+ parenthesis but not the opening one. ATTRS are the attributes at
+ the start of the list. ID_LIST_OK is true if an identifier list is
+ acceptable; such a list must not have attributes at the start. */
+
+static struct c_arg_info *
+c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
+{
+ push_scope ();
+ declare_parm_level ();
+ /* If the list starts with an identifier, it is an identifier list.
+ Otherwise, it is either a prototype list or an empty list. */
+ if (id_list_ok
+ && !attrs
+ && c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+ {
+ tree list = NULL_TREE;
+ while (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+ {
+ list = chainon (list, build_tree_list (NULL_TREE,
+ c_parser_peek_token (parser)->value));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_COMMA))
+ break;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = 0;
+ ret->tags = 0;
+ ret->types = list;
+ ret->others = 0;
+ c_parser_consume_token (parser);
+ pop_scope ();
+ return ret;
+ }
+ else
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ pop_scope ();
+ return NULL;
+ }
+ }
+ else
+ {
+ struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs);
+ pop_scope ();
+ return ret;
+ }
+}
+
+/* Parse a parameter list (possibly empty), including the closing
+ parenthesis but not the opening one. ATTRS are the attributes at
+ the start of the list. */
+
+static struct c_arg_info *
+c_parser_parms_list_declarator (c_parser *parser, tree attrs)
+{
+ bool good_parm = false;
+ /* ??? Following the old parser, forward parameter declarations may
+ use abstract declarators, and if no real parameter declarations
+ follow the forward declarations then this is not diagnosed. Also
+ note as above that attributes are ignored as the only contents of
+ the parentheses, or as the only contents after forward
+ declarations. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = 0;
+ ret->tags = 0;
+ ret->types = 0;
+ ret->others = 0;
+ c_parser_consume_token (parser);
+ return ret;
+ }
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+ {
+ struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = 0;
+ ret->tags = 0;
+ ret->others = 0;
+ /* Suppress -Wold-style-definition for this case. */
+ ret->types = error_mark_node;
+ error ("ISO C requires a named argument before %<...%>");
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_consume_token (parser);
+ return ret;
+ }
+ else
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return NULL;
+ }
+ }
+ /* Nonempty list of parameters, either terminated with semicolon
+ (forward declarations; recurse) or with close parenthesis (normal
+ function) or with ", ... )" (variadic function). */
+ while (true)
+ {
+ /* Parse a parameter. */
+ struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
+ attrs = NULL_TREE;
+ if (parm != NULL)
+ {
+ good_parm = true;
+ push_parm_decl (parm);
+ }
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree new_attrs;
+ c_parser_consume_token (parser);
+ new_attrs = c_parser_attributes (parser);
+ return c_parser_parms_list_declarator (parser, new_attrs);
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_consume_token (parser);
+ if (good_parm)
+ return get_parm_info (false);
+ else
+ {
+ struct c_arg_info *ret
+ = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = 0;
+ ret->tags = 0;
+ ret->types = 0;
+ ret->others = 0;
+ return ret;
+ }
+ }
+ if (!c_parser_require (parser, CPP_COMMA,
+ "expected %<;%>, %<,%> or %<)%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL;
+ }
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_consume_token (parser);
+ if (good_parm)
+ return get_parm_info (true);
+ else
+ {
+ struct c_arg_info *ret
+ = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = 0;
+ ret->tags = 0;
+ ret->types = 0;
+ ret->others = 0;
+ return ret;
+ }
+ }
+ else
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return NULL;
+ }
+ }
+ }
+}
+
+/* Parse a parameter declaration. ATTRS are the attributes at the
+ start of the declaration if it is the first parameter. */
+
+static struct c_parm *
+c_parser_parameter_declaration (c_parser *parser, tree attrs)
+{
+ struct c_declspecs *specs;
+ struct c_declarator *declarator;
+ tree prefix_attrs;
+ tree postfix_attrs = NULL_TREE;
+ bool dummy = false;
+ if (!c_parser_next_token_starts_declspecs (parser))
+ {
+ /* ??? In some Objective-C cases '...' isn't applicable so there
+ should be a different message. */
+ c_parser_error (parser,
+ "expected declaration specifiers or %<...%>");
+ c_parser_skip_to_end_of_parameter (parser);
+ return NULL;
+ }
+ specs = build_null_declspecs ();
+ if (attrs)
+ {
+ declspecs_add_attrs (specs, attrs);
+ attrs = NULL_TREE;
+ }
+ c_parser_declspecs (parser, specs, true, true, true);
+ finish_declspecs (specs);
+ pending_xref_error ();
+ prefix_attrs = specs->attrs;
+ specs->attrs = NULL_TREE;
+ declarator = c_parser_declarator (parser, specs->type_seen_p,
+ C_DTR_PARM, &dummy);
+ if (declarator == NULL)
+ {
+ c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+ return NULL;
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ postfix_attrs = c_parser_attributes (parser);
+ return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
+ declarator);
+}
+
+/* Parse a string literal in an asm expression. It should not be
+ translated, and wide string literals are an error although
+ permitted by the syntax. This is a GNU extension.
+
+ asm-string-literal:
+ string-literal
+
+ ??? At present, following the old parser, the caller needs to have
+ set c_lex_string_translate to 0. It would be better to follow the
+ C++ parser rather than using the c_lex_string_translate kludge. */
+
+static tree
+c_parser_asm_string_literal (c_parser *parser)
+{
+ tree str;
+ if (c_parser_next_token_is (parser, CPP_STRING))
+ {
+ str = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ else if (c_parser_next_token_is (parser, CPP_WSTRING))
+ {
+ error ("wide string literal in %<asm%>");
+ str = build_string (1, "");
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ c_parser_error (parser, "expected string literal");
+ str = NULL_TREE;
+ }
+ return str;
+}
+
+/* Parse a simple asm expression. This is used in restricted
+ contexts, where a full expression with inputs and outputs does not
+ make sense. This is a GNU extension.
+
+ simple-asm-expr:
+ asm ( asm-string-literal )
+*/
+
+static tree
+c_parser_simple_asm_expr (c_parser *parser)
+{
+ tree str;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
+ /* ??? Follow the C++ parser rather than using the
+ c_lex_string_translate kludge. */
+ c_lex_string_translate = 0;
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_lex_string_translate = 1;
+ return NULL_TREE;
+ }
+ str = c_parser_asm_string_literal (parser);
+ c_lex_string_translate = 1;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ return str;
+}
+
+/* Parse (possibly empty) attributes. This is a GNU extension.
+
+ attributes:
+ empty
+ attributes attribute
+
+ attribute:
+ __attribute__ ( ( attribute-list ) )
+
+ attribute-list:
+ attrib
+ attribute_list , attrib
+
+ attrib:
+ empty
+ any-word
+ any-word ( identifier )
+ any-word ( identifier , nonempty-expr-list )
+ any-word ( expr-list )
+
+ where the "identifier" must not be declared as a type, and
+ "any-word" may be any identifier (including one declared as a
+ type), a reserved word storage class specifier, type specifier or
+ type qualifier. ??? This still leaves out most reserved keywords
+ (following the old parser), shouldn't we include them, and why not
+ allow identifiers declared as types to start the arguments? */
+
+static tree
+c_parser_attributes (c_parser *parser)
+{
+ tree attrs = NULL_TREE;
+ while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ {
+ /* ??? Follow the C++ parser rather than using the
+ c_lex_string_translate kludge. */
+ c_lex_string_translate = 0;
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_lex_string_translate = 1;
+ return attrs;
+ }
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return attrs;
+ }
+ /* Parse the attribute list. */
+ while (c_parser_next_token_is (parser, CPP_COMMA)
+ || c_parser_next_token_is (parser, CPP_NAME)
+ || c_parser_next_token_is (parser, CPP_KEYWORD))
+ {
+ tree attr, attr_name, attr_args;
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ if (c_parser_next_token_is (parser, CPP_KEYWORD))
+ {
+ /* ??? See comment above about what keywords are
+ accepted here. */
+ bool ok;
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_STATIC:
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_CONST:
+ case RID_EXTERN:
+ case RID_REGISTER:
+ case RID_TYPEDEF:
+ case RID_SHORT:
+ case RID_INLINE:
+ case RID_VOLATILE:
+ case RID_SIGNED:
+ case RID_AUTO:
+ case RID_RESTRICT:
+ case RID_COMPLEX:
+ case RID_THREAD:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_BOOL:
+ ok = true;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ break;
+ }
+ attr_name = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ {
+ attr = build_tree_list (attr_name, NULL_TREE);
+ attrs = chainon (attrs, attr);
+ continue;
+ }
+ c_parser_consume_token (parser);
+ /* Parse the attribute contents. If they start with an
+ identifier which is followed by a comma or close
+ parenthesis, then the arguments start with that
+ identifier; otherwise they are an expression list. */
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_token (parser)->id_kind == C_ID_ID
+ && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
+ || (c_parser_peek_2nd_token (parser)->type
+ == CPP_CLOSE_PAREN)))
+ {
+ tree arg1 = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ attr_args = build_tree_list (NULL_TREE, arg1);
+ else
+ {
+ c_parser_consume_token (parser);
+ attr_args = tree_cons (NULL_TREE, arg1,
+ c_parser_expr_list (parser));
+ }
+ }
+ else
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ attr_args = NULL_TREE;
+ else
+ attr_args = c_parser_expr_list (parser);
+ }
+ attr = build_tree_list (attr_name, attr_args);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return attrs;
+ }
+ attrs = chainon (attrs, attr);
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return attrs;
+ }
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return attrs;
+ }
+ c_lex_string_translate = 1;
+ }
+ return attrs;
+}
+
+/* Parse a type name (C90 6.5.5, C99 6.7.6).
+
+ type-name:
+ specifier-qualifier-list abstract-declarator[opt]
+*/
+
+static struct c_type_name *
+c_parser_type_name (c_parser *parser)
+{
+ struct c_declspecs *specs = build_null_declspecs ();
+ struct c_declarator *declarator;
+ struct c_type_name *ret;
+ bool dummy = false;
+ c_parser_declspecs (parser, specs, false, true, true);
+ if (!specs->declspecs_seen_p)
+ {
+ c_parser_error (parser, "expected specifier-qualifier-list");
+ return NULL;
+ }
+ pending_xref_error ();
+ finish_declspecs (specs);
+ declarator = c_parser_declarator (parser, specs->type_seen_p,
+ C_DTR_ABSTRACT, &dummy);
+ if (declarator == NULL)
+ return NULL;
+ ret = XOBNEW (&parser_obstack, struct c_type_name);
+ ret->specs = specs;
+ ret->declarator = declarator;
+ return ret;
+}
+
+/* Parse an initializer (C90 6.5.7, C99 6.7.8).
+
+ initializer:
+ assignment-expression
+ { initializer-list }
+ { initializer-list , }
+
+ initializer-list:
+ designation[opt] initializer
+ initializer-list , designation[opt] initializer
+
+ designation:
+ designator-list =
+
+ designator-list:
+ designator
+ designator-list designator
+
+ designator:
+ array-designator
+ . identifier
+
+ array-designator:
+ [ constant-expression ]
+
+ GNU extensions:
+
+ initializer:
+ { }
+
+ designation:
+ array-designator
+ identifier :
+
+ array-designator:
+ [ constant-expression ... constant-expression ]
+
+ Any expression without commas is accepted in the syntax for the
+ constant-expressions, with non-constant expressions rejected later.
+
+ This function is only used for top-level initializers; for nested
+ ones, see c_parser_initval. */
+
+static struct c_expr
+c_parser_initializer (c_parser *parser)
+{
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ return c_parser_braced_init (parser, NULL_TREE, false);
+ else
+ return c_parser_expr_no_commas (parser, NULL);
+}
+
+/* Parse a braced initializer list. TYPE is the type specified for a
+ compound literal, and NULL_TREE for other initializers and for
+ nested braced lists. NESTED_P is true for nested braced lists,
+ false for the list of a compound literal or the list that is the
+ top-level initializer in a declaration. */
+
+static struct c_expr
+c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
+{
+ gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
+ c_parser_consume_token (parser);
+ if (nested_p)
+ push_init_level (0);
+ else
+ really_start_incremental_init (type);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ if (pedantic)
+ pedwarn ("ISO C forbids empty initializer braces");
+ }
+ else
+ {
+ /* Parse a non-empty initializer list, possibly with a trailing
+ comma. */
+ while (true)
+ {
+ c_parser_initelt (parser);
+ if (parser->error)
+ break;
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ }
+ }
+ if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ struct c_expr ret;
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+ return ret;
+ }
+ c_parser_consume_token (parser);
+ return pop_init_level (0);
+}
+
+/* Parse a nested initializer, including designators. */
+
+static void
+c_parser_initelt (c_parser *parser)
+{
+ /* Parse any designator or designator list. A single array
+ designator may have the subsequent "=" omitted in GNU C, but a
+ longer list or a structure member designator may not. */
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ /* Old-style structure member designator. */
+ set_init_label (c_parser_peek_token (parser)->value);
+ if (pedantic)
+ pedwarn ("obsolete use of designated initializer with %<:%>");
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ /* des_seen is 0 if there have been no designators, 1 if there
+ has been a single array designator and 2 otherwise. */
+ int des_seen = 0;
+ while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
+ || c_parser_next_token_is (parser, CPP_DOT))
+ {
+ int des_prev = des_seen;
+ if (des_seen < 2)
+ des_seen++;
+ if (c_parser_next_token_is (parser, CPP_DOT))
+ {
+ des_seen = 2;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ set_init_label (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ struct c_expr init;
+ init.value = error_mark_node;
+ init.original_code = ERROR_MARK;
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+ process_init_element (init);
+ return;
+ }
+ }
+ else
+ {
+ tree first, second;
+ /* ??? Following the old parser, [ objc-receiver
+ objc-message-args ] is accepted as an initializer,
+ being distinguished from a designator by what follows
+ the first assignment expression inside the square
+ brackets, but after a first array designator a
+ subsequent square bracket is for Objective-C taken to
+ start an expression, using the obsolete form of
+ designated initializer without '=', rather than
+ possibly being a second level of designation: in LALR
+ terms, the '[' is shifted rather than reducing
+ designator to designator-list. */
+ if (des_prev == 1 && c_dialect_objc ())
+ {
+ des_seen = des_prev;
+ break;
+ }
+ if (des_prev == 0 && c_dialect_objc ())
+ {
+ /* This might be an array designator or an
+ Objective-C message expression. If the former,
+ continue parsing here; if the latter, parse the
+ remainder of the initializer given the starting
+ primary-expression. ??? It might make sense to
+ distinguish when des_prev == 1 as well; see
+ previous comment. */
+ tree rec, args;
+ struct c_expr mexpr;
+ c_parser_consume_token (parser);
+ if (c_parser_peek_token (parser)->type == CPP_NAME
+ && ((c_parser_peek_token (parser)->id_kind
+ == C_ID_TYPENAME)
+ || (c_parser_peek_token (parser)->id_kind
+ == C_ID_CLASSNAME)))
+ {
+ /* Type name receiver. */
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ rec = objc_get_class_reference (id);
+ goto parse_message_args;
+ }
+ first = c_parser_expr_no_commas (parser, NULL).value;
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
+ || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ goto array_desig_after_first;
+ /* Expression receiver. So far only one part
+ without commas has been parsed; there might be
+ more of the expression. */
+ rec = first;
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ tree next;
+ c_parser_consume_token (parser);
+ next = c_parser_expr_no_commas (parser, NULL).value;
+ rec = build_compound_expr (rec, next);
+ }
+ parse_message_args:
+ /* Now parse the objc-message-args. */
+ args = c_parser_objc_message_args (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ mexpr.value
+ = objc_build_message_expr (build_tree_list (rec, args));
+ mexpr.original_code = ERROR_MARK;
+ /* Now parse and process the remainder of the
+ initializer, starting with this message
+ expression as a primary-expression. */
+ c_parser_initval (parser, &mexpr);
+ return;
+ }
+ c_parser_consume_token (parser);
+ first = c_parser_expr_no_commas (parser, NULL).value;
+ array_desig_after_first:
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+ {
+ c_parser_consume_token (parser);
+ second = c_parser_expr_no_commas (parser, NULL).value;
+ }
+ else
+ second = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ {
+ c_parser_consume_token (parser);
+ set_init_index (first, second);
+ if (pedantic && second)
+ pedwarn ("ISO C forbids specifying range of "
+ "elements to initialize");
+ }
+ else
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ }
+ }
+ if (des_seen >= 1)
+ {
+ if (c_parser_next_token_is (parser, CPP_EQ))
+ {
+ if (pedantic && !flag_isoc99)
+ pedwarn ("ISO C90 forbids specifying subobject to initialize");
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ if (des_seen == 1)
+ {
+ if (pedantic)
+ pedwarn ("obsolete use of designated initializer "
+ "without %<=%>");
+ }
+ else
+ {
+ struct c_expr init;
+ init.value = error_mark_node;
+ init.original_code = ERROR_MARK;
+ c_parser_error (parser, "expected %<=%>");
+ c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+ process_init_element (init);
+ return;
+ }
+ }
+ }
+ }
+ c_parser_initval (parser, NULL);
+}
+
+/* Parse a nested initializer; as c_parser_initializer but parses
+ initializers within braced lists, after any designators have been
+ applied. If AFTER is not NULL then it is an Objective-C message
+ expression which is the primary-expression starting the
+ initializer. */
+
+static void
+c_parser_initval (c_parser *parser, struct c_expr *after)
+{
+ struct c_expr init;
+ gcc_assert (!after || c_dialect_objc ());
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
+ init = c_parser_braced_init (parser, NULL_TREE, true);
+ else
+ init = c_parser_expr_no_commas (parser, after);
+ process_init_element (init);
+}
+
+/* Parse a compound statement (possibly a function body) (C90 6.6.2,
+ C99 6.8.2).
+
+ compound-statement:
+ { block-item-list[opt] }
+ { label-declarations block-item-list }
+
+ block-item-list:
+ block-item
+ block-item-list block-item
+
+ block-item:
+ nested-declaration
+ statement
+
+ nested-declaration:
+ declaration
+
+ GNU extensions:
+
+ compound-statement:
+ { label-declarations block-item-list }
+
+ nested-declaration:
+ __extension__ nested-declaration
+ nested-function-definition
+
+ label-declarations:
+ label-declaration
+ label-declarations label-declaration
+
+ label-declaration:
+ __label__ identifier-list ;
+
+ Allowing the mixing of declarations and code is new in C99. The
+ GNU syntax also permits (not shown above) labels at the end of
+ compound statements, which yield an error. We don't allow labels
+ on declarations; this might seem like a natural extension, but
+ there would be a conflict between attributes on the label and
+ prefix attributes on the declaration. ??? The syntax follows the
+ old parser in requiring something after label declarations.
+ Although they are erroneous if the labels declared aren't defined,
+ is it useful for the syntax to be this way? */
+
+static tree
+c_parser_compound_statement (c_parser *parser)
+{
+ tree stmt;
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ return NULL_TREE;
+ stmt = c_begin_compound_stmt (true);
+ c_parser_compound_statement_nostart (parser);
+ return c_end_compound_stmt (stmt, true);
+}
+
+/* Parse a compound statement except for the opening brace. This is
+ used for parsing both compound statements and statement expressions
+ (which follow different paths to handling the opening). */
+
+static void
+c_parser_compound_statement_nostart (c_parser *parser)
+{
+ bool last_stmt = false;
+ bool last_label = false;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_consume_token (parser);
+ return;
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_LABEL))
+ {
+ /* Read zero or more forward-declarations for labels that nested
+ functions can jump to. */
+ while (c_parser_next_token_is_keyword (parser, RID_LABEL))
+ {
+ c_parser_consume_token (parser);
+ /* Any identifiers, including those declared as type names,
+ are OK here. */
+ while (true)
+ {
+ tree label;
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ label
+ = declare_label (c_parser_peek_token (parser)->value);
+ C_DECLARED_LABEL_FLAG (label) = 1;
+ add_stmt (build_stmt (DECL_EXPR, label));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+ /* ??? Locating this diagnostic on the token after the
+ declarations end follows the old parser, but it might be
+ better to locate it where the declarations start instead. */
+ if (pedantic)
+ pedwarn ("ISO C forbids label declarations");
+ }
+ /* We must now have at least one statement, label or declaration. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_error (parser, "expected declaration or statement");
+ c_parser_consume_token (parser);
+ return;
+ }
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ parser->error = true;
+ return;
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_CASE)
+ || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+ || (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+ {
+ last_label = true;
+ last_stmt = false;
+ c_parser_label (parser);
+ }
+ else if (!last_label
+ && c_parser_next_token_starts_declspecs (parser))
+ {
+ last_label = false;
+ c_parser_declaration_or_fndef (parser, true, true, true, true);
+ if (last_stmt
+ && ((pedantic && !flag_isoc99)
+ || warn_declaration_after_statement))
+ pedwarn_c90 ("%HISO C90 forbids mixed declarations and code",
+ &loc);
+ last_stmt = false;
+ }
+ else if (!last_label
+ && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+ {
+ /* __extension__ can start a declaration, but is also an
+ unary operator that can start an expression. Consume all
+ but the last of a possible series of __extension__ to
+ determine which. */
+ while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+ && (c_parser_peek_2nd_token (parser)->keyword
+ == RID_EXTENSION))
+ c_parser_consume_token (parser);
+ if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+ {
+ int ext;
+ ext = disable_extension_diagnostics ();
+ c_parser_consume_token (parser);
+ last_label = false;
+ c_parser_declaration_or_fndef (parser, true, true, true, true);
+ /* Following the old parser, __extension__ does not
+ disable this diagnostic. */
+ restore_extension_diagnostics (ext);
+ if (last_stmt
+ && ((pedantic && !flag_isoc99)
+ || warn_declaration_after_statement))
+ pedwarn_c90 ("%HISO C90 forbids mixed declarations and code",
+ &loc);
+ last_stmt = false;
+ }
+ else
+ goto statement;
+ }
+ else
+ {
+ statement:
+ last_label = false;
+ last_stmt = true;
+ c_parser_statement_after_labels (parser);
+ }
+ }
+ if (last_label)
+ error ("label at end of compound statement");
+ c_parser_consume_token (parser);
+}
+
+/* Parse a label (C90 6.6.1, C99 6.8.1).
+
+ label:
+ identifier : attributes[opt]
+ case constant-expression :
+ default :
+
+ GNU extensions:
+
+ label:
+ case constant-expression ... constant-expression :
+
+ The use of attributes on labels is a GNU extension. The syntax in
+ GNU C accepts any expressions without commas, non-constant
+ expressions being rejected later. */
+
+static void
+c_parser_label (c_parser *parser)
+{
+ location_t loc1 = c_parser_peek_token (parser)->location;
+ tree label = NULL_TREE;
+ if (c_parser_next_token_is_keyword (parser, RID_CASE))
+ {
+ tree exp1, exp2;
+ c_parser_consume_token (parser);
+ exp1 = c_parser_expr_no_commas (parser, NULL).value;
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ label = do_case (exp1, NULL_TREE);
+ }
+ else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+ {
+ c_parser_consume_token (parser);
+ exp2 = c_parser_expr_no_commas (parser, NULL).value;
+ if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ label = do_case (exp1, exp2);
+ }
+ else
+ c_parser_error (parser, "expected %<:%> or %<...%>");
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ label = do_case (NULL_TREE, NULL_TREE);
+ }
+ else
+ {
+ tree name = c_parser_peek_token (parser)->value;
+ tree tlab;
+ location_t loc2;
+ tree attrs;
+ gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+ c_parser_consume_token (parser);
+ gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+ loc2 = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ attrs = c_parser_attributes (parser);
+ tlab = define_label (loc2, name);
+ if (tlab)
+ {
+ decl_attributes (&tlab, attrs, 0);
+ label = add_stmt (build_stmt (LABEL_EXPR, tlab));
+ }
+ }
+ if (label)
+ SET_EXPR_LOCATION (label, loc1);
+}
+
+/* Parse a statement (C90 6.6, C99 6.8).
+
+ statement:
+ labeled-statement
+ compound-statement
+ expression-statement
+ selection-statement
+ iteration-statement
+ jump-statement
+
+ labeled-statement:
+ label statement
+
+ expression-statement:
+ expression[opt] ;
+
+ selection-statement:
+ if-statement
+ switch-statement
+
+ iteration-statement:
+ while-statement
+ do-statement
+ for-statement
+
+ jump-statement:
+ goto identifier ;
+ continue ;
+ break ;
+ return expression[opt] ;
+
+ GNU extensions:
+
+ statement:
+ asm-statement
+
+ jump-statement:
+ goto * expression ;
+
+ Objective-C:
+
+ statement:
+ objc-throw-statement
+ objc-try-catch-statement
+ objc-synchronized-statement
+
+ objc-throw-statement:
+ @throw expression ;
+ @throw ;
+*/
+
+static void
+c_parser_statement (c_parser *parser)
+{
+ while (c_parser_next_token_is_keyword (parser, RID_CASE)
+ || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+ || (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+ c_parser_label (parser);
+ c_parser_statement_after_labels (parser);
+}
+
+/* Parse a statement, other than a labeled statement. */
+
+static void
+c_parser_statement_after_labels (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree stmt = NULL_TREE;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_BRACE:
+ add_stmt (c_parser_compound_statement (parser));
+ break;
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_IF:
+ c_parser_if_statement (parser);
+ break;
+ case RID_SWITCH:
+ c_parser_switch_statement (parser);
+ break;
+ case RID_WHILE:
+ c_parser_while_statement (parser);
+ break;
+ case RID_DO:
+ c_parser_do_statement (parser);
+ break;
+ case RID_FOR:
+ c_parser_for_statement (parser);
+ break;
+ case RID_GOTO:
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ stmt = c_finish_goto_label (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ }
+ else if (c_parser_next_token_is (parser, CPP_MULT))
+ {
+ c_parser_consume_token (parser);
+ stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
+ }
+ else
+ c_parser_error (parser, "expected identifier or %<*%>");
+ goto expect_semicolon;
+ case RID_CONTINUE:
+ c_parser_consume_token (parser);
+ stmt = c_finish_bc_stmt (&c_cont_label, false);
+ goto expect_semicolon;
+ case RID_BREAK:
+ c_parser_consume_token (parser);
+ stmt = c_finish_bc_stmt (&c_break_label, true);
+ goto expect_semicolon;
+ case RID_RETURN:
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ stmt = c_finish_return (NULL_TREE);
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ stmt = c_finish_return (c_parser_expression (parser).value);
+ goto expect_semicolon;
+ }
+ break;
+ case RID_ASM:
+ stmt = c_parser_asm_statement (parser);
+ break;
+ case RID_AT_THROW:
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ stmt = objc_build_throw_stmt (NULL_TREE);
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ stmt
+ = objc_build_throw_stmt (c_parser_expression (parser).value);
+ goto expect_semicolon;
+ }
+ break;
+ case RID_AT_TRY:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_try_catch_statement (parser);
+ break;
+ case RID_AT_SYNCHRONIZED:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_synchronized_statement (parser);
+ break;
+ default:
+ goto expr_stmt;
+ }
+ break;
+ case CPP_SEMICOLON:
+ c_parser_consume_token (parser);
+ break;
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_SQUARE:
+ /* Avoid infinite loop in error recovery:
+ c_parser_skip_until_found stops at a closing nesting
+ delimiter without consuming it, but here we need to consume
+ it to proceed further. */
+ c_parser_error (parser, "expected statement");
+ c_parser_consume_token (parser);
+ break;
+ default:
+ expr_stmt:
+ stmt = c_finish_expr_stmt (c_parser_expression (parser).value);
+ expect_semicolon:
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ break;
+ }
+ /* 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 statements should already have
+ line numbers assigned. ??? Can we discard no-op statements
+ earlier? */
+ if (stmt && EXPR_P (stmt))
+ SET_EXPR_LOCATION (stmt, loc);
+}
+
+/* Parse a parenthesized condition from an if, do or while statement.
+
+ condition:
+ ( expression )
+*/
+static tree
+c_parser_paren_condition (c_parser *parser)
+{
+ location_t loc;
+ tree cond;
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return error_mark_node;
+ loc = c_parser_peek_token (parser)->location;
+ cond = lang_hooks.truthvalue_conversion (c_parser_expression (parser).value);
+ if (EXPR_P (cond))
+ SET_EXPR_LOCATION (cond, loc);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return cond;
+}
+
+/* Parse a statement which is a block in C99. */
+
+static tree
+c_parser_c99_block_statement (c_parser *parser)
+{
+ tree block = c_begin_compound_stmt (flag_isoc99);
+ c_parser_statement (parser);
+ return c_end_compound_stmt (block, flag_isoc99);
+}
+
+/* Parse the body of an if statement or the else half thereof. This
+ is just parsing a statement but (a) it is a block in C99, (b) we
+ track whether the body is an if statement for the sake of
+ -Wparentheses warnings, (c) we handle an empty body specially for
+ the sake of -Wextra warnings. */
+
+static tree
+c_parser_if_body (c_parser *parser, bool *if_p)
+{
+ tree block = c_begin_compound_stmt (flag_isoc99);
+ while (c_parser_next_token_is_keyword (parser, RID_CASE)
+ || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+ || (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+ c_parser_label (parser);
+ *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
+ if (extra_warnings && c_parser_next_token_is (parser, CPP_SEMICOLON))
+ add_stmt (build (NOP_EXPR, NULL_TREE, NULL_TREE));
+ c_parser_statement_after_labels (parser);
+ return c_end_compound_stmt (block, flag_isoc99);
+}
+
+/* Parse an if statement (C90 6.6.4, C99 6.8.4).
+
+ if-statement:
+ if ( expression ) statement
+ if ( expression ) statement else statement
+*/
+
+static void
+c_parser_if_statement (c_parser *parser)
+{
+ tree block;
+ location_t loc;
+ tree cond;
+ bool first_if = false, second_if = false;
+ tree first_body, second_body;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (flag_isoc99);
+ loc = c_parser_peek_token (parser)->location;
+ cond = c_parser_paren_condition (parser);
+ first_body = c_parser_if_body (parser, &first_if);
+ if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ {
+ c_parser_consume_token (parser);
+ second_body = c_parser_if_body (parser, &second_if);
+ }
+ else
+ second_body = NULL_TREE;
+ c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
+ add_stmt (c_end_compound_stmt (block, flag_isoc99));
+}
+
+/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
+
+ switch-statement:
+ switch (expression) statement
+*/
+
+static void
+c_parser_switch_statement (c_parser *parser)
+{
+ tree block, expr, body, save_break;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (flag_isoc99);
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr = c_parser_expression (parser).value;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ expr = error_mark_node;
+ c_start_case (expr);
+ save_break = c_break_label;
+ c_break_label = NULL_TREE;
+ body = c_parser_c99_block_statement (parser);
+ c_finish_case (body);
+ if (c_break_label)
+ add_stmt (build (LABEL_EXPR, void_type_node, c_break_label));
+ c_break_label = save_break;
+ add_stmt (c_end_compound_stmt (block, flag_isoc99));
+}
+
+/* Parse a while statement (C90 6.6.5, C99 6.8.5).
+
+ while-statement:
+ while (expression) statement
+*/
+
+static void
+c_parser_while_statement (c_parser *parser)
+{
+ tree block, cond, body, save_break, save_cont;
+ location_t loc;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (flag_isoc99);
+ loc = c_parser_peek_token (parser)->location;
+ cond = c_parser_paren_condition (parser);
+ save_break = c_break_label;
+ c_break_label = NULL_TREE;
+ save_cont = c_cont_label;
+ c_cont_label = NULL_TREE;
+ body = c_parser_c99_block_statement (parser);
+ c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
+ add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ c_break_label = save_break;
+ c_cont_label = save_cont;
+}
+
+/* Parse a do statement (C90 6.6.5, C99 6.8.5).
+
+ do-statement:
+ do statement while ( expression ) ;
+*/
+
+static void
+c_parser_do_statement (c_parser *parser)
+{
+ tree block, cond, body, save_break, save_cont, new_break, new_cont;
+ location_t loc;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (flag_isoc99);
+ loc = c_parser_peek_token (parser)->location;
+ save_break = c_break_label;
+ c_break_label = NULL_TREE;
+ save_cont = c_cont_label;
+ c_cont_label = NULL_TREE;
+ body = c_parser_c99_block_statement (parser);
+ c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
+ new_break = c_break_label;
+ c_break_label = save_break;
+ new_cont = c_cont_label;
+ c_cont_label = save_cont;
+ cond = c_parser_paren_condition (parser);
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
+ add_stmt (c_end_compound_stmt (block, flag_isoc99));
+}
+
+/* Parse a for statement (C90 6.6.5, C99 6.8.5).
+
+ for-statement:
+ for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
+ for ( nested-declaration expression[opt] ; expression[opt] ) statement
+
+ The form with a declaration is new in C99.
+
+ ??? In accordance with the old parser, the declaration may be a
+ nested function, which is then rejected in check_for_loop_decls,
+ but does it make any sense for this to be included in the grammar?
+ Note in particular that the nested function does not include a
+ trailing ';', whereas the "declaration" production includes one.
+ Also, can we reject bad declarations earlier and cheaper than
+ check_for_loop_decls? */
+
+static void
+c_parser_for_statement (c_parser *parser)
+{
+ tree block, cond, incr, save_break, save_cont, body;
+ location_t loc;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
+ c_parser_consume_token (parser);
+ block = c_begin_compound_stmt (flag_isoc99);
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ /* Parse the initialization declaration or expression. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_parser_consume_token (parser);
+ c_finish_expr_stmt (NULL_TREE);
+ }
+ else if (c_parser_next_token_starts_declspecs (parser))
+ {
+ c_parser_declaration_or_fndef (parser, true, true, true, true);
+ check_for_loop_decls ();
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+ {
+ /* __extension__ can start a declaration, but is also an
+ unary operator that can start an expression. Consume all
+ but the last of a possible series of __extension__ to
+ determine which. */
+ while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+ && (c_parser_peek_2nd_token (parser)->keyword
+ == RID_EXTENSION))
+ c_parser_consume_token (parser);
+ if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+ {
+ int ext;
+ ext = disable_extension_diagnostics ();
+ c_parser_consume_token (parser);
+ c_parser_declaration_or_fndef (parser, true, true, true, true);
+ restore_extension_diagnostics (ext);
+ check_for_loop_decls ();
+ }
+ else
+ goto init_expr;
+ }
+ else
+ {
+ init_expr:
+ c_finish_expr_stmt (c_parser_expression (parser).value);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+ /* Parse the loop condition. */
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_parser_consume_token (parser);
+ cond = NULL_TREE;
+ }
+ else
+ {
+ tree ocond = c_parser_expression (parser).value;
+ cond = lang_hooks.truthvalue_conversion (ocond);
+ if (EXPR_P (cond))
+ SET_EXPR_LOCATION (cond, loc);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+ /* Parse the increment expression. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ incr = c_process_expr_stmt (NULL_TREE);
+ else
+ incr = c_process_expr_stmt (c_parser_expression (parser).value);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ {
+ cond = error_mark_node;
+ incr = error_mark_node;
+ }
+ save_break = c_break_label;
+ c_break_label = NULL_TREE;
+ save_cont = c_cont_label;
+ c_cont_label = NULL_TREE;
+ body = c_parser_c99_block_statement (parser);
+ c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+ add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ c_break_label = save_break;
+ c_cont_label = save_cont;
+}
+
+/* Parse an asm statement, a GNU extension. This is a full-blown asm
+ statement with inputs, outputs, clobbers, and volatile tag
+ allowed.
+
+ asm-statement:
+ asm type-qualifier[opt] ( asm-argument ) ;
+
+ asm-argument:
+ asm-string-literal
+ asm-string-literal : asm-operands[opt]
+ asm-string-literal : asm-operands[opt] : asm-operands[opt]
+ asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers
+
+ Qualifiers other than volatile are accepted in the syntax but
+ warned for. */
+
+static tree
+c_parser_asm_statement (c_parser *parser)
+{
+ tree quals, str, outputs, inputs, clobbers, ret;
+ bool simple;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
+ {
+ quals = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_CONST)
+ || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
+ {
+ warning ("%E qualifier ignored on asm",
+ c_parser_peek_token (parser)->value);
+ quals = NULL_TREE;
+ c_parser_consume_token (parser);
+ }
+ else
+ quals = NULL_TREE;
+ /* ??? Follow the C++ parser rather than using the
+ c_lex_string_translate kludge. */
+ c_lex_string_translate = 0;
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_lex_string_translate = 1;
+ return NULL_TREE;
+ }
+ str = c_parser_asm_string_literal (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ simple = true;
+ outputs = NULL_TREE;
+ inputs = NULL_TREE;
+ clobbers = NULL_TREE;
+ goto done_asm;
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ simple = false;
+ /* Parse outputs. */
+ if (c_parser_next_token_is (parser, CPP_COLON)
+ || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ outputs = NULL_TREE;
+ else
+ outputs = c_parser_asm_operands (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ inputs = NULL_TREE;
+ clobbers = NULL_TREE;
+ goto done_asm;
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ /* Parse inputs. */
+ if (c_parser_next_token_is (parser, CPP_COLON)
+ || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ inputs = NULL_TREE;
+ else
+ inputs = c_parser_asm_operands (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ clobbers = NULL_TREE;
+ goto done_asm;
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
+ {
+ c_lex_string_translate = 1;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ /* Parse clobbers. */
+ clobbers = c_parser_asm_clobbers (parser);
+ done_asm:
+ c_lex_string_translate = 1;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs,
+ clobbers, simple));
+ return ret;
+}
+
+/* Parse asm operands, a GNU extension.
+
+ asm-operands:
+ asm-operand
+ asm-operands , asm-operand
+
+ asm-operand:
+ asm-string-literal ( expression )
+ [ identifier ] asm-string-literal ( expression )
+*/
+
+static tree
+c_parser_asm_operands (c_parser *parser)
+{
+ tree list = NULL_TREE;
+ while (true)
+ {
+ tree name, str, expr;
+ if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ name = build_string (IDENTIFIER_LENGTH (id),
+ IDENTIFIER_POINTER (id));
+ }
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+ return NULL_TREE;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ }
+ else
+ name = NULL_TREE;
+ str = c_parser_asm_string_literal (parser);
+ if (str == NULL_TREE)
+ return NULL_TREE;
+ c_lex_string_translate = 1;
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_lex_string_translate = 0;
+ return NULL_TREE;
+ }
+ expr = c_parser_expression (parser).value;
+ c_lex_string_translate = 0;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return NULL_TREE;
+ }
+ list = chainon (list, build_tree_list (build_tree_list (name, str),
+ expr));
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ return list;
+}
+
+/* Parse asm clobbers, a GNU extension.
+
+ asm-clobbers:
+ asm-string-literal
+ asm-clobbers , asm-string-literal
+*/
+
+static tree
+c_parser_asm_clobbers (c_parser *parser)
+{
+ tree list = NULL_TREE;
+ while (true)
+ {
+ tree str = c_parser_asm_string_literal (parser);
+ if (str)
+ list = tree_cons (NULL_TREE, str, list);
+ else
+ return NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ return list;
+}
+
+/* Parse an expression other than a compound expression; that is, an
+ assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not
+ NULL then it is an Objective-C message expression which is the
+ primary-expression starting the expression as an initializer.
+
+ assignment-expression:
+ conditional-expression
+ unary-expression assignment-operator assignment-expression
+
+ assignment-operator: one of
+ = *= /= %= += -= <<= >>= &= ^= |=
+
+ In GNU C we accept any conditional expression on the LHS and
+ diagnose the invalid lvalue rather than producing a syntax
+ error. */
+
+static struct c_expr
+c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
+{
+ struct c_expr lhs, rhs, ret;
+ enum tree_code code;
+ gcc_assert (!after || c_dialect_objc ());
+ lhs = c_parser_conditional_expression (parser, after);
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_EQ:
+ code = NOP_EXPR;
+ break;
+ case CPP_MULT_EQ:
+ code = MULT_EXPR;
+ break;
+ case CPP_DIV_EQ:
+ code = TRUNC_DIV_EXPR;
+ break;
+ case CPP_MOD_EQ:
+ code = TRUNC_MOD_EXPR;
+ break;
+ case CPP_PLUS_EQ:
+ code = PLUS_EXPR;
+ break;
+ case CPP_MINUS_EQ:
+ code = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT_EQ:
+ code = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT_EQ:
+ code = RSHIFT_EXPR;
+ break;
+ case CPP_AND_EQ:
+ code = BIT_AND_EXPR;
+ break;
+ case CPP_XOR_EQ:
+ code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR_EQ:
+ code = BIT_IOR_EXPR;
+ break;
+ default:
+ return lhs;
+ }
+ c_parser_consume_token (parser);
+ rhs = c_parser_expr_no_commas (parser, NULL);
+ ret.value = build_modify_expr (lhs.value, code, rhs.value);
+ if (code == NOP_EXPR)
+ ret.original_code = MODIFY_EXPR;
+ else
+ {
+ TREE_NO_WARNING (ret.value) = 1;
+ ret.original_code = ERROR_MARK;
+ }
+ return ret;
+}
+
+/* Parse a conditional expression (C90 6.3.15, C99 6.5.15). If AFTER
+ is not NULL then it is an Objective-C message expression which is
+ the primary-expression starting the expression as an initializer.
+
+ conditional-expression:
+ logical-OR-expression
+ logical-OR-expression ? expression : conditional-expression
+
+ GNU extensions:
+
+ conditional-expression:
+ logical-OR-expression ? : conditional-expression
+*/
+
+static struct c_expr
+c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
+{
+ struct c_expr cond, exp1, exp2, ret;
+ gcc_assert (!after || c_dialect_objc ());
+ cond = c_parser_binary_expression (parser, after);
+ if (c_parser_next_token_is_not (parser, CPP_QUERY))
+ return cond;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ if (pedantic)
+ pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
+ /* Make sure first operand is calculated only once. */
+ exp1.value = save_expr (default_conversion (cond.value));
+ cond.value = lang_hooks.truthvalue_conversion (exp1.value);
+ skip_evaluation += cond.value == truthvalue_true_node;
+ }
+ else
+ {
+ cond.value
+ = lang_hooks.truthvalue_conversion (default_conversion (cond.value));
+ skip_evaluation += cond.value == truthvalue_false_node;
+ exp1 = c_parser_expression (parser);
+ skip_evaluation += ((cond.value == truthvalue_true_node)
+ - (cond.value == truthvalue_false_node));
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ {
+ skip_evaluation -= cond.value == truthvalue_true_node;
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ exp2 = c_parser_conditional_expression (parser, NULL);
+ skip_evaluation -= cond.value == truthvalue_true_node;
+ ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
+ ret.original_code = ERROR_MARK;
+ return ret;
+}
+
+/* Parse a binary expression; that is, a logical-OR-expression (C90
+ 6.3.5-6.3.14, C99 6.5.5-6.5.14). If AFTER is not NULL then it is
+ an Objective-C message expression which is the primary-expression
+ starting the expression as an initializer.
+
+ multiplicative-expression:
+ cast-expression
+ multiplicative-expression * cast-expression
+ multiplicative-expression / cast-expression
+ multiplicative-expression % cast-expression
+
+ additive-expression:
+ multiplicative-expression
+ additive-expression + multiplicative-expression
+ additive-expression - multiplicative-expression
+
+ shift-expression:
+ additive-expression
+ shift-expression << additive-expression
+ shift-expression >> additive-expression
+
+ relational-expression:
+ shift-expression
+ relational-expression < shift-expression
+ relational-expression > shift-expression
+ relational-expression <= shift-expression
+ relational-expression >= shift-expression
+
+ equality-expression:
+ relational-expression
+ equality-expression == relational-expression
+ equality-expression != relational-expression
+
+ AND-expression:
+ equality-expression
+ AND-expression & equality-expression
+
+ exclusive-OR-expression:
+ AND-expression
+ exclusive-OR-expression ^ AND-expression
+
+ inclusive-OR-expression:
+ exclusive-OR-expression
+ inclusive-OR-expression | exclusive-OR-expression
+
+ logical-AND-expression:
+ inclusive-OR-expression
+ logical-AND-expression && inclusive-OR-expression
+
+ logical-OR-expression:
+ logical-AND-expression
+ logical-OR-expression || logical-AND-expression
+*/
+
+static struct c_expr
+c_parser_binary_expression (c_parser *parser, struct c_expr *after)
+{
+ /* A binary expression is parsed using operator-precedence parsing,
+ with the operands being cast expressions. All the binary
+ operators are left-associative. Thus a binary expression is of
+ form:
+
+ E0 op1 E1 op2 E2 ...
+
+ which we represent on a stack. On the stack, the precedence
+ levels are strictly increasing. When a new operator is
+ encountered of higher precedence than that at the top of the
+ stack, it is pushed; its LHS is the top expression, and its RHS
+ is everything parsed until it is popped. When a new operator is
+ encountered with precedence less than or equal to that at the top
+ of the stack, triples E[i-1] op[i] E[i] are popped and replaced
+ by the result of the operation until the operator at the top of
+ the stack has lower precedence than the new operator or there is
+ only one element on the stack; then the top expression is the LHS
+ of the new operator. In the case of logical AND and OR
+ expressions, we also need to adjust skip_evaluation as
+ appropriate when the operators are pushed and popped. */
+
+ /* The precedence levels, where 0 is a dummy lowest level used for
+ the bottom of the stack. */
+ enum prec {
+ PREC_NONE,
+ PREC_LOGOR,
+ PREC_LOGAND,
+ PREC_BITOR,
+ PREC_BITXOR,
+ PREC_BITAND,
+ PREC_EQ,
+ PREC_REL,
+ PREC_SHIFT,
+ PREC_ADD,
+ PREC_MULT,
+ NUM_PRECS
+ };
+ struct {
+ /* The expression at this stack level. */
+ struct c_expr expr;
+ /* The precedence of the operator on its left, PREC_NONE at the
+ bottom of the stack. */
+ enum prec prec;
+ /* The operation on its left. */
+ enum tree_code op;
+ } stack[NUM_PRECS];
+ int sp;
+#define POP \
+ do { \
+ switch (stack[sp].op) \
+ { \
+ case TRUTH_ANDIF_EXPR: \
+ skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \
+ break; \
+ case TRUTH_ORIF_EXPR: \
+ skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node; \
+ break; \
+ default: \
+ break; \
+ } \
+ stack[sp - 1].expr = parser_build_binary_op (stack[sp].op, \
+ stack[sp - 1].expr, \
+ stack[sp].expr); \
+ sp--; \
+ } while (0)
+ gcc_assert (!after || c_dialect_objc ());
+ stack[0].expr = c_parser_cast_expression (parser, after);
+ stack[0].prec = PREC_NONE;
+ sp = 0;
+ while (true)
+ {
+ enum prec oprec;
+ enum tree_code ocode;
+ if (parser->error)
+ goto out;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_MULT:
+ oprec = PREC_MULT;
+ ocode = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ oprec = PREC_MULT;
+ ocode = TRUNC_DIV_EXPR;
+ break;
+ case CPP_MOD:
+ oprec = PREC_MULT;
+ ocode = TRUNC_MOD_EXPR;
+ break;
+ case CPP_PLUS:
+ oprec = PREC_ADD;
+ ocode = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ oprec = PREC_ADD;
+ ocode = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ oprec = PREC_SHIFT;
+ ocode = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ oprec = PREC_SHIFT;
+ ocode = RSHIFT_EXPR;
+ break;
+ case CPP_LESS:
+ oprec = PREC_REL;
+ ocode = LT_EXPR;
+ break;
+ case CPP_GREATER:
+ oprec = PREC_REL;
+ ocode = GT_EXPR;
+ break;
+ case CPP_LESS_EQ:
+ oprec = PREC_REL;
+ ocode = LE_EXPR;
+ break;
+ case CPP_GREATER_EQ:
+ oprec = PREC_REL;
+ ocode = GE_EXPR;
+ break;
+ case CPP_EQ_EQ:
+ oprec = PREC_EQ;
+ ocode = EQ_EXPR;
+ break;
+ case CPP_NOT_EQ:
+ oprec = PREC_EQ;
+ ocode = NE_EXPR;
+ break;
+ case CPP_AND:
+ oprec = PREC_BITAND;
+ ocode = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ oprec = PREC_BITXOR;
+ ocode = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ oprec = PREC_BITOR;
+ ocode = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ oprec = PREC_LOGAND;
+ ocode = TRUTH_ANDIF_EXPR;
+ break;
+ case CPP_OR_OR:
+ oprec = PREC_LOGOR;
+ ocode = TRUTH_ORIF_EXPR;
+ break;
+ default:
+ /* Not a binary operator, so end of the binary
+ expression. */
+ goto out;
+ }
+ c_parser_consume_token (parser);
+ while (oprec <= stack[sp].prec)
+ POP;
+ switch (ocode)
+ {
+ case TRUTH_ANDIF_EXPR:
+ stack[sp].expr.value = lang_hooks.truthvalue_conversion
+ (default_conversion (stack[sp].expr.value));
+ skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
+ break;
+ case TRUTH_ORIF_EXPR:
+ stack[sp].expr.value = lang_hooks.truthvalue_conversion
+ (default_conversion (stack[sp].expr.value));
+ skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
+ break;
+ default:
+ break;
+ }
+ sp++;
+ stack[sp].expr = c_parser_cast_expression (parser, NULL);
+ stack[sp].prec = oprec;
+ stack[sp].op = ocode;
+ }
+ out:
+ while (sp > 0)
+ POP;
+ return stack[0].expr;
+#undef POP
+}
+
+/* Parse a cast expression (C90 6.3.4, C99 6.5.4). If AFTER is not
+ NULL then it is an Objective-C message expression which is the
+ primary-expression starting the expression as an initializer.
+
+ cast-expression:
+ unary-expression
+ ( type-name ) unary-expression
+*/
+
+static struct c_expr
+c_parser_cast_expression (c_parser *parser, struct c_expr *after)
+{
+ gcc_assert (!after || c_dialect_objc ());
+ if (after)
+ return c_parser_postfix_expression_after_primary (parser, *after);
+ /* If the expression begins with a parenthesized type name, it may
+ be either a cast or a compound literal; we need to see whether
+ the next character is '{' to tell the difference. If not, it is
+ an unary expression. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ struct c_type_name *type_name;
+ struct c_expr ret;
+ tree expr;
+ c_parser_consume_token (parser);
+ type_name = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (type_name == NULL)
+ {
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ return c_parser_postfix_expression_after_paren_type (parser,
+ type_name);
+ expr = c_parser_cast_expression (parser, NULL).value;
+ ret.value = c_cast_expr (type_name, expr);
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ else
+ return c_parser_unary_expression (parser);
+}
+
+/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
+
+ unary-expression:
+ postfix-expression
+ ++ unary-expression
+ -- unary-expression
+ unary-operator cast-expression
+ sizeof unary-expression
+ sizeof ( type-name )
+
+ unary-operator: one of
+ & * + - ~ !
+
+ GNU extensions:
+
+ unary-expression:
+ __alignof__ unary-expression
+ __alignof__ ( type-name )
+ && identifier
+
+ unary-operator: one of
+ __extension__ __real__ __imag__
+
+ In addition, the GNU syntax treats ++ and -- as unary operators, so
+ they may be applied to cast expressions with errors for non-lvalues
+ given later. */
+
+static struct c_expr
+c_parser_unary_expression (c_parser *parser)
+{
+ int ext;
+ struct c_expr ret;
+ ret.original_code = ERROR_MARK;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_PLUS_PLUS:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (PREINCREMENT_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_MINUS_MINUS:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (PREDECREMENT_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_AND:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (ADDR_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_MULT:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_indirect_ref (c_parser_cast_expression (parser, NULL).value,
+ "unary *");
+ return ret;
+ case CPP_PLUS:
+ c_parser_consume_token (parser);
+ if (!c_dialect_objc () && warn_traditional && !in_system_header)
+ warning ("traditional C rejects the unary plus operator");
+ ret.value
+ = build_unary_op (CONVERT_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_MINUS:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (NEGATE_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_COMPL:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (BIT_NOT_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_NOT:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (TRUTH_NOT_EXPR,
+ c_parser_cast_expression (parser, NULL).value, 0);
+ overflow_warning (ret.value);
+ return ret;
+ case CPP_AND_AND:
+ /* Refer to the address of a label as a pointer. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ ret.value = finish_label_address_expr
+ (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ return ret;
+ }
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ ret.value = error_mark_node;
+ return ret;
+ }
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_SIZEOF:
+ return c_parser_sizeof_expression (parser);
+ case RID_ALIGNOF:
+ return c_parser_alignof_expression (parser);
+ case RID_EXTENSION:
+ c_parser_consume_token (parser);
+ ext = disable_extension_diagnostics ();
+ ret = c_parser_cast_expression (parser, NULL);
+ restore_extension_diagnostics (ext);
+ return ret;
+ case RID_REALPART:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (REALPART_EXPR,
+ c_parser_cast_expression (parser, NULL).value,
+ 0);
+ return ret;
+ case RID_IMAGPART:
+ c_parser_consume_token (parser);
+ ret.value
+ = build_unary_op (IMAGPART_EXPR,
+ c_parser_cast_expression (parser, NULL).value,
+ 0);
+ return ret;
+ default:
+ return c_parser_postfix_expression (parser);
+ }
+ default:
+ return c_parser_postfix_expression (parser);
+ }
+}
+
+/* Parse a sizeof expression. */
+
+static struct c_expr
+c_parser_sizeof_expression (c_parser *parser)
+{
+ struct c_expr expr;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+ c_parser_consume_token (parser);
+ skip_evaluation++;
+ in_sizeof++;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ /* Either sizeof ( type-name ) or sizeof unary-expression
+ starting with a compound literal. */
+ struct c_type_name *type_name;
+ c_parser_consume_token (parser);
+ type_name = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (type_name == NULL)
+ {
+ struct c_expr ret;
+ skip_evaluation--;
+ in_sizeof--;
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ {
+ expr = c_parser_postfix_expression_after_paren_type (parser,
+ type_name);
+ goto sizeof_expr;
+ }
+ /* sizeof ( type-name ). */
+ skip_evaluation--;
+ in_sizeof--;
+ return c_expr_sizeof_type (type_name);
+ }
+ else
+ {
+ expr = c_parser_unary_expression (parser);
+ sizeof_expr:
+ skip_evaluation--;
+ in_sizeof--;
+ if (TREE_CODE (expr.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+ error ("%<sizeof%> applied to a bit-field");
+ return c_expr_sizeof_expr (expr);
+ }
+}
+
+/* Parse an alignof expression. */
+
+static struct c_expr
+c_parser_alignof_expression (c_parser *parser)
+{
+ struct c_expr expr;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
+ c_parser_consume_token (parser);
+ skip_evaluation++;
+ in_alignof++;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ /* Either __alignof__ ( type-name ) or __alignof__
+ unary-expression starting with a compound literal. */
+ struct c_type_name *type_name;
+ struct c_expr ret;
+ c_parser_consume_token (parser);
+ type_name = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (type_name == NULL)
+ {
+ struct c_expr ret;
+ skip_evaluation--;
+ in_alignof--;
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ {
+ expr = c_parser_postfix_expression_after_paren_type (parser,
+ type_name);
+ goto alignof_expr;
+ }
+ /* alignof ( type-name ). */
+ skip_evaluation--;
+ in_alignof--;
+ ret.value = c_alignof (groktypename (type_name));
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+ else
+ {
+ struct c_expr ret;
+ expr = c_parser_unary_expression (parser);
+ alignof_expr:
+ skip_evaluation--;
+ in_alignof--;
+ ret.value = c_alignof_expr (expr.value);
+ ret.original_code = ERROR_MARK;
+ return ret;
+ }
+}
+
+/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
+
+ postfix-expression:
+ primary-expression
+ postfix-expression [ expression ]
+ postfix-expression ( argument-expression-list[opt] )
+ postfix-expression . identifier
+ postfix-expression -> identifier
+ postfix-expression ++
+ postfix-expression --
+ ( type-name ) { initializer-list }
+ ( type-name ) { initializer-list , }
+
+ argument-expression-list:
+ argument-expression
+ argument-expression-list , argument-expression
+
+ primary-expression:
+ identifier
+ constant
+ string-literal
+ ( expression )
+
+ GNU extensions:
+
+ primary-expression:
+ __func__
+ (treated as a keyword in GNU C)
+ __FUNCTION__
+ __PRETTY_FUNCTION__
+ ( compound-statement )
+ __builtin_va_arg ( assignment-expression , type-name )
+ __builtin_offsetof ( type-name , offsetof-member-designator )
+ __builtin_choose_expr ( assignment-expression ,
+ assignment-expression ,
+ assignment-expression )
+ __builtin_types_compatible_p ( type-name , type-name )
+
+ offsetof-member-designator:
+ identifier
+ offsetof-member-designator . identifier
+ offsetof-member-designator [ expression ]
+
+ Objective-C:
+
+ primary-expression:
+ [ objc-receiver objc-message-args ]
+ @selector ( objc-selector-arg )
+ @protocol ( identifier )
+ @encode ( type-name )
+ objc-string-literal
+*/
+
+static struct c_expr
+c_parser_postfix_expression (c_parser *parser)
+{
+ struct c_expr expr, e1, e2, e3;
+ struct c_type_name *t1, *t2;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_NUMBER:
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ expr.value = c_parser_peek_token (parser)->value;
+ expr.original_code = ERROR_MARK;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_STRING:
+ case CPP_WSTRING:
+ expr.value = c_parser_peek_token (parser)->value;
+ expr.original_code = STRING_CST;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_OBJC_STRING:
+ gcc_assert (c_dialect_objc ());
+ expr.value
+ = objc_build_string_object (c_parser_peek_token (parser)->value);
+ expr.original_code = ERROR_MARK;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_NAME:
+ if (c_parser_peek_token (parser)->id_kind != C_ID_ID)
+ {
+ c_parser_error (parser, "expected expression");
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ expr.value = build_external_ref (id,
+ (c_parser_peek_token (parser)->type
+ == CPP_OPEN_PAREN));
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case CPP_OPEN_PAREN:
+ /* A parenthesized expression, statement expression or compound
+ literal. */
+ if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
+ {
+ /* A statement expression. */
+ tree stmt;
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ if (cur_stmt_list == NULL)
+ {
+ error ("braced-group within expression allowed "
+ "only inside a function");
+ parser->error = true;
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ stmt = c_begin_stmt_expr ();
+ c_parser_compound_statement_nostart (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (pedantic)
+ pedwarn ("ISO C forbids braced-groups within expressions");
+ expr.value = c_finish_stmt_expr (stmt);
+ expr.original_code = ERROR_MARK;
+ }
+ else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ /* A compound literal. ??? Can we actually get here rather
+ than going directly to
+ c_parser_postfix_expression_after_paren_type from
+ elsewhere? */
+ struct c_type_name *type_name;
+ c_parser_consume_token (parser);
+ type_name = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (type_name == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ }
+ else
+ expr = c_parser_postfix_expression_after_paren_type (parser,
+ type_name);
+ }
+ else
+ {
+ /* A parenthesized expression. */
+ c_parser_consume_token (parser);
+ expr = c_parser_expression (parser);
+ if (TREE_CODE (expr.value) == MODIFY_EXPR)
+ TREE_NO_WARNING (expr.value) = 1;
+ expr.original_code = ERROR_MARK;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ }
+ break;
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_FUNCTION_NAME:
+ case RID_PRETTY_FUNCTION_NAME:
+ case RID_C99_FUNCTION_NAME:
+ expr.value = fname_decl (c_parser_peek_token (parser)->keyword,
+ c_parser_peek_token (parser)->value);
+ expr.original_code = ERROR_MARK;
+ c_parser_consume_token (parser);
+ break;
+ case RID_VA_ARG:
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ e1 = c_parser_expr_no_commas (parser, NULL);
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ t1 = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (t1 == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ }
+ else
+ {
+ expr.value = build_va_arg (e1.value, groktypename (t1));
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case RID_OFFSETOF:
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ t1 = c_parser_type_name (parser);
+ if (t1 == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ {
+ tree type = groktypename (t1);
+ tree offsetof_ref;
+ if (type == error_mark_node)
+ offsetof_ref = error_mark_node;
+ else
+ offsetof_ref = build1 (INDIRECT_REF, type, NULL);
+ /* Parse the second argument to __builtin_offsetof. We
+ must have one identifier, and beyond that we want to
+ accept sub structure and sub array references. */
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ offsetof_ref = build_component_ref
+ (offsetof_ref, c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is (parser, CPP_DOT)
+ || c_parser_next_token_is (parser,
+ CPP_OPEN_SQUARE))
+ {
+ if (c_parser_next_token_is (parser, CPP_DOT))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser,
+ CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ offsetof_ref = build_component_ref
+ (offsetof_ref,
+ c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ tree idx;
+ c_parser_consume_token (parser);
+ idx = c_parser_expression (parser).value;
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ offsetof_ref = build_array_ref (offsetof_ref, idx);
+ }
+ }
+ }
+ else
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ expr.value = fold_offsetof (offsetof_ref);
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case RID_CHOOSE_EXPR:
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ e1 = c_parser_expr_no_commas (parser, NULL);
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ e2 = c_parser_expr_no_commas (parser, NULL);
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ e3 = c_parser_expr_no_commas (parser, NULL);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ {
+ tree c;
+
+ c = fold (e1.value);
+ STRIP_NOPS (c);
+ if (TREE_CODE (c) != INTEGER_CST)
+ error ("first argument to %<__builtin_choose_expr%> not"
+ " a constant");
+ expr = integer_zerop (c) ? e3 : e2;
+ }
+ break;
+ case RID_TYPES_COMPATIBLE_P:
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ t1 = c_parser_type_name (parser);
+ if (t1 == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ t2 = c_parser_type_name (parser);
+ if (t2 == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ {
+ tree e1, e2;
+
+ e1 = TYPE_MAIN_VARIANT (groktypename (t1));
+ e2 = TYPE_MAIN_VARIANT (groktypename (t2));
+
+ expr.value = comptypes (e1, e2)
+ ? build_int_cst (NULL_TREE, 1)
+ : build_int_cst (NULL_TREE, 0);
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case RID_AT_SELECTOR:
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ {
+ tree sel = c_parser_objc_selector_arg (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ expr.value = objc_build_selector_expr (sel);
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case RID_AT_PROTOCOL:
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ expr.value = objc_build_protocol_expr (id);
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ case RID_AT_ENCODE:
+ /* Extension to support C-structures in the archiver. */
+ gcc_assert (c_dialect_objc ());
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ t1 = c_parser_type_name (parser);
+ if (t1 == NULL)
+ {
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ {
+ tree type = groktypename (t1);
+ expr.value = objc_build_encode_expr (type);
+ expr.original_code = ERROR_MARK;
+ }
+ break;
+ default:
+ c_parser_error (parser, "expected expression");
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ break;
+ case CPP_OPEN_SQUARE:
+ if (c_dialect_objc ())
+ {
+ tree receiver, args;
+ c_parser_consume_token (parser);
+ receiver = c_parser_objc_receiver (parser);
+ args = c_parser_objc_message_args (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ expr.value = objc_build_message_expr (build_tree_list (receiver,
+ args));
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ /* Else fall through to report error. */
+ default:
+ c_parser_error (parser, "expected expression");
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ break;
+ }
+ return c_parser_postfix_expression_after_primary (parser, expr);
+}
+
+/* Parse a postfix expression after a parenthesized type name: the
+ brace-enclosed initializer of a compound literal, possibly followed
+ by some postfix operators. This is separate because it is not
+ possible to tell until after the type name whether a cast
+ expression has a cast or a compound literal, or whether the operand
+ of sizeof is a parenthesized type name or starts with a compound
+ literal. */
+
+static struct c_expr
+c_parser_postfix_expression_after_paren_type (c_parser *parser,
+ struct c_type_name *type_name)
+{
+ tree type;
+ struct c_expr init;
+ struct c_expr expr;
+ start_init (NULL_TREE, NULL, 0);
+ type = groktypename (type_name);
+ if (C_TYPE_VARIABLE_SIZE (type))
+ {
+ error ("compound literal has variable size");
+ type = error_mark_node;
+ }
+ init = c_parser_braced_init (parser, type, false);
+ finish_init ();
+ maybe_warn_string_init (type, init);
+
+ if (pedantic && !flag_isoc99)
+ pedwarn ("ISO C90 forbids compound literals");
+ expr.value = build_compound_literal (type, init.value);
+ expr.original_code = ERROR_MARK;
+ return c_parser_postfix_expression_after_primary (parser, expr);
+}
+
+/* Parse a postfix expression after the initial primary or compound
+ literal; that is, parse a series of postfix operators. */
+
+static struct c_expr
+c_parser_postfix_expression_after_primary (c_parser *parser,
+ struct c_expr expr)
+{
+ tree ident, idx, exprlist;
+ while (true)
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_SQUARE:
+ /* Array reference. */
+ c_parser_consume_token (parser);
+ idx = c_parser_expression (parser).value;
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>");
+ expr.value = build_array_ref (expr.value, idx);
+ expr.original_code = ERROR_MARK;
+ break;
+ case CPP_OPEN_PAREN:
+ /* Function call. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ exprlist = NULL_TREE;
+ else
+ exprlist = c_parser_expr_list (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ expr.value = build_function_call (expr.value, exprlist);
+ expr.original_code = ERROR_MARK;
+ break;
+ case CPP_DOT:
+ /* Structure element reference. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ ident = c_parser_peek_token (parser)->value;
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ return expr;
+ }
+ c_parser_consume_token (parser);
+ expr.value = build_component_ref (expr.value, ident);
+ expr.original_code = ERROR_MARK;
+ break;
+ case CPP_DEREF:
+ /* Structure element reference. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ ident = c_parser_peek_token (parser)->value;
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ expr.value = error_mark_node;
+ expr.original_code = ERROR_MARK;
+ return expr;
+ }
+ c_parser_consume_token (parser);
+ expr.value = build_component_ref (build_indirect_ref (expr.value,
+ "->"), ident);
+ expr.original_code = ERROR_MARK;
+ break;
+ case CPP_PLUS_PLUS:
+ /* Postincrement. */
+ c_parser_consume_token (parser);
+ expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0);
+ expr.original_code = ERROR_MARK;
+ break;
+ case CPP_MINUS_MINUS:
+ /* Postdecrement. */
+ c_parser_consume_token (parser);
+ expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0);
+ expr.original_code = ERROR_MARK;
+ break;
+ default:
+ return expr;
+ }
+ }
+}
+
+/* Parse an expression (C90 6.3.17, C99 6.5.17).
+
+ expression:
+ assignment-expression
+ expression , assignment-expression
+*/
+
+static struct c_expr
+c_parser_expression (c_parser *parser)
+{
+ struct c_expr expr;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ struct c_expr next;
+ c_parser_consume_token (parser);
+ next = c_parser_expr_no_commas (parser, NULL);
+ expr.value = build_compound_expr (expr.value, next.value);
+ expr.original_code = COMPOUND_EXPR;
+ }
+ return expr;
+}
+
+/* Parse a non-empty list of expressions.
+
+ nonempty-expr-list:
+ assignment-expression
+ nonempty-expr-list , assignment-expression
+*/
+
+static tree
+c_parser_expr_list (c_parser *parser)
+{
+ struct c_expr expr;
+ tree ret;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ ret = build_tree_list (NULL_TREE, expr.value);
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ expr = c_parser_expr_no_commas (parser, NULL);
+ ret = chainon (ret, build_tree_list (NULL_TREE, expr.value));
+ }
+ return ret;
+}
+
+
+/* Parse Objective-C-specific constructs. */
+
+/* Parse an objc-class-definition.
+
+ objc-class-definition:
+ @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
+ objc-class-instance-variables[opt] objc-methodprotolist @end
+ @implementation identifier objc-superclass[opt]
+ objc-class-instance-variables[opt]
+ @interface identifier ( identifier ) objc-protocol-refs[opt]
+ objc-methodprotolist @end
+ @implementation identifier ( identifier )
+
+ objc-superclass:
+ : identifier
+
+ "@interface identifier (" must start "@interface identifier (
+ identifier ) ...": objc-methodprotolist in the first production may
+ not start with a parenthesised identifier as a declarator of a data
+ definition with no declaration specifiers if the objc-superclass,
+ objc-protocol-refs and objc-class-instance-variables are omitted. */
+
+static void
+c_parser_objc_class_definition (c_parser *parser)
+{
+ bool iface_p;
+ tree id1;
+ tree superclass;
+ if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
+ iface_p = true;
+ else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
+ iface_p = false;
+ else
+ gcc_unreachable ();
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ return;
+ }
+ id1 = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree id2;
+ tree proto = NULL_TREE;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return;
+ }
+ id2 = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (!iface_p)
+ {
+ objc_start_category_implementation (id1, id2);
+ return;
+ }
+ if (c_parser_next_token_is (parser, CPP_LESS))
+ proto = c_parser_objc_protocol_refs (parser);
+ objc_start_category_interface (id1, id2, proto);
+ c_parser_objc_methodprotolist (parser);
+ c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+ objc_finish_interface ();
+ return;
+ }
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ return;
+ }
+ superclass = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ else
+ superclass = NULL_TREE;
+ if (iface_p)
+ {
+ tree proto = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_LESS))
+ proto = c_parser_objc_protocol_refs (parser);
+ objc_start_class_interface (id1, superclass, proto);
+ }
+ else
+ objc_start_class_implementation (id1, superclass);
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ c_parser_objc_class_instance_variables (parser);
+ if (iface_p)
+ {
+ objc_continue_interface ();
+ c_parser_objc_methodprotolist (parser);
+ c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+ objc_finish_interface ();
+ }
+ else
+ {
+ objc_continue_implementation ();
+ return;
+ }
+}
+
+/* Parse objc-class-instance-variables.
+
+ objc-class-instance-variables:
+ { objc-instance-variable-decl-list[opt] }
+
+ objc-instance-variable-decl-list:
+ objc-visibility-spec
+ objc-instance-variable-decl ;
+ ;
+ objc-instance-variable-decl-list objc-visibility-spec
+ objc-instance-variable-decl-list objc-instance-variable-decl ;
+ objc-instance-variable-decl-list ;
+
+ objc-visibility-spec:
+ @private
+ @protected
+ @public
+
+ objc-instance-variable-decl:
+ struct-declaration
+*/
+
+static void
+c_parser_objc_class_instance_variables (c_parser *parser)
+{
+ gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is_not (parser, CPP_EOF))
+ {
+ tree decls;
+ /* Parse any stray semicolon. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ if (pedantic)
+ pedwarn ("extra semicolon in struct or union specified");
+ c_parser_consume_token (parser);
+ continue;
+ }
+ /* Stop if at the end of the instance variables. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Parse any objc-visibility-spec. */
+ if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
+ {
+ c_parser_consume_token (parser);
+ objc_set_visibility (2);
+ continue;
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
+ {
+ c_parser_consume_token (parser);
+ objc_set_visibility (0);
+ continue;
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
+ {
+ c_parser_consume_token (parser);
+ objc_set_visibility (1);
+ continue;
+ }
+ /* Parse some comma-separated declarations. */
+ decls = c_parser_struct_declaration (parser);
+ {
+ /* Comma-separated instance variables are chained together in
+ reverse order; add them one by one. */
+ tree ivar = nreverse (decls);
+ for (; ivar; ivar = TREE_CHAIN (ivar))
+ objc_add_instance_variable (copy_node (ivar));
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+}
+
+/* Parse an objc-class-declaration.
+
+ objc-class-declaration:
+ @class identifier-list ;
+*/
+
+static void
+c_parser_objc_class_declaration (c_parser *parser)
+{
+ tree list = NULL_TREE;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
+ c_parser_consume_token (parser);
+ /* Any identifiers, including those declared as type names, are OK
+ here. */
+ while (true)
+ {
+ tree id;
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ id = c_parser_peek_token (parser)->value;
+ list = chainon (list, build_tree_list (NULL_TREE, id));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ objc_declare_class (list);
+}
+
+/* Parse an objc-alias-declaration.
+
+ objc-alias-declaration:
+ @compatibility_alias identifier identifier ;
+*/
+
+static void
+c_parser_objc_alias_declaration (c_parser *parser)
+{
+ tree id1, id2;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+ return;
+ }
+ id1 = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+ return;
+ }
+ id2 = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ objc_declare_alias (id1, id2);
+}
+
+/* Parse an objc-protocol-definition.
+
+ objc-protocol-definition:
+ @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
+ @protocol identifier-list ;
+
+ "@protocol identifier ;" should be resolved as "@protocol
+ identifier-list ;": objc-methodprotolist may not start with a
+ semicolon in the first alternative if objc-protocol-refs are
+ omitted. */
+
+static void
+c_parser_objc_protocol_definition (c_parser *parser)
+{
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ return;
+ }
+ if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
+ || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
+ {
+ tree list = NULL_TREE;
+ /* Any identifiers, including those declared as type names, are
+ OK here. */
+ while (true)
+ {
+ tree id;
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ id = c_parser_peek_token (parser)->value;
+ list = chainon (list, build_tree_list (NULL_TREE, id));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ objc_declare_protocols (list);
+ }
+ else
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ tree proto = NULL_TREE;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_LESS))
+ proto = c_parser_objc_protocol_refs (parser);
+ objc_pq_context = 1;
+ objc_start_protocol (id, proto);
+ c_parser_objc_methodprotolist (parser);
+ c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+ objc_pq_context = 0;
+ objc_finish_interface ();
+ }
+}
+
+/* Parse an objc-method-type.
+
+ objc-method-type:
+ +
+ -
+*/
+
+static enum tree_code
+c_parser_objc_method_type (c_parser *parser)
+{
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_PLUS:
+ c_parser_consume_token (parser);
+ return PLUS_EXPR;
+ case CPP_MINUS:
+ c_parser_consume_token (parser);
+ return MINUS_EXPR;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Parse an objc-method-definition.
+
+ objc-method-definition:
+ objc-method-type objc-method-decl ;[opt] compound-statement
+*/
+
+static void
+c_parser_objc_method_definition (c_parser *parser)
+{
+ enum tree_code type = c_parser_objc_method_type (parser);
+ tree decl;
+ objc_set_method_type (type);
+ objc_pq_context = 1;
+ decl = c_parser_objc_method_decl (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_parser_consume_token (parser);
+ if (pedantic)
+ pedwarn ("extra semicolon in method definition specified");
+ }
+ objc_pq_context = 0;
+ objc_start_method_definition (decl);
+ add_stmt (c_parser_compound_statement (parser));
+ objc_finish_method_definition (current_function_decl);
+}
+
+/* Parse an objc-methodprotolist.
+
+ objc-methodprotolist:
+ empty
+ objc-methodprotolist objc-methodproto
+ objc-methodprotolist declaration
+ objc-methodprotolist ;
+
+ The declaration is a data definition, which may be missing
+ declaration specifiers under the same rules and diagnostics as
+ other data definitions outside functions, and the stray semicolon
+ is diagnosed the same way as a stray semicolon outside a
+ function. */
+
+static void
+c_parser_objc_methodprotolist (c_parser *parser)
+{
+ while (true)
+ {
+ /* The list is terminated by @end. */
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_SEMICOLON:
+ if (pedantic)
+ pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+ c_parser_consume_token (parser);
+ break;
+ case CPP_PLUS:
+ case CPP_MINUS:
+ c_parser_objc_methodproto (parser);
+ break;
+ case CPP_EOF:
+ return;
+ default:
+ if (c_parser_next_token_is_keyword (parser, RID_AT_END))
+ return;
+ c_parser_declaration_or_fndef (parser, false, true, false, true);
+ break;
+ }
+ }
+}
+
+/* Parse an objc-methodproto.
+
+ objc-methodproto:
+ objc-method-type objc-method-decl ;
+*/
+
+static void
+c_parser_objc_methodproto (c_parser *parser)
+{
+ enum tree_code type = c_parser_objc_method_type (parser);
+ tree decl;
+ objc_set_method_type (type);
+ /* Remember protocol qualifiers in prototypes. */
+ objc_pq_context = 1;
+ decl = c_parser_objc_method_decl (parser);
+ /* Forget protocol qualifiers here. */
+ objc_pq_context = 0;
+ objc_add_method_declaration (decl);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+/* Parse an objc-method-decl.
+
+ objc-method-decl:
+ ( objc-type-name ) objc-selector
+ objc-selector
+ ( objc-type-name ) objc-keyword-selector objc-optparmlist
+ objc-keyword-selector objc-optparmlist
+
+ objc-keyword-selector:
+ objc-keyword-decl
+ objc-keyword-selector objc-keyword-decl
+
+ objc-keyword-decl:
+ objc-selector : ( objc-type-name ) identifier
+ objc-selector : identifier
+ : ( objc-type-name ) identifier
+ : identifier
+
+ objc-optparmlist:
+ objc-optparms objc-optellipsis
+
+ objc-optparms:
+ empty
+ objc-opt-parms , parameter-declaration
+
+ objc-optellipsis:
+ empty
+ , ...
+*/
+
+static tree
+c_parser_objc_method_decl (c_parser *parser)
+{
+ tree type = NULL_TREE;
+ tree sel;
+ tree parms = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ type = c_parser_objc_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ sel = c_parser_objc_selector (parser);
+ /* If there is no selector, or a colon follows, we have an
+ objc-keyword-selector. If there is a selector, and a colon does
+ not follow, that selector ends the objc-method-decl. */
+ if (!sel || c_parser_next_token_is (parser, CPP_COLON))
+ {
+ tree tsel = sel;
+ tree list = NULL_TREE;
+ bool ellipsis;
+ while (true)
+ {
+ tree atype = NULL_TREE, id, keyworddecl;
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ break;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ atype = c_parser_objc_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ }
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ return error_mark_node;
+ }
+ id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ keyworddecl = objc_build_keyword_decl (tsel, atype, id);
+ list = chainon (list, keyworddecl);
+ tsel = c_parser_objc_selector (parser);
+ if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
+ break;
+ }
+ /* Parse the optional parameter list. Optional Objective-C
+ method parameters follow the C syntax, and may include '...'
+ to denote a variable number of arguments. */
+ parms = make_node (TREE_LIST);
+ ellipsis = false;
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ struct c_parm *parm;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+ {
+ ellipsis = true;
+ c_parser_consume_token (parser);
+ break;
+ }
+ parm = c_parser_parameter_declaration (parser, NULL_TREE);
+ if (parm == NULL)
+ break;
+ parms = chainon (parms,
+ build_tree_list (NULL_TREE, grokparm (parm)));
+ }
+ TREE_OVERFLOW (parms) = ellipsis;
+ sel = list;
+ }
+ return objc_build_method_signature (type, sel, parms);
+}
+
+/* Parse an objc-type-name.
+
+ objc-type-name:
+ objc-type-qualifiers[opt] type-name
+ objc-type-qualifiers[opt]
+
+ objc-type-qualifiers:
+ objc-type-qualifier
+ objc-type-qualifiers objc-type-qualifier
+
+ objc-type-qualifier: one of
+ in out inout bycopy byref oneway
+*/
+
+static tree
+c_parser_objc_type_name (c_parser *parser)
+{
+ tree quals = NULL_TREE;
+ struct c_type_name *typename = NULL;
+ tree type = NULL_TREE;
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_KEYWORD
+ && (token->keyword == RID_IN
+ || token->keyword == RID_OUT
+ || token->keyword == RID_INOUT
+ || token->keyword == RID_BYCOPY
+ || token->keyword == RID_BYREF
+ || token->keyword == RID_ONEWAY))
+ {
+ quals = chainon (quals, build_tree_list (NULL_TREE, token->value));
+ c_parser_consume_token (parser);
+ }
+ else
+ break;
+ }
+ if (c_parser_next_token_starts_typename (parser))
+ typename = c_parser_type_name (parser);
+ if (typename)
+ type = groktypename (typename);
+ return build_tree_list (quals, type);
+}
+
+/* Parse objc-protocol-refs.
+
+ objc-protocol-refs:
+ < identifier-list >
+*/
+
+static tree
+c_parser_objc_protocol_refs (c_parser *parser)
+{
+ tree list = NULL_TREE;
+ gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
+ c_parser_consume_token (parser);
+ /* Any identifiers, including those declared as type names, are OK
+ here. */
+ while (true)
+ {
+ tree id;
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+ id = c_parser_peek_token (parser)->value;
+ list = chainon (list, build_tree_list (NULL_TREE, id));
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ c_parser_require (parser, CPP_GREATER, "expected %<>%>");
+ return list;
+}
+
+/* Parse an objc-try-catch-statement.
+
+ objc-try-catch-statement:
+ @try compound-statement objc-catch-list[opt]
+ @try compound-statement objc-catch-list[opt] @finally compound-statement
+
+ objc-catch-list:
+ @catch ( parameter-declaration ) compound-statement
+ objc-catch-list @catch ( parameter-declaration ) compound-statement
+*/
+
+static void
+c_parser_objc_try_catch_statement (c_parser *parser)
+{
+ location_t loc;
+ tree stmt;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
+ c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
+ stmt = c_parser_compound_statement (parser);
+ objc_begin_try_stmt (loc, stmt);
+ while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
+ {
+ struct c_parm *parm;
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ break;
+ parm = c_parser_parameter_declaration (parser, NULL_TREE);
+ if (parm == NULL)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ break;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ objc_begin_catch_clause (grokparm (parm));
+ if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ c_parser_compound_statement_nostart (parser);
+ objc_finish_catch_clause ();
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
+ {
+ location_t finloc;
+ tree finstmt;
+ c_parser_consume_token (parser);
+ finloc = c_parser_peek_token (parser)->location;
+ finstmt = c_parser_compound_statement (parser);
+ objc_build_finally_clause (finloc, finstmt);
+ }
+ objc_finish_try_stmt ();
+}
+
+/* Parse an objc-synchronized-statement.
+
+ objc-synchronized-statement:
+ @synchronized ( expression ) compound-statement
+*/
+
+static void
+c_parser_objc_synchronized_statement (c_parser *parser)
+{
+ location_t loc;
+ tree expr, stmt;
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
+ c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ expr = c_parser_expression (parser).value;
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ expr = error_mark_node;
+ stmt = c_parser_compound_statement (parser);
+ objc_build_synchronized (loc, expr, stmt);
+}
+
+/* Parse an objc-selector; return NULL_TREE without an error if the
+ next token is not an objc-selector.
+
+ objc-selector:
+ identifier
+ one of
+ enum struct union if else while do for switch case default
+ break continue return goto asm sizeof typeof __alignof
+ unsigned long const short volatile signed restrict _Complex
+ in out inout bycopy byref oneway int char float double void _Bool
+
+ ??? Why this selection of keywords but not, for example, storage
+ class specifiers? */
+
+static tree
+c_parser_objc_selector (c_parser *parser)
+{
+ c_token *token = c_parser_peek_token (parser);
+ tree value = token->value;
+ if (token->type == CPP_NAME)
+ {
+ c_parser_consume_token (parser);
+ return value;
+ }
+ if (token->type != CPP_KEYWORD)
+ return NULL_TREE;
+ switch (token->keyword)
+ {
+ case RID_ENUM:
+ case RID_STRUCT:
+ case RID_UNION:
+ case RID_IF:
+ case RID_ELSE:
+ case RID_WHILE:
+ case RID_DO:
+ case RID_FOR:
+ case RID_SWITCH:
+ case RID_CASE:
+ case RID_DEFAULT:
+ case RID_BREAK:
+ case RID_CONTINUE:
+ case RID_RETURN:
+ case RID_GOTO:
+ case RID_ASM:
+ case RID_SIZEOF:
+ case RID_TYPEOF:
+ case RID_ALIGNOF:
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_CONST:
+ case RID_SHORT:
+ case RID_VOLATILE:
+ case RID_SIGNED:
+ case RID_RESTRICT:
+ case RID_COMPLEX:
+ case RID_IN:
+ case RID_OUT:
+ case RID_INOUT:
+ case RID_BYCOPY:
+ case RID_BYREF:
+ case RID_ONEWAY:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_BOOL:
+ c_parser_consume_token (parser);
+ return value;
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Parse an objc-selector-arg.
+
+ objc-selector-arg:
+ objc-selector
+ objc-keywordname-list
+
+ objc-keywordname-list:
+ objc-keywordname
+ objc-keywordname-list objc-keywordname
+
+ objc-keywordname:
+ objc-selector :
+ :
+*/
+
+static tree
+c_parser_objc_selector_arg (c_parser *parser)
+{
+ tree sel = c_parser_objc_selector (parser);
+ tree list = NULL_TREE;
+ if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
+ return sel;
+ while (true)
+ {
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ return list;
+ list = chainon (list, build_tree_list (sel, NULL_TREE));
+ sel = c_parser_objc_selector (parser);
+ if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
+ break;
+ }
+ return list;
+}
+
+/* Parse an objc-receiver.
+
+ objc-receiver:
+ expression
+ class-name
+ type-name
+*/
+
+static tree
+c_parser_objc_receiver (c_parser *parser)
+{
+ if (c_parser_peek_token (parser)->type == CPP_NAME
+ && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
+ || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ return objc_get_class_reference (id);
+ }
+ return c_parser_expression (parser).value;
+}
+
+/* Parse objc-message-args.
+
+ objc-message-args:
+ objc-selector
+ objc-keywordarg-list
+
+ objc-keywordarg-list:
+ objc-keywordarg
+ objc-keywordarg-list objc-keywordarg
+
+ objc-keywordarg:
+ objc-selector : objc-keywordexpr
+ : objc-keywordexpr
+*/
+
+static tree
+c_parser_objc_message_args (c_parser *parser)
+{
+ tree sel = c_parser_objc_selector (parser);
+ tree list = NULL_TREE;
+ if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
+ return sel;
+ while (true)
+ {
+ tree keywordexpr;
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ return list;
+ keywordexpr = c_parser_objc_keywordexpr (parser);
+ list = chainon (list, build_tree_list (sel, keywordexpr));
+ sel = c_parser_objc_selector (parser);
+ if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
+ break;
+ }
+ return list;
+}
+
+/* Parse an objc-keywordexpr.
+
+ objc-keywordexpr:
+ nonempty-expr-list
+*/
+
+static tree
+c_parser_objc_keywordexpr (c_parser *parser)
+{
+ tree list = c_parser_expr_list (parser);
+ if (TREE_CHAIN (list) == NULL_TREE)
+ {
+ /* Just return the expression, remove a level of
+ indirection. */
+ return TREE_VALUE (list);
+ }
+ else
+ {
+ /* We have a comma expression, we will collapse later. */
+ return list;
+ }
+}
+
+
+/* The actual parser and external interface. ??? Does this need to be
+ garbage-collected? */
+
+static GTY (()) c_parser *the_parser;
+
+/* Parse a single source file. */
+
+void
+c_parse_file (void)
+{
+ the_parser = c_parser_new ();
+ c_parser_translation_unit (the_parser);
+ the_parser = NULL;
+}
+
+#include "gt-c-parser.h"
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 1cde482..d16d6a6 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -205,6 +205,10 @@ struct c_declspecs {
enum c_typespec_keyword typespec_word;
/* The storage class specifier, or csc_none if none. */
enum c_storage_class storage_class;
+ /* Whether any declaration specifiers have been seen at all. */
+ BOOL_BITFIELD declspecs_seen_p : 1;
+ /* Whether a type specifier has been seen. */
+ BOOL_BITFIELD type_seen_p : 1;
/* Whether something other than a storage class specifier or
attribute has been seen. This is used to warn for the
obsolescent usage of storage class specifiers other than at the
@@ -346,7 +350,7 @@ struct language_function GTY(())
};
-/* in c-parse.in */
+/* in c-parser.c */
extern void c_parse_init (void);
/* in c-aux-info.c */
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index e2872ee..096af89 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -1,6 +1,6 @@
/* -*- indented-text -*- */
/* Process source files and output type information.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -272,8 +272,6 @@ ITYPE {IWORD}({WS}{IWORD})*
^"%{" { BEGIN(in_yacc_escape); } /* } */
-^"@@".* /* Used for c-parse.in C/ObjC demarcation. */
-
{WS} { update_lineno (yytext, yyleng); }
"const"/[^[:alnum:]_] /* don't care */
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 88037f3..49e73af 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,11 @@
+2005-02-25 Joseph S. Myers <joseph@codesourcery.com>
+
+ * Make-lang.in (objc/objc-parse.o-warn, objc/objc-parse.o,
+ objc/objc-parse.c, objc/objc-parse.y): Remove
+ (OBJC_OBJS, objc.srcextra, objc.tags, objc.mostlyclean,
+ objc.distclean, objc.maintainer-clean): Update for new parser.
+ * config-lang.in (gtfiles): Update for new parser.
+
2005-01-29 Kazu Hirata <kazu@cs.umass.edu>
* lang-specs.h, objc-act.c, objc-act.h, objc-lang.c: Update
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index 08909437..56fad72 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU Objective-C
-# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004
+# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -46,11 +46,9 @@ OBJECTIVE-C objective-c: cc1obj$(exeext)
# Use maximal warnings for this front end.
objc-warn = $(STRICT_WARN)
-# Bison-1.75 output yields (harmless) -Wtraditional warnings
-objc/objc-parse.o-warn = -Wno-error
# Language-specific object files for Objective C.
-OBJC_OBJS = objc/objc-lang.o objc/objc-parse.o objc/objc-act.o
+OBJC_OBJS = objc/objc-lang.o objc/objc-act.o
cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) $(BACKEND) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
@@ -64,28 +62,13 @@ objc/objc-lang.o : objc/objc-lang.c \
$(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
c-objc-common.h objc/objc-act.h
-objc/objc-parse.o : objc/objc-parse.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
- toplev.h $(GGC_H) input.h flags.h output.h langhooks.h $(C_COMMON_H) \
- $(C_PRAGMA_H)
-
objc/objc-act.o : objc/objc-act.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) $(TM_P_H) \
$(EXPR_H) $(TARGET_H) $(C_TREE_H) diagnostic.h toplev.h flags.h \
objc/objc-act.h input.h function.h output.h debug.h langhooks.h \
$(LANGHOOKS_DEF_H) $(HASHTAB_H) c-pragma.h gt-objc-objc-act.h
-objc.srcextra: objc/objc-parse.c objc/objc-parse.y
- -cp -p $^ $(srcdir)/objc
-
-objc/objc-parse.c : objc/objc-parse.y
- -$(BISON) $(BISONFLAGS) -o $@ $<
-
-objc/objc-parse.y: c-parse.in
- echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y
- sed -e "/^@@ifc.*/,/^@@end_ifc.*/d" \
- -e "/^@@ifobjc.*/d" -e "/^@@end_ifobjc.*/d" < $< >>tmp-objc-prs.y
- $(SHELL) $(srcdir)/../move-if-change tmp-objc-prs.y $@
+objc.srcextra:
gtype-objc.h : s-gtype ; @true
gt-objc-objc-act.h : s-gtype ; @true
@@ -103,7 +86,7 @@ objc.srcinfo:
objc.srcman:
objc.tags: force
- cd $(srcdir)/objc; etags -o TAGS.sub *.y *.c *.h; \
+ cd $(srcdir)/objc; etags -o TAGS.sub *.c *.h; \
etags --include TAGS.sub --include ../TAGS.sub
lang_checks += check-objc
@@ -124,18 +107,14 @@ objc.uninstall:
# A lot of the ancillary files are deleted by the main makefile.
# We just have to delete files specific to us.
objc.mostlyclean:
- -rm -f tmp-objc-prs.y
-rm -f objc/*$(objext) objc/xforward objc/fflags
- -rm -f objc/objc-parse.y objc/objc-parse.c objc/objc-parse.output
-rm -f objc/*$(coverageexts)
objc.clean: objc.mostlyclean
-rm -rf objc-headers
objc.distclean:
-rm -f objc/Makefile objc/Make-host objc/Make-target
-rm -f objc/config.status objc/config.cache
- -rm -f objc-parse.output
objc.maintainer-clean:
- -rm -f $(srcdir)/objc/objc-parse.y $(srcdir)/objc/objc-parse.c
#
# Stage hooks:
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index 72de2ff..fbb9a6e 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU Objective-C
-# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004
+# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -37,4 +37,4 @@ target_libs=target-libobjc
# Most of the object files for cc1obj actually come from C.
lang_requires="c"
-gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parse.in \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/objc/objc-act.c"
+gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/objc/objc-act.c"
diff --git a/gcc/stub-objc.c b/gcc/stub-objc.c
index f01fd9b..8c03da2 100644
--- a/gcc/stub-objc.c
+++ b/gcc/stub-objc.c
@@ -2,7 +2,7 @@
that are called from within the C and C++ front-ends,
respectively.
Copyright (C) 1991, 1995, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -254,3 +254,47 @@ objc_is_public (tree ARG_UNUSED (expr), tree ARG_UNUSED (identifier))
{
return 1;
}
+
+tree
+objc_get_class_ivars (tree ARG_UNUSED (class_name))
+{
+ return 0;
+}
+
+tree
+objc_build_throw_stmt (tree ARG_UNUSED (throw_expr))
+{
+ return 0;
+}
+
+void
+objc_build_synchronized (location_t ARG_UNUSED (start_locus),
+ tree ARG_UNUSED (mutex), tree ARG_UNUSED (body))
+{
+}
+
+void
+objc_begin_try_stmt (location_t ARG_UNUSED (try_locus), tree ARG_UNUSED (body))
+{
+}
+
+void
+objc_begin_catch_clause (tree ARG_UNUSED (decl))
+{
+}
+
+void
+objc_finish_catch_clause (void)
+{
+}
+
+void
+objc_build_finally_clause (location_t ARG_UNUSED (finally_locus),
+ tree ARG_UNUSED (body))
+{
+}
+
+void
+objc_finish_try_stmt (void)
+{
+}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5210413..ffa4977 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-02-25 Joseph S. Myers <joseph@codesourcery.com>
+
+ * gcc.dg/cpp/separate-1.c, gcc.dg/noncompile/971104-1.c,
+ gcc.dg/noncompile/990416-1.c: Adjust expected messages for new
+ parser.
+
2005-02-25 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/20204
diff --git a/gcc/testsuite/gcc.dg/cpp/separate-1.c b/gcc/testsuite/gcc.dg/cpp/separate-1.c
index 71dcfef..8698147 100644
--- a/gcc/testsuite/gcc.dg/cpp/separate-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/separate-1.c
@@ -12,4 +12,4 @@ int FOO( /* { dg-error "parse error|syntax error|expected" "error on this line"
), bar;
int baz FOO /* { dg-error "parse error|syntax error|expected" "error on this line" } */
-; /* { dg-warning "no type or storage class" "warning on this line" } */
+;
diff --git a/gcc/testsuite/gcc.dg/noncompile/971104-1.c b/gcc/testsuite/gcc.dg/noncompile/971104-1.c
index 4b02d71..722b71c 100644
--- a/gcc/testsuite/gcc.dg/noncompile/971104-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/971104-1.c
@@ -25,5 +25,5 @@ static void up(int sem){
({ "MUTEX ", "BARB_SEM 1", "BARB_SEM 2", "CUST_SEM 1",
"CUST_SEM 2", "WAIT_SEM 1", "WAIT_SEM 2", "WAIT_SEM 3",
"WAIT_SEM 4"} /* { dg-error "parse error|syntax error|expected" } */
- [( sb.sem_num )]) );
+ [( sb.sem_num )]) ); /* { dg-error "expected" } */
}
diff --git a/gcc/testsuite/gcc.dg/noncompile/990416-1.c b/gcc/testsuite/gcc.dg/noncompile/990416-1.c
index a0e02e2..49f5569 100644
--- a/gcc/testsuite/gcc.dg/noncompile/990416-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/990416-1.c
@@ -3,7 +3,7 @@ typedef int word_type;
static void
copy_reg (unsigned int reg, frame_state *udata, /* { dg-error "parse|syntax|expected" } */
- frame_state *target_udata)
+ frame_state *target_udata) /* { dg-error "expected" } */
{
word_type *preg = get_reg_addr (reg, udata, 0); /* { dg-error "undeclared|function|without a cast" } */
word_type *ptreg = get_reg_addr (reg, target_udata, 0); /* { dg-error "undeclared|without a cast" } */