/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+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.
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. */
+ written by AT&T, but I have never seen it. */
ifobjc
-%expect 40
+%expect 74
end ifobjc
ifc
-%expect 28
-
-/* These are the 23 conflicts you should get in parse.output;
- the state numbers may vary if minor changes in the grammar are made.
-
-State 42 contains 1 shift/reduce conflict. (Two ways to parse ATTRIBUTE.)
-State 44 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 103 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 110 contains 1 shift/reduce conflict. (Two ways to parse ATTRIBUTE.)
-State 111 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 115 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 132 contains 1 shift/reduce conflict. (See comment at component_decl.)
-State 180 contains 1 shift/reduce conflict. (Two ways to parse ATTRIBUTE.)
-State 194 contains 2 shift/reduce conflict. (Four ways to parse this.)
-State 202 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 214 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 220 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 304 contains 2 shift/reduce conflicts. (Four ways to parse this.)
-State 335 contains 2 shift/reduce conflicts. (Four ways to parse this.)
-State 347 contains 1 shift/reduce conflict. (Two ways to parse ATTRIBUTES.)
-State 352 contains 1 shift/reduce conflict. (Two ways to parse ATTRIBUTES.)
-State 383 contains 2 shift/reduce conflicts. (Four ways to parse this.)
-State 434 contains 2 shift/reduce conflicts. (Four ways to parse this.) */
-
+%expect 53
end ifc
%{
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-
#include "config.h"
+#include "system.h"
+#include <setjmp.h>
#include "tree.h"
#include "input.h"
+#include "cpplib.h"
+#include "intl.h"
+#include "timevar.h"
#include "c-lex.h"
#include "c-tree.h"
+#include "c-pragma.h"
#include "flags.h"
-
+#include "output.h"
+#include "toplev.h"
+#include "ggc.h"
+
#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
#include <locale.h>
#endif
/* Since parsers are distinct for each language, put the language string
definition here. */
ifobjc
-char *language_string = "GNU Obj-C";
+const char * const language_string = "GNU Objective-C";
end ifobjc
ifc
-char *language_string = "GNU C";
+const char * const language_string = "GNU C";
end ifc
-#ifndef errno
-extern int errno;
-#endif
-
-void yyerror ();
-
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
%start program
%union {long itype; tree ttype; enum tree_code code;
- char *filename; int lineno; }
+ const char *filename; int lineno; int ends_in_label; }
/* All identifiers that are not reserved words
and are not declared typedefs in the current block */
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL
%token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART
+%token REALPART IMAGPART VA_ARG
+%token PTR_VALUE PTR_BASE PTR_EXTENT
/* Add precedence rules to solve dangling else s/r conflict */
%nonassoc IF
%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
/* Objective-C string constants in raw form.
- yylval is an OBJC_STRING_CST node. */
+ yylval is an STRING_CST node. */
%token OBJC_STRING
%type <code> unop
+%type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
+%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
%type <ttype> typed_declspecs reserved_declspecs
%type <ttype> typed_typespecs reserved_typespecquals
%type <ttype> declmods typespec typespecqual_reserved
+%type <ttype> typed_declspecs_no_prefix_attr reserved_declspecs_no_prefix_attr
+%type <ttype> declmods_no_prefix_attr
%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
%type <ttype> init maybeasm
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word
+%type <ttype> any_word extension
-%type <ttype> compstmt
+%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
+%type <ttype> do_stmt_start poplevel
%type <ttype> declarator
%type <ttype> notype_declarator after_type_declarator
%type <ttype> structsp component_decl_list component_decl_list2
%type <ttype> component_decl components component_declarator
%type <ttype> enumlist enumerator
+%type <ttype> struct_head union_head enum_head
%type <ttype> typename absdcl absdcl1 type_quals
%type <ttype> xexpr parms parm identifiers
%type <itype> setspecs
+%type <ends_in_label> lineno_stmt_or_label lineno_stmt_or_labels stmt_or_label
+
%type <filename> save_filename
%type <lineno> save_lineno
\f
%type <ttype> keywordexpr keywordarglist keywordarg
%type <ttype> myparms myparm optparmlist reservedwords objcselectorexpr
%type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
-%type <ttype> objc_string protocolrefs identifier_list objcprotocolexpr
+%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
+
%type <ttype> CLASSNAME OBJC_STRING OBJECTNAME
end ifobjc
\f
%{
-/* Number of statements (loosely speaking) seen so far. */
+/* Number of statements (loosely speaking) and compound statements
+ seen so far. */
static int stmt_count;
-
+static int compstmt_count;
+
/* Input file and line number of the end of the body of last simple_if;
used by the stmt-rule immediately after simple_if returns. */
-static char *if_stmt_file;
+static const char *if_stmt_file;
static int if_stmt_line;
/* List of types and structure classes of the current declaration. */
-static tree current_declspecs;
+static tree current_declspecs = NULL_TREE;
static tree prefix_attributes = NULL_TREE;
/* Stack of saved values of current_declspecs and prefix_attributes. */
static tree declspec_stack;
-/* 1 if we explained undeclared var errors. */
-static int undeclared_variable_notice;
+/* For __extension__, save/restore the warning flags which are
+ controlled by __extension__. */
+#define SAVE_WARN_FLAGS() \
+ size_int (pedantic | (warn_pointer_arith << 1))
+#define RESTORE_WARN_FLAGS(tval) \
+ do { \
+ int val = tree_low_cst (tval, 0); \
+ pedantic = val & 1; \
+ warn_pointer_arith = (val >> 1) & 1; \
+ } while (0)
ifobjc
/* Objective-C specific information */
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint ();
+
+static void yyprint PARAMS ((FILE *, int, YYSTYPE));
+static void yyerror PARAMS ((const char *));
+static inline int _yylex PARAMS ((void));
+static int yylex PARAMS ((void));
+static void init_reswords PARAMS ((void));
+
+/* Add GC roots for variables local to this file. */
+void
+c_parse_init ()
+{
+ ggc_add_tree_root (&declspec_stack, 1);
+ ggc_add_tree_root (¤t_declspecs, 1);
+ ggc_add_tree_root (&prefix_attributes, 1);
+ifobjc
+ ggc_add_tree_root (&objc_interface_context, 1);
+ ggc_add_tree_root (&objc_implementation_context, 1);
+ ggc_add_tree_root (&objc_method_context, 1);
+ ggc_add_tree_root (&objc_ivar_chain, 1);
+ ggc_add_tree_root (&objc_ivar_context, 1);
+end ifobjc
+}
+
%}
\f
%%
program: /* empty */
{ if (pedantic)
- pedwarn ("ANSI C forbids an empty source file");
+ pedwarn ("ISO C forbids an empty source file");
finish_file ();
}
| extdefs
extdefs:
{$<ttype>$ = NULL_TREE; } extdef
- | extdefs {$<ttype>$ = NULL_TREE; } extdef
+ | extdefs {$<ttype>$ = NULL_TREE; ggc_collect(); } extdef
;
extdef:
assemble_asm ($3);
else
error ("argument of `asm' is not a constant string"); }
+ | extension extdef
+ { RESTORE_WARN_FLAGS ($1); }
;
datadef:
setspecs notype_initdecls ';'
{ if (pedantic)
- error ("ANSI C forbids data definition with no type or storage class");
+ error ("ISO C forbids data definition with no type or storage class");
else if (!flag_traditional)
- warning ("data definition has no type or storage class"); }
+ warning ("data definition has no type or storage class");
+
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_initdecls ';'
- {}
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs initdecls ';'
- {}
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| typed_declspecs ';'
| error '}'
| ';'
{ if (pedantic)
- pedwarn ("ANSI C does not allow extra `;' outside of a function"); }
+ pedwarn ("ISO C does not allow extra `;' outside of a function"); }
;
\f
fndef:
typed_declspecs setspecs declarator
- { if (! start_function ($1, $3, prefix_attributes, 0))
+ { if (! start_function (current_declspecs, $3,
+ prefix_attributes, NULL_TREE))
YYERROR1;
- reinit_parse_for_function (); }
- xdecls
+ }
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
- { finish_function (0); }
+ { finish_function (0);
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs declarator error
- { }
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_declarator
- { if (! start_function ($1, $3, prefix_attributes, 0))
+ { if (! start_function (current_declspecs, $3,
+ prefix_attributes, NULL_TREE))
YYERROR1;
- reinit_parse_for_function (); }
- xdecls
+ }
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
- { finish_function (0); }
+ { finish_function (0);
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_declarator error
- { }
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| setspecs notype_declarator
- { if (! start_function (NULL_TREE, $2, prefix_attributes, 0))
+ { if (! start_function (NULL_TREE, $2,
+ prefix_attributes, NULL_TREE))
YYERROR1;
- reinit_parse_for_function (); }
- xdecls
+ }
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
- { finish_function (0); }
+ { finish_function (0);
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| setspecs notype_declarator error
- { }
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
;
identifier:
| '-'
{ $$ = NEGATE_EXPR; }
| '+'
- { $$ = CONVERT_EXPR; }
+ { $$ = CONVERT_EXPR;
+ifc
+ if (warn_traditional && !in_system_header)
+ warning ("traditional C rejects the unary plus operator");
+end ifc
+ }
| PLUSPLUS
{ $$ = PREINCREMENT_EXPR; }
| MINUSMINUS
| '*' cast_expr %prec UNARY
{ $$ = build_indirect_ref ($2, "unary *"); }
/* __extension__ turns off -pedantic for following primary. */
- | EXTENSION
- { $<itype>1 = pedantic;
- pedantic = 0; }
- cast_expr %prec UNARY
- { $$ = $3;
- pedantic = $<itype>1; }
+ | extension cast_expr %prec UNARY
+ { $$ = $2;
+ RESTORE_WARN_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
| ANDAND identifier
{ tree label = lookup_label ($2);
if (pedantic)
- pedwarn ("ANSI C forbids `&&'");
+ pedwarn ("ISO C forbids `&&'");
if (label == 0)
$$ = null_pointer_node;
else
else
{
if (pedantic)
- pedwarn ("ANSI C forbids `&...'");
+ pedwarn ("ISO C forbids `&...'");
$$ = tree_last (DECL_ARGUMENTS (current_function_decl));
$$ = build_unary_op (ADDR_EXPR, $$, 0);
} }
*/
- | SIZEOF unary_expr %prec UNARY
- { if (TREE_CODE ($2) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND ($2, 1)))
+ | sizeof unary_expr %prec UNARY
+ { skip_evaluation--;
+ if (TREE_CODE ($2) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1)))
error ("`sizeof' applied to a bit-field");
$$ = c_sizeof (TREE_TYPE ($2)); }
- | SIZEOF '(' typename ')' %prec HYPERUNARY
- { $$ = c_sizeof (groktypename ($3)); }
- | ALIGNOF unary_expr %prec UNARY
- { $$ = c_alignof_expr ($2); }
- | ALIGNOF '(' typename ')' %prec HYPERUNARY
- { $$ = c_alignof (groktypename ($3)); }
+ | sizeof '(' typename ')' %prec HYPERUNARY
+ { skip_evaluation--;
+ $$ = c_sizeof (groktypename ($3)); }
+ | alignof unary_expr %prec UNARY
+ { skip_evaluation--;
+ $$ = c_alignof_expr ($2); }
+ | alignof '(' typename ')' %prec HYPERUNARY
+ { skip_evaluation--;
+ $$ = c_alignof (groktypename ($3)); }
| REALPART cast_expr %prec UNARY
{ $$ = build_unary_op (REALPART_EXPR, $2, 0); }
| IMAGPART cast_expr %prec UNARY
{ $$ = build_unary_op (IMAGPART_EXPR, $2, 0); }
+ | VA_ARG '(' expr_no_commas ',' typename ')'
+ { $$ = build_va_arg ($3, groktypename ($5)); }
+ ;
+
+sizeof:
+ SIZEOF { skip_evaluation++; }
+ ;
+
+alignof:
+ ALIGNOF { skip_evaluation++; }
;
cast_expr:
unary_expr
| '(' typename ')' cast_expr %prec UNARY
- { tree type = groktypename ($2);
+ { tree type;
+ int SAVED_warn_strict_prototypes = warn_strict_prototypes;
+ /* This avoids warnings about unprototyped casts on
+ integers. E.g. "#define SIG_DFL (void(*)())0". */
+ if (TREE_CODE ($4) == INTEGER_CST)
+ warn_strict_prototypes = 0;
+ type = groktypename ($2);
+ warn_strict_prototypes = SAVED_warn_strict_prototypes;
$$ = build_c_cast (type, $4); }
| '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0);
$2 = groktypename ($2);
really_start_incremental_init ($2); }
initlist_maybe_comma '}' %prec UNARY
- { char *name;
+ { const char *name;
tree result = pop_init_level (0);
tree type = $2;
finish_init ();
- if (pedantic)
- pedwarn ("ANSI C forbids constructor expressions");
+ if (pedantic && ! flag_isoc99)
+ pedwarn ("ISO C89 forbids constructor expressions");
if (TYPE_NAME (type) != 0)
{
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
else
name = "";
$$ = result;
- if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
+ if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
int failure = complete_array_type (type, $$, 1);
if (failure)
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
- | expr_no_commas ANDAND expr_no_commas
- { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
- | expr_no_commas OROR expr_no_commas
- { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
- | expr_no_commas '?' xexpr ':' expr_no_commas
- { $$ = build_conditional_expr ($1, $3, $5); }
+ | expr_no_commas ANDAND
+ { $1 = truthvalue_conversion (default_conversion ($1));
+ skip_evaluation += $1 == boolean_false_node; }
+ expr_no_commas
+ { skip_evaluation -= $1 == boolean_false_node;
+ $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
+ | expr_no_commas OROR
+ { $1 = truthvalue_conversion (default_conversion ($1));
+ skip_evaluation += $1 == boolean_true_node; }
+ expr_no_commas
+ { skip_evaluation -= $1 == boolean_true_node;
+ $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
+ | expr_no_commas '?'
+ { $1 = truthvalue_conversion (default_conversion ($1));
+ skip_evaluation += $1 == boolean_false_node; }
+ expr ':'
+ { skip_evaluation += (($1 == boolean_true_node)
+ - ($1 == boolean_false_node)); }
+ expr_no_commas
+ { skip_evaluation -= $1 == boolean_true_node;
+ $$ = build_conditional_expr ($1, $4, $7); }
+ | expr_no_commas '?'
+ { if (pedantic)
+ pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
+ /* Make sure first operand is calculated only once. */
+ $<ttype>2 = save_expr ($1);
+ $1 = truthvalue_conversion (default_conversion ($<ttype>2));
+ skip_evaluation += $1 == boolean_true_node; }
+ ':' expr_no_commas
+ { skip_evaluation -= $1 == boolean_true_node;
+ $$ = build_conditional_expr ($1, $<ttype>2, $5); }
| expr_no_commas '=' expr_no_commas
- { $$ = build_modify_expr ($1, NOP_EXPR, $3);
- C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+ { char class;
+ $$ = build_modify_expr ($1, NOP_EXPR, $3);
+ class = TREE_CODE_CLASS (TREE_CODE ($$));
+ if (class == 'e' || class == '1'
+ || class == '2' || class == '<')
+ C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
+ }
| expr_no_commas ASSIGN expr_no_commas
- { $$ = build_modify_expr ($1, $2, $3);
+ { char class;
+ $$ = build_modify_expr ($1, $2, $3);
/* This inhibits warnings in truthvalue_conversion. */
- C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+ class = TREE_CODE_CLASS (TREE_CODE ($$));
+ if (class == 'e' || class == '1'
+ || class == '2' || class == '<')
+ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
+ }
;
primary:
IDENTIFIER
{
- $$ = lastiddecl;
- if (!$$ || $$ == error_mark_node)
- {
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar == '(')
- {
-ifobjc
- tree decl;
-
- if (objc_receiver_context
- && ! (objc_receiver_context
- && strcmp (IDENTIFIER_POINTER ($1), "super")))
- /* we have a message to super */
- $$ = get_super_receiver ();
- else if (objc_method_context
- && (decl = is_ivar (objc_ivar_chain, $1)))
- {
- if (is_private (decl))
- $$ = error_mark_node;
- else
- $$ = build_ivar_reference ($1);
- }
- else
-end ifobjc
- {
- /* Ordinary implicit function declaration. */
- $$ = implicitly_declare ($1);
- assemble_external ($$);
- TREE_USED ($$) = 1;
- }
- }
- else if (current_function_decl == 0)
- {
- error ("`%s' undeclared here (not in a function)",
- IDENTIFIER_POINTER ($1));
- $$ = error_mark_node;
- }
- else
- {
-ifobjc
- tree decl;
-
- if (objc_receiver_context
- && ! strcmp (IDENTIFIER_POINTER ($1), "super"))
- /* we have a message to super */
- $$ = get_super_receiver ();
- else if (objc_method_context
- && (decl = is_ivar (objc_ivar_chain, $1)))
- {
- if (is_private (decl))
- $$ = error_mark_node;
- else
- $$ = build_ivar_reference ($1);
- }
- else
-end ifobjc
- {
- if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node
- || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl)
- {
- error ("`%s' undeclared (first use this function)",
- IDENTIFIER_POINTER ($1));
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
- }
- $$ = error_mark_node;
- /* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;
- IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl;
- }
- }
- }
- else if (TREE_TYPE ($$) == error_mark_node)
- $$ = error_mark_node;
- else if (C_DECL_ANTICIPATED ($$))
- {
- /* The first time we see a build-in function used,
- if it has not been declared. */
- C_DECL_ANTICIPATED ($$) = 0;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar == '(')
- {
- /* Omit the implicit declaration we
- would ordinarily do, so we don't lose
- the actual built in type.
- But print a diagnostic for the mismatch. */
-ifobjc
- if (objc_method_context
- && is_ivar (objc_ivar_chain, $1))
- error ("Instance variable `%s' implicitly declared as function",
- IDENTIFIER_POINTER (DECL_NAME ($$)));
- else
-end ifobjc
- if (TREE_CODE ($$) != FUNCTION_DECL)
- error ("`%s' implicitly declared as function",
- IDENTIFIER_POINTER (DECL_NAME ($$)));
- else if ((TYPE_MODE (TREE_TYPE (TREE_TYPE ($$)))
- != TYPE_MODE (integer_type_node))
- && (TREE_TYPE (TREE_TYPE ($$))
- != void_type_node))
- pedwarn ("type mismatch in implicit declaration for built-in function `%s'",
- IDENTIFIER_POINTER (DECL_NAME ($$)));
- /* If it really returns void, change that to int. */
- if (TREE_TYPE (TREE_TYPE ($$)) == void_type_node)
- TREE_TYPE ($$)
- = build_function_type (integer_type_node,
- TYPE_ARG_TYPES (TREE_TYPE ($$)));
- }
- else
- pedwarn ("built-in function `%s' used without declaration",
- IDENTIFIER_POINTER (DECL_NAME ($$)));
-
- /* Do what we would ordinarily do when a fn is used. */
- assemble_external ($$);
- TREE_USED ($$) = 1;
- }
- else
- {
- assemble_external ($$);
- TREE_USED ($$) = 1;
-ifobjc
- /* we have a definition - still check if iVariable */
-
- if (!objc_receiver_context
- || (objc_receiver_context
- && strcmp (IDENTIFIER_POINTER ($1), "super")))
- {
- tree decl;
-
- if (objc_method_context
- && (decl = is_ivar (objc_ivar_chain, $1)))
- {
- if (IDENTIFIER_LOCAL_VALUE ($1))
- warning ("local declaration of `%s' hides instance variable",
- IDENTIFIER_POINTER ($1));
- else
- {
- if (is_private (decl))
- $$ = error_mark_node;
- else
- $$ = build_ivar_reference ($1);
- }
- }
- }
- else /* we have a message to super */
- $$ = get_super_receiver ();
-end ifobjc
- }
-
- if (TREE_CODE ($$) == CONST_DECL)
- {
- $$ = DECL_INITIAL ($$);
- /* This is to prevent an enum whose value is 0
- from being considered a null pointer constant. */
- $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$);
- TREE_CONSTANT ($$) = 1;
- }
+ if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$ = build_external_ref ($1, yychar == '(');
}
| CONSTANT
| string
$$ = $2; }
| '(' error ')'
{ $$ = error_mark_node; }
- | '('
- { if (current_function_decl == 0)
- {
- error ("braced-group within expression allowed only inside a function");
- YYERROR;
- }
- /* We must force a BLOCK for this level
- so that, if it is not expanded later,
- there is a way to turn off the entire subtree of blocks
- that are contained in it. */
- keep_next_level ();
- push_iterator_stack ();
- push_label_level ();
- $<ttype>$ = expand_start_stmt_expr (); }
- compstmt ')'
- { tree rtl_exp;
- if (pedantic)
- pedwarn ("ANSI C forbids braced-groups within expressions");
- pop_iterator_stack ();
+ | compstmt_primary_start compstmt_nostart ')'
+ { tree saved_last_tree;
+
+ if (pedantic)
+ pedwarn ("ISO C forbids braced-groups within expressions");
pop_label_level ();
- rtl_exp = expand_end_stmt_expr ($<ttype>2);
- /* The statements have side effects, so the group does. */
- TREE_SIDE_EFFECTS (rtl_exp) = 1;
- if (TREE_CODE ($3) == BLOCK)
- {
- /* Make a BIND_EXPR for the BLOCK already made. */
- $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
- NULL_TREE, rtl_exp, $3);
- /* Remove the block from the tree at this point.
- It gets put back at the proper place
- when the BIND_EXPR is expanded. */
- delete_block ($3);
- }
- else
- $$ = $3;
+ saved_last_tree = COMPOUND_BODY ($1);
+ RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+ last_tree = saved_last_tree;
+ TREE_CHAIN (last_tree) = NULL_TREE;
+ if (!last_expr_type)
+ last_expr_type = void_type_node;
+ $$ = build1 (STMT_EXPR, last_expr_type, $1);
+ TREE_SIDE_EFFECTS ($$) = 1;
+ }
+ | compstmt_primary_start error ')'
+ {
+ pop_label_level ();
+ last_tree = COMPOUND_BODY ($1);
+ TREE_CHAIN (last_tree) = NULL_TREE;
+ $$ = error_mark_node;
}
| primary '(' exprlist ')' %prec '.'
{ $$ = build_function_call ($1, $3); }
string:
STRING
| string STRING
- { $$ = chainon ($1, $2); }
+ {
+ifc
+ static int last_lineno = 0;
+ static const char *last_input_filename = 0;
+end ifc
+ $$ = chainon ($1, $2);
+ifc
+ if (warn_traditional && !in_system_header
+ && (lineno != last_lineno || !last_input_filename ||
+ strcmp (last_input_filename, input_filename)))
+ {
+ warning ("traditional C rejects string concatenation");
+ last_lineno = lineno;
+ last_input_filename = input_filename;
+ }
+end ifc
+ }
;
ifobjc
-/* Produces an OBJC_STRING_CST with prehaps more OBJC_STRING_CSTs chained
- onto it. */
+/* Produces an STRING_CST with perhaps more STRING_CSTs chained
+ onto it, which is to be read as an ObjC string object. */
objc_string:
OBJC_STRING
| objc_string OBJC_STRING
;
end ifobjc
-xdecls:
+old_style_parm_decls:
/* empty */
| datadecls
| datadecls ELLIPSIS
/* ... is used here to indicate a varargs function. */
{ c_mark_varargs ();
if (pedantic)
- pedwarn ("ANSI C does not permit use of `varargs.h'"); }
+ pedwarn ("ISO C does not permit use of `varargs.h'"); }
;
/* The following are analogous to lineno_decl, decls and decl
| 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:
- typed_declspecs setspecs initdecls ';'
+ typed_declspecs_no_prefix_attr setspecs initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
- | declmods setspecs notype_initdecls ';'
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | declmods_no_prefix_attr setspecs notype_initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
- | typed_declspecs ';'
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | typed_declspecs_no_prefix_attr ';'
{ shadow_tag_warned ($1, 1);
pedwarn ("empty declaration"); }
- | declmods ';'
+ | declmods_no_prefix_attr ';'
{ pedwarn ("empty declaration"); }
;
Maintains a stack of outer-level values of current_declspecs,
for the sake of parm declarations nested in function declarators. */
setspecs: /* empty */
- { $$ = suspend_momentary ();
- pending_xref_error ();
+ { pending_xref_error ();
declspec_stack = tree_cons (prefix_attributes,
current_declspecs,
declspec_stack);
- current_declspecs = $<ttype>0;
- prefix_attributes = NULL_TREE; }
+ split_specs_attrs ($<ttype>0,
+ ¤t_declspecs, &prefix_attributes); }
;
+/* ??? Yuck. See after_type_declarator. */
setattrs: /* empty */
{ prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
;
typed_declspecs setspecs initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs nested_function
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_nested_function
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs ';'
{ shadow_tag ($1); }
| declmods ';'
{ pedwarn ("empty declaration"); }
+ | extension decl
+ { RESTORE_WARN_FLAGS ($1); }
;
/* 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. */
+ A typedef'd name following these is taken as a name to be declared.
+ Declspecs have a non-NULL TREE_VALUE, attributes do not. */
typed_declspecs:
typespec reserved_declspecs
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1); }
+ | reserved_declspecs attributes
+ { $$ = tree_cons ($2, NULL_TREE, $1); }
;
-/* List of just storage classes and type modifiers.
+typed_declspecs_no_prefix_attr:
+ typespec reserved_declspecs_no_prefix_attr
+ { $$ = tree_cons (NULL_TREE, $1, $2); }
+ | declmods_no_prefix_attr typespec reserved_declspecs_no_prefix_attr
+ { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
+ ;
+
+reserved_declspecs_no_prefix_attr:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | reserved_declspecs_no_prefix_attr typespecqual_reserved
+ { $$ = tree_cons (NULL_TREE, $2, $1); }
+ | reserved_declspecs_no_prefix_attr SCSPEC
+ { if (extra_warnings)
+ warning ("`%s' is not at beginning of declaration",
+ IDENTIFIER_POINTER ($2));
+ $$ = tree_cons (NULL_TREE, $2, $1); }
+ ;
+
+/* List of just storage classes, type modifiers, and prefix attributes.
A declaration can start with just this, but then it cannot be used
- to redeclare a typedef-name. */
+ to redeclare a typedef-name.
+ Declspecs have a non-NULL TREE_VALUE, attributes do not. */
declmods:
+ declmods_no_prefix_attr
+ { $$ = $1; }
+ | attributes
+ { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+ | declmods declmods_no_prefix_attr
+ { $$ = chainon ($2, $1); }
+ | declmods attributes
+ { $$ = tree_cons ($2, NULL_TREE, $1); }
+ ;
+
+declmods_no_prefix_attr:
TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
TREE_STATIC ($$) = 1; }
| SCSPEC
{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
- | declmods TYPE_QUAL
+ | declmods_no_prefix_attr TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declmods SCSPEC
+ | declmods_no_prefix_attr SCSPEC
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
{ $$ = get_static_reference ($1, $2); }
| OBJECTNAME protocolrefs
{ $$ = get_object_reference ($2); }
+
+/* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
+ - nisse@lysator.liu.se */
+ | non_empty_protocolrefs
+ { $$ = get_object_reference ($1); }
end ifobjc
| TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3); }
initdcl:
declarator maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($1, current_declspecs, 1);
- decl_attributes ($<ttype>$, $3, prefix_attributes);
+ { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+ $3, prefix_attributes);
start_init ($<ttype>$, $2, global_bindings_p ()); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
{ finish_init ();
finish_decl ($<ttype>5, $6, $2); }
| declarator maybeasm maybe_attribute
- { tree d = start_decl ($1, current_declspecs, 0);
- decl_attributes (d, $3, prefix_attributes);
+ { tree d = start_decl ($1, current_declspecs, 0,
+ $3, prefix_attributes);
finish_decl (d, NULL_TREE, $2);
}
;
notype_initdcl:
notype_declarator maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($1, current_declspecs, 1);
- decl_attributes ($<ttype>$, $3, prefix_attributes);
+ { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+ $3, prefix_attributes);
start_init ($<ttype>$, $2, global_bindings_p ()); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
decl_attributes ($<ttype>5, $3, prefix_attributes);
finish_decl ($<ttype>5, $6, $2); }
| notype_declarator maybeasm maybe_attribute
- { tree d = start_decl ($1, current_declspecs, 0);
- decl_attributes (d, $3, prefix_attributes);
+ { tree d = start_decl ($1, current_declspecs, 0,
+ $3, prefix_attributes);
finish_decl (d, NULL_TREE, $2); }
;
/* the * rules are dummies to accept the Apollo extended syntax
{ $$ = 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 '(' nonnull_exprlist ')'
+ | any_word '(' exprlist ')'
{ $$ = build_tree_list ($1, $3); }
;
init:
expr_no_commas
| '{'
- { really_start_incremental_init (NULL_TREE);
- /* Note that the call to clear_momentary
- is in process_init_element. */
- push_momentary (); }
+ { really_start_incremental_init (NULL_TREE); }
initlist_maybe_comma '}'
- { $$ = pop_init_level (0);
- if ($$ == error_mark_node
- && ! (yychar == STRING || yychar == CONSTANT))
- pop_momentary ();
- else
- pop_momentary_nofree (); }
-
+ { $$ = pop_init_level (0); }
| error
{ $$ = error_mark_node; }
;
initlist_maybe_comma:
/* empty */
{ if (pedantic)
- pedwarn ("ANSI C forbids empty initializer braces"); }
+ pedwarn ("ISO C forbids empty initializer braces"); }
| initlist1 maybecomma
;
/* `initelt' is a single element of an initializer.
It may use braces. */
initelt:
- expr_no_commas
- { process_init_element ($1); }
- | '{'
+ designator_list '=' initval
+ | designator initval
+ | identifier ':'
+ { set_init_label ($1); }
+ initval
+ | initval
+ ;
+
+initval:
+ '{'
{ push_init_level (0); }
initlist_maybe_comma '}'
{ process_init_element (pop_init_level (0)); }
+ | expr_no_commas
+ { process_init_element ($1); }
| error
+ ;
+
+designator_list:
+ designator
+ | designator_list designator
+ ;
+
+designator:
+ '.' identifier
+ { set_init_label ($2); }
/* These are for labeled elements. The syntax for an array element
initializer conflicts with the syntax for an Objective-C message,
- so don't include these productions in the Objective-C grammer. */
+ so don't include these productions in the Objective-C grammar. */
ifc
- | '[' expr_no_commas ELLIPSIS expr_no_commas ']' '='
+ | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
{ set_init_index ($2, $4); }
- initelt
- | '[' expr_no_commas ']' '='
- { set_init_index ($2, NULL_TREE); }
- initelt
| '[' expr_no_commas ']'
{ set_init_index ($2, NULL_TREE); }
- initelt
end ifc
- | identifier ':'
- { set_init_label ($1); }
- initelt
- | '.' identifier '='
- { set_init_label ($2); }
- initelt
;
\f
nested_function:
declarator
- { push_c_function_context ();
+ { if (pedantic)
+ pedwarn ("ISO C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, $1,
- prefix_attributes, 1))
+ prefix_attributes, NULL_TREE))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
- reinit_parse_for_function ();
- store_parm_decls (); }
+ }
+ old_style_parm_decls
+ { store_parm_decls (); }
/* This used to use compstmt_or_error.
That caused a bug with input `f(g) int g {}',
where the use of YYERROR1 above caused an error
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
compstmt
- { finish_function (1);
- pop_c_function_context (); }
+ { tree decl = current_function_decl;
+ finish_function (1);
+ pop_function_context ();
+ add_decl_stmt (decl); }
;
notype_nested_function:
notype_declarator
- { push_c_function_context ();
+ { if (pedantic)
+ pedwarn ("ISO C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, $1,
- prefix_attributes, 1))
+ prefix_attributes, NULL_TREE))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
- reinit_parse_for_function ();
- store_parm_decls (); }
+ }
+ old_style_parm_decls
+ { store_parm_decls (); }
/* This used to use compstmt_or_error.
That caused a bug with input `f(g) int g {}',
where the use of YYERROR1 above caused an error
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
compstmt
- { finish_function (1);
- pop_c_function_context (); }
+ { tree decl = current_function_decl;
+ finish_function (1);
+ pop_function_context ();
+ add_decl_stmt (decl); }
;
/* Any kind of declarator (thus, all declarators allowed
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| '*' type_quals after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ /* ??? Yuck. setattrs is a quick hack. We can't use
+ prefix_attributes because $1 only applies to this
+ declarator. We assume setspecs has already been done.
+ setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+ attributes could be recognized here or in `attributes'). */
| attributes setattrs after_type_declarator
{ $$ = $3; }
| TYPENAME
/* | parm_declarator '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
+ifc
+ | parm_declarator '[' '*' ']' %prec '.'
+ { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+ if (! flag_isoc99)
+ error ("`[*]' in parameter declaration only allowed in ISO C 99");
+ }
+end ifc
| parm_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| parm_declarator '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| '*' type_quals parm_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ /* ??? Yuck. setattrs is a quick hack. We can't use
+ prefix_attributes because $1 only applies to this
+ declarator. We assume setspecs has already been done.
+ setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+ attributes could be recognized here or in `attributes'). */
| attributes setattrs parm_declarator
{ $$ = $3; }
| TYPENAME
{ $$ = $2; }
| '*' type_quals notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ifc
+ | notype_declarator '[' '*' ']' %prec '.'
+ { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+ if (! flag_isoc99)
+ error ("`[*]' in parameter declaration only allowed in ISO C 99");
+ }
+end ifc
| notype_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| notype_declarator '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
+ /* ??? Yuck. setattrs is a quick hack. We can't use
+ prefix_attributes because $1 only applies to this
+ declarator. We assume setspecs has already been done.
+ setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+ attributes could be recognized here or in `attributes'). */
| attributes setattrs notype_declarator
{ $$ = $3; }
| IDENTIFIER
;
+struct_head:
+ STRUCT
+ { $$ = NULL_TREE; }
+ | STRUCT attributes
+ { $$ = $2; }
+ ;
+
+union_head:
+ UNION
+ { $$ = NULL_TREE; }
+ | UNION attributes
+ { $$ = $2; }
+ ;
+
+enum_head:
+ ENUM
+ { $$ = NULL_TREE; }
+ | ENUM attributes
+ { $$ = $2; }
+ ;
+
structsp:
- STRUCT identifier '{'
+ struct_head identifier '{'
{ $$ = start_struct (RECORD_TYPE, $2);
/* Start scope of tag before parsing components. */
}
component_decl_list '}' maybe_attribute
- { $$ = finish_struct ($<ttype>4, $5);
- decl_attributes ($$, $7, NULL_TREE);
- /* Really define the structure. */
- }
- | STRUCT '{' component_decl_list '}' maybe_attribute
+ { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+ | struct_head '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
- $3);
- decl_attributes ($$, $5, NULL_TREE);
+ $3, chainon ($1, $5));
}
- | STRUCT identifier
+ | struct_head identifier
{ $$ = xref_tag (RECORD_TYPE, $2); }
- | UNION identifier '{'
+ | union_head identifier '{'
{ $$ = start_struct (UNION_TYPE, $2); }
component_decl_list '}' maybe_attribute
- { $$ = finish_struct ($<ttype>4, $5);
- decl_attributes ($$, $7, NULL_TREE);
- }
- | UNION '{' component_decl_list '}' maybe_attribute
+ { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+ | union_head '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
- $3);
- decl_attributes ($$, $5, NULL_TREE);
+ $3, chainon ($1, $5));
}
- | UNION identifier
+ | union_head identifier
{ $$ = xref_tag (UNION_TYPE, $2); }
- | ENUM identifier '{'
- { $<itype>3 = suspend_momentary ();
- $$ = start_enum ($2); }
- enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>4, nreverse ($5));
- resume_momentary ($<itype>3); }
- | ENUM '{'
- { $<itype>2 = suspend_momentary ();
- $$ = start_enum (NULL_TREE); }
- enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>3, nreverse ($4));
- resume_momentary ($<itype>2); }
- | ENUM identifier
+ | enum_head identifier '{'
+ { $$ = start_enum ($2); }
+ enumlist maybecomma_warn '}' maybe_attribute
+ { $$ = finish_enum ($<ttype>4, nreverse ($5),
+ chainon ($1, $8)); }
+ | enum_head '{'
+ { $$ = start_enum (NULL_TREE); }
+ enumlist maybecomma_warn '}' maybe_attribute
+ { $$ = finish_enum ($<ttype>3, nreverse ($4),
+ chainon ($1, $7)); }
+ | enum_head identifier
{ $$ = xref_tag (ENUMERAL_TYPE, $2); }
;
maybecomma_warn:
/* empty */
| ','
- { if (pedantic) pedwarn ("comma at end of enumerator list"); }
+ { if (pedantic && ! flag_isoc99)
+ pedwarn ("comma at end of enumerator list"); }
;
component_decl_list:
{ $$ = $3;
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | typed_typespecs setspecs save_filename save_lineno maybe_attribute
+ {
+ /* Support for unnamed structs or unions as members of
+ structs or unions (which is [a] useful and [b] supports
+ MS P-SDK). */
+ if (pedantic)
+ pedwarn ("ISO C doesn't support unnamed structs/unions");
+
+ $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
- | typed_typespecs
- { if (pedantic)
- pedwarn ("ANSI C forbids member declarations with no members");
- shadow_tag($1);
- $$ = NULL_TREE; }
- | nonempty_type_quals setspecs components
+ }
+ | nonempty_type_quals setspecs components
{ $$ = $3;
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| nonempty_type_quals
{ if (pedantic)
- pedwarn ("ANSI C forbids member declarations with no members");
+ pedwarn ("ISO C forbids member declarations with no members");
shadow_tag($1);
$$ = NULL_TREE; }
| error
{ $$ = NULL_TREE; }
+ | extension component_decl
+ { $$ = $2;
+ RESTORE_WARN_FLAGS ($1); }
;
components:
enumlist:
enumerator
| enumlist ',' enumerator
- { $$ = chainon ($3, $1); }
+ { if ($1 == error_mark_node)
+ $$ = $1;
+ else
+ $$ = chainon ($3, $1); }
| error
{ $$ = error_mark_node; }
;
{ $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
| '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
+ /* ??? It appears we have to support attributes here, however
+ using prefix_attributes is wrong. */
| attributes setattrs absdcl1
{ $$ = $3; }
;
is actually regarded as an invalid decl and part of the decls. */
stmts:
+ lineno_stmt_or_labels
+ {
+ if (pedantic && $1)
+ pedwarn ("ISO C forbids label at end of compound statement");
+ }
+ ;
+
+lineno_stmt_or_labels:
lineno_stmt_or_label
- | stmts lineno_stmt_or_label
- | stmts errstmt
+ | lineno_stmt_or_labels lineno_stmt_or_label
+ { $$ = $2; }
+ | lineno_stmt_or_labels errstmt
+ { $$ = 0; }
;
xstmts:
;
pushlevel: /* empty */
- { emit_line_note (input_filename, lineno);
- pushlevel (0);
+ { pushlevel (0);
clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
+ add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
ifobjc
if (objc_method_context)
add_objc_decls ();
}
;
+poplevel: /* empty */
+ { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+
/* Read zero or more forward-declarations for labels
that nested functions can jump to. */
maybe_label_decls:
/* empty */
| label_decls
{ if (pedantic)
- pedwarn ("ANSI C forbids label declarations"); }
+ pedwarn ("ISO C forbids label declarations"); }
;
label_decls:
{
tree label = shadow_label (TREE_VALUE (link));
C_DECLARED_LABEL_FLAG (label) = 1;
- declare_nonlocal_label (label);
+ add_decl_stmt (label);
}
}
;
| error compstmt
;
-compstmt: '{' '}'
+compstmt_start: '{' { compstmt_count++;
+ $$ = c_begin_compound_stmt (); }
+
+compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
- | '{' pushlevel maybe_label_decls decls xstmts '}'
- { emit_line_note (input_filename, lineno);
- expand_end_bindings (getdecls (), 1, 0);
- $$ = poplevel (1, 1, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
- | '{' pushlevel maybe_label_decls error '}'
- { emit_line_note (input_filename, lineno);
- expand_end_bindings (getdecls (), kept_level_p (), 0);
- $$ = poplevel (kept_level_p (), 0, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
- | '{' pushlevel maybe_label_decls stmts '}'
- { emit_line_note (input_filename, lineno);
- expand_end_bindings (getdecls (), kept_level_p (), 0);
- $$ = poplevel (kept_level_p (), 0, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
+ | pushlevel maybe_label_decls decls xstmts '}' poplevel
+ { $$ = poplevel (1, 1, 0);
+ SCOPE_STMT_BLOCK (TREE_PURPOSE ($6))
+ = SCOPE_STMT_BLOCK (TREE_VALUE ($6))
+ = $$; }
+ | pushlevel maybe_label_decls error '}' poplevel
+ { $$ = poplevel (kept_level_p (), 0, 0);
+ SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
+ = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
+ = $$; }
+ | pushlevel maybe_label_decls stmts '}' poplevel
+ { $$ = poplevel (kept_level_p (), 0, 0);
+ SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
+ = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
+ = $$; }
+ ;
+
+compstmt_primary_start:
+ '(' '{'
+ { if (current_function_decl == 0)
+ {
+ error ("braced-group within expression allowed only inside a function");
+ YYERROR;
+ }
+ /* We must force a BLOCK for this level
+ so that, if it is not expanded later,
+ there is a way to turn off the entire subtree of blocks
+ that are contained in it. */
+ keep_next_level ();
+ push_label_level ();
+ compstmt_count++;
+ $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
+ }
+
+compstmt: compstmt_start compstmt_nostart
+ { RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+ $$ = $2; }
;
/* Value is number of statements counted as of the closeparen. */
simple_if:
if_prefix lineno_labeled_stmt
-/* Make sure expand_end_cond is run once
- for each call to expand_start_cond.
+ { c_finish_then (); }
+/* Make sure c_expand_end_cond is run once
+ for each call to c_expand_start_cond.
Otherwise a crash is likely. */
| if_prefix error
;
if_prefix:
IF '(' expr ')'
- { emit_line_note ($<filename>-1, $<lineno>0);
- expand_start_cond (truthvalue_conversion ($3), 0);
+ { c_expand_start_cond (truthvalue_conversion ($3),
+ compstmt_count);
$<itype>$ = stmt_count;
if_stmt_file = $<filename>-1;
- if_stmt_line = $<lineno>0;
- position_after_white_space (); }
+ if_stmt_line = $<lineno>0; }
;
/* This is a subroutine of stmt.
do_stmt_start:
DO
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- /* See comment in `while' alternative, above. */
- emit_nop ();
- expand_start_loop_continue_elsewhere (1);
- position_after_white_space (); }
+ compstmt_count++;
+ $<ttype>$
+ = add_stmt (build_stmt (DO_STMT, NULL_TREE,
+ NULL_TREE));
+ /* In the event that a parse error prevents
+ parsing the complete do-statement, set the
+ condition now. Otherwise, we can get crashes at
+ RTL-generation time. */
+ DO_COND ($<ttype>$) = error_mark_node; }
lineno_labeled_stmt WHILE
- { expand_loop_continue_here (); }
+ { $$ = $<ttype>2;
+ RECHAIN_STMTS ($$, DO_BODY ($$)); }
;
+/* The forced readahead in here is because we might be at the end of a
+ line, and the line and file won't be bumped until yylex absorbs the
+ first token on the next line. */
save_filename:
- { $$ = input_filename; }
+ { if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$ = input_filename; }
;
save_lineno:
- { $$ = lineno; }
+ { if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$ = lineno; }
;
lineno_labeled_stmt:
lineno_stmt_or_label:
save_filename save_lineno stmt_or_label
- { }
+ { $$ = $3; }
;
stmt_or_label:
stmt
+ { $$ = 0; }
| label
- { int next;
- position_after_white_space ();
- next = getc (finput);
- ungetc (next, finput);
- if (pedantic && next == '}')
- pedwarn ("ANSI C forbids label at end of compound statement");
- }
+ { $$ = 1; }
;
/* Parse a single real statement, not including any labels. */
stmt:
compstmt
{ stmt_count++; }
- | all_iter_stmt
| expr ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
-/* It appears that this should not be done--that a non-lvalue array
- shouldn't get an error if the value isn't used.
- Section 3.2.2.1 says that an array lvalue gets converted to a pointer
- if it appears as a top-level expression,
- but says nothing about non-lvalue arrays. */
-#if 0
- /* Call default_conversion to get an error
- on referring to a register array if pedantic. */
- if (TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
- $1 = default_conversion ($1);
-#endif
- iterator_expand ($1);
- clear_momentary (); }
+ c_expand_expr_stmt ($1); }
| simple_if ELSE
- { expand_start_else ();
- $<itype>1 = stmt_count;
- position_after_white_space (); }
+ { c_expand_start_else ();
+ $<itype>1 = stmt_count; }
lineno_labeled_stmt
- { expand_end_cond ();
+ { c_finish_else ();
+ c_expand_end_cond ();
if (extra_warnings && stmt_count == $<itype>1)
warning ("empty body in an else-statement"); }
| simple_if %prec IF
- { expand_end_cond ();
+ { c_expand_end_cond ();
/* This warning is here instead of in simple_if, because we
do not want a warning if an empty if is followed by an
else statement. Increment stmt_count so we don't
if (extra_warnings && stmt_count++ == $<itype>1)
warning_with_file_and_line (if_stmt_file, if_stmt_line,
"empty body in an if-statement"); }
-/* Make sure expand_end_cond is run once
- for each call to expand_start_cond.
+/* Make sure c_expand_end_cond is run once
+ for each call to c_expand_start_cond.
Otherwise a crash is likely. */
| simple_if ELSE error
- { expand_end_cond (); }
+ { c_expand_end_cond (); }
| WHILE
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- /* The emit_nop used to come before emit_line_note,
- but that made the nop seem like part of the preceding line.
- And that was confusing when the preceding line was
- inside of an if statement and was not really executed.
- I think it ought to work to put the nop after the line number.
- We will see. --rms, July 15, 1991. */
- emit_nop (); }
+ { stmt_count++; }
'(' expr ')'
- { /* Don't start the loop till we have succeeded
- in parsing the end test. This is to make sure
- that we end every loop we start. */
- expand_start_loop (1);
- emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (NULL_PTR,
- truthvalue_conversion ($4));
- position_after_white_space (); }
+ { $4 = truthvalue_conversion ($4);
+ $<ttype>$
+ = add_stmt (build_stmt (WHILE_STMT, $4, NULL_TREE)); }
lineno_labeled_stmt
- { expand_end_loop (); }
+ { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
- { emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (NULL_PTR,
- truthvalue_conversion ($3));
- expand_end_loop ();
- clear_momentary (); }
-/* This rule is needed to make sure we end every loop we start. */
+ { DO_COND ($1) = truthvalue_conversion ($3); }
| do_stmt_start error
- { expand_end_loop ();
- clear_momentary (); }
+ { }
| FOR
'(' xexpr ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- /* See comment in `while' alternative, above. */
- emit_nop ();
- if ($3) c_expand_expr_stmt ($3);
- /* Next step is to call expand_start_loop_continue_elsewhere,
- but wait till after we parse the entire for (...).
- Otherwise, invalid input might cause us to call that
- fn without calling expand_end_loop. */
+ $3 = build_stmt (EXPR_STMT, $3);
+ $<ttype>$ = build_stmt (FOR_STMT, $3, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ add_stmt ($<ttype>$);
}
xexpr ';'
- /* Can't emit now; wait till after expand_start_loop... */
- { $<lineno>7 = lineno;
- $<filename>$ = input_filename; }
+ { FOR_COND ($<ttype>5) = $6; }
xexpr ')'
- {
- /* Start the loop. Doing this after parsing
- all the expressions ensures we will end the loop. */
- expand_start_loop_continue_elsewhere (1);
- /* Emit the end-test, with a line number. */
- emit_line_note ($<filename>8, $<lineno>7);
- if ($6)
- expand_exit_loop_if_false (NULL_PTR,
- truthvalue_conversion ($6));
- /* Don't let the tree nodes for $9 be discarded by
- clear_momentary during the parsing of the next stmt. */
- push_momentary ();
- $<lineno>7 = lineno;
- $<filename>8 = input_filename;
- position_after_white_space (); }
+ { FOR_EXPR ($<ttype>5) = $9; }
lineno_labeled_stmt
- { /* Emit the increment expression, with a line number. */
- emit_line_note ($<filename>8, $<lineno>7);
- expand_loop_continue_here ();
- if ($9)
- c_expand_expr_stmt ($9);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary ();
- expand_end_loop (); }
+ { RECHAIN_STMTS ($<ttype>5, FOR_BODY ($<ttype>5)); }
| SWITCH '(' expr ')'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- c_expand_start_case ($3);
- /* Don't let the tree nodes for $3 be discarded by
- clear_momentary during the parsing of the next stmt. */
- push_momentary ();
- position_after_white_space (); }
+ $<ttype>$ = c_start_case ($3); }
lineno_labeled_stmt
- { expand_end_case ($3);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
+ { c_finish_case (); }
| BREAK ';'
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- if ( ! expand_exit_something ())
- error ("break statement not within loop or switch"); }
+ { stmt_count++;
+ add_stmt (build_break_stmt ()); }
| CONTINUE ';'
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- if (! expand_continue_loop (NULL_PTR))
- error ("continue statement not within a loop"); }
+ { stmt_count++;
+ add_stmt (build_continue_stmt ()); }
| RETURN ';'
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
+ { stmt_count++;
c_expand_return (NULL_TREE); }
| RETURN expr ';'
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
+ { stmt_count++;
c_expand_return ($2); }
| ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
STRIP_NOPS ($4);
if ((TREE_CODE ($4) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND ($4, 0)) == STRING_CST)
|| TREE_CODE ($4) == STRING_CST)
- expand_asm ($4);
+ {
+ if (TREE_CODE ($4) == ADDR_EXPR)
+ $4 = TREE_OPERAND ($4, 0);
+ if (TREE_CHAIN ($4))
+ $4 = combine_strings ($4);
+ add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
+ NULL_TREE, NULL_TREE, NULL_TREE));
+ }
else
error ("argument of `asm' is not a constant string"); }
/* This is the case with just output operands. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
/* This is the case with input operands as well. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
c_expand_asm_operands ($4, $6, $8, NULL_TREE,
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
c_expand_asm_operands ($4, $6, $8, $10,
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
| GOTO identifier ';'
{ tree decl;
stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
decl = lookup_label ($2);
if (decl != 0)
{
TREE_USED (decl) = 1;
- expand_goto (decl);
+ add_stmt (build_stmt (GOTO_STMT, decl));
}
}
| GOTO '*' expr ';'
- { stmt_count++;
- emit_line_note ($<filename>-1, $<lineno>0);
- expand_computed_goto (convert (ptr_type_node, $3)); }
+ { if (pedantic)
+ pedwarn ("ISO C forbids `goto *expr;'");
+ stmt_count++;
+ $3 = convert (ptr_type_node, $3);
+ add_stmt (build_stmt (GOTO_STMT, $3)); }
| ';'
;
-all_iter_stmt:
- all_iter_stmt_simple
-/* | all_iter_stmt_with_decl */
- ;
-
-all_iter_stmt_simple:
- FOR '(' primary ')'
- {
- /* The value returned by this action is */
- /* 1 if everything is OK */
- /* 0 in case of error or already bound iterator */
-
- $<itype>$ = 0;
- if (TREE_CODE ($3) != VAR_DECL)
- error ("invalid `for (ITERATOR)' syntax");
- else if (! ITERATOR_P ($3))
- error ("`%s' is not an iterator",
- IDENTIFIER_POINTER (DECL_NAME ($3)));
- else if (ITERATOR_BOUND_P ($3))
- error ("`for (%s)' inside expansion of same iterator",
- IDENTIFIER_POINTER (DECL_NAME ($3)));
- else
- {
- $<itype>$ = 1;
- iterator_for_loop_start ($3);
- }
- }
- lineno_labeled_stmt
- {
- if ($<itype>5)
- iterator_for_loop_end ($3);
- }
-
-/* This really should allow any kind of declaration,
- for generality. Fix it before turning it back on.
-
-all_iter_stmt_with_decl:
- FOR '(' ITERATOR pushlevel setspecs iterator_spec ')'
- {
-*/ /* The value returned by this action is */
- /* 1 if everything is OK */
- /* 0 in case of error or already bound iterator */
-/*
- iterator_for_loop_start ($6);
- }
- lineno_labeled_stmt
- {
- iterator_for_loop_end ($6);
- emit_line_note (input_filename, lineno);
- expand_end_bindings (getdecls (), 1, 0);
- $<ttype>$ = poplevel (1, 1, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary ();
- }
-*/
-
/* 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 ':'
- { register tree value = check_case_value ($2);
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- stmt_count++;
-
- if (value != error_mark_node)
- {
- tree duplicate;
- int success = pushcase (value, convert_and_check,
- label, &duplicate);
- if (success == 1)
- error ("case label not within a switch statement");
- else if (success == 2)
- {
- error ("duplicate case value");
- error_with_decl (duplicate, "this is the first entry for that value");
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- position_after_white_space (); }
+ { stmt_count++;
+ do_case ($2, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
- { register tree value1 = check_case_value ($2);
- register tree value2 = check_case_value ($4);
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- stmt_count++;
-
- if (value1 != error_mark_node && value2 != error_mark_node)
- {
- tree duplicate;
- int success = pushcase_range (value1, value2,
- convert_and_check, label,
- &duplicate);
- if (success == 1)
- error ("case label not within a switch statement");
- else if (success == 2)
- {
- error ("duplicate case value");
- error_with_decl (duplicate, "this is the first entry for that value");
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 4)
- warning ("empty case range");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- position_after_white_space (); }
+ { stmt_count++;
+ do_case ($2, $4); }
| DEFAULT ':'
- {
- tree duplicate;
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- int success = pushcase (NULL_TREE, 0, label, &duplicate);
+ { stmt_count++;
+ do_case (NULL_TREE, NULL_TREE); }
+ | identifier save_filename save_lineno ':' maybe_attribute
+ { tree label = define_label ($2, $3, $1);
stmt_count++;
- if (success == 1)
- error ("default label not within a switch statement");
- else if (success == 2)
+ if (label)
{
- error ("multiple default labels in one switch");
- error_with_decl (duplicate, "this is the first default label");
+ decl_attributes (label, $5, NULL_TREE);
+ add_stmt (build_stmt (LABEL_STMT, label));
}
- position_after_white_space (); }
- | identifier ':'
- { tree label = define_label (input_filename, lineno, $1);
- stmt_count++;
- emit_nop ();
- if (label)
- expand_label (label);
- position_after_white_space (); }
+ }
;
/* Either a type-qualifier or nothing. First thing in an `asm' statement. */
| parms ';'
{ tree parm;
if (pedantic)
- pedwarn ("ANSI C forbids forward parameter declarations");
+ pedwarn ("ISO C forbids forward parameter declarations");
/* Mark the forward decls as such. */
for (parm = getdecls (); parm; parm = TREE_CHAIN (parm))
TREE_ASM_WRITTEN (parm) = 1;
it caused problems with the code in expand_builtin which
tries to verify that BUILT_IN_NEXT_ARG is being used
correctly. */
- error ("ANSI C requires a named argument before `...'");
+ error ("ISO C requires a named argument before `...'");
}
| parms
{ $$ = get_parm_info (1); }
/* A single parameter declaration or parameter type name,
as found in a parmlist. */
parm:
- typed_declspecs parm_declarator
- { $$ = build_tree_list ($1, $2) ; }
- | typed_declspecs notype_declarator
- { $$ = build_tree_list ($1, $2) ; }
- | typed_declspecs absdcl
- { $$ = build_tree_list ($1, $2); }
- | declmods notype_declarator
- { $$ = build_tree_list ($1, $2) ; }
- | declmods absdcl
- { $$ = build_tree_list ($1, $2); }
+ typed_declspecs setspecs parm_declarator maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $3),
+ build_tree_list (prefix_attributes,
+ $4));
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | typed_declspecs setspecs notype_declarator maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $3),
+ build_tree_list (prefix_attributes,
+ $4));
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | typed_declspecs setspecs absdcl maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $3),
+ build_tree_list (prefix_attributes,
+ $4));
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+ | declmods setspecs notype_declarator maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $3),
+ build_tree_list (prefix_attributes,
+ $4));
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
+
+ | declmods setspecs absdcl maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $3),
+ build_tree_list (prefix_attributes,
+ $4));
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
;
/* This is used in a function definition
| identifiers_or_typenames ',' identifier
{ $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
;
+
+extension:
+ EXTENSION
+ { $$ = SAVE_WARN_FLAGS();
+ pedantic = 0;
+ warn_pointer_arith = 0; }
+ ;
\f
ifobjc
/* Objective-C productions. */
{
$$ = NULL_TREE;
}
- | ARITHCOMPARE identifier_list ARITHCOMPARE
+ | non_empty_protocolrefs
+ ;
+
+non_empty_protocolrefs:
+ ARITHCOMPARE identifier_list ARITHCOMPARE
{
if ($1 == LT_EXPR && $3 == GT_EXPR)
$$ = $2;
ivar_decl:
typed_typespecs setspecs ivars
- {
- $$ = $3;
- resume_momentary ($2);
- }
+ { $$ = $3;
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| nonempty_type_quals setspecs ivars
- {
- $$ = $3;
- resume_momentary ($2);
- }
+ { $$ = $3;
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| error
{ $$ = NULL_TREE; }
;
methodproto:
'+'
{
+ /* Remember protocol qualifiers in prototypes. */
+ remember_protocol_qualifiers ();
objc_inherit_code = CLASS_METHOD_DECL;
}
methoddecl
{
+ /* Forget protocol qualifiers here. */
+ forget_protocol_qualifiers ();
add_class_method (objc_interface_context, $3);
}
semi_or_error
| '-'
{
+ /* Remember protocol qualifiers in prototypes. */
+ remember_protocol_qualifiers ();
objc_inherit_code = INSTANCE_METHOD_DECL;
}
methoddecl
{
+ /* Forget protocol qualifiers here. */
+ forget_protocol_qualifiers ();
add_instance_method (objc_interface_context, $3);
}
semi_or_error
mydecl:
typed_declspecs setspecs myparms ';'
- { resume_momentary ($2); }
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs ';'
{ shadow_tag ($1); }
| declmods ';'
as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */
myparm:
- parm_declarator
- { $$ = build_tree_list (current_declspecs, $1) ; }
- | notype_declarator
- { $$ = build_tree_list (current_declspecs, $1) ; }
- | absdcl
- { $$ = build_tree_list (current_declspecs, $1) ; }
+ parm_declarator maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $1),
+ build_tree_list (prefix_attributes,
+ $2)); }
+ | notype_declarator maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $1),
+ build_tree_list (prefix_attributes,
+ $2)); }
+ | absdcl maybe_attribute
+ { $$ = build_tree_list (build_tree_list (current_declspecs,
+ $1),
+ build_tree_list (prefix_attributes,
+ $2)); }
;
optparmlist:
| ',' ELLIPSIS
{
/* oh what a kludge! */
- $$ = (tree)1;
+ $$ = objc_ellipsis_node;
}
| ','
{
;
reservedwords:
- ENUM { $$ = get_identifier (token_buffer); }
- | STRUCT { $$ = get_identifier (token_buffer); }
- | UNION { $$ = get_identifier (token_buffer); }
- | IF { $$ = get_identifier (token_buffer); }
- | ELSE { $$ = get_identifier (token_buffer); }
- | WHILE { $$ = get_identifier (token_buffer); }
- | DO { $$ = get_identifier (token_buffer); }
- | FOR { $$ = get_identifier (token_buffer); }
- | SWITCH { $$ = get_identifier (token_buffer); }
- | CASE { $$ = get_identifier (token_buffer); }
- | DEFAULT { $$ = get_identifier (token_buffer); }
- | BREAK { $$ = get_identifier (token_buffer); }
- | CONTINUE { $$ = get_identifier (token_buffer); }
- | RETURN { $$ = get_identifier (token_buffer); }
- | GOTO { $$ = get_identifier (token_buffer); }
- | ASM_KEYWORD { $$ = get_identifier (token_buffer); }
- | SIZEOF { $$ = get_identifier (token_buffer); }
- | TYPEOF { $$ = get_identifier (token_buffer); }
- | ALIGNOF { $$ = get_identifier (token_buffer); }
+ ENUM | STRUCT | UNION | IF | ELSE | WHILE | DO | FOR
+ | SWITCH | CASE | DEFAULT | BREAK | CONTINUE | RETURN
+ | GOTO | ASM_KEYWORD | SIZEOF | TYPEOF | ALIGNOF
| TYPESPEC | TYPE_QUAL
;
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;
+#if USE_CPPLIB
+extern cpp_reader parse_in;
+#endif
+
+/* 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_TRAD 0x01 /* not in traditional C */
+#define D_C89 0x02 /* not in C89 */
+#define D_EXT 0x04 /* GCC extension */
+#define D_EXT89 0x08 /* GCC extension incorporated in C99 */
+#define D_OBJC 0x10 /* Objective C only */
+#define D_YES 0x20 /* always starts disabled */
+
+static const struct resword reswords[] =
+{
+ { "_Complex", RID_COMPLEX, 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 },
+ { "__bounded", RID_BOUNDED, 0 },
+ { "__bounded__", RID_BOUNDED, 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 },
+ { "__imag", RID_IMAGPART, 0 },
+ { "__imag__", RID_IMAGPART, 0 },
+ { "__inline", RID_INLINE, 0 },
+ { "__inline__", RID_INLINE, 0 },
+ { "__label__", RID_LABEL, 0 },
+ { "__ptrbase", RID_PTRBASE, 0 },
+ { "__ptrbase__", RID_PTRBASE, 0 },
+ { "__ptrextent", RID_PTREXTENT, 0 },
+ { "__ptrextent__", RID_PTREXTENT, 0 },
+ { "__ptrvalue", RID_PTRVALUE, 0 },
+ { "__ptrvalue__", RID_PTRVALUE, 0 },
+ { "__real", RID_REALPART, 0 },
+ { "__real__", RID_REALPART, 0 },
+ { "__restrict", RID_RESTRICT, 0 },
+ { "__restrict__", RID_RESTRICT, 0 },
+ { "__signed", RID_SIGNED, 0 },
+ { "__signed__", RID_SIGNED, 0 },
+ { "__typeof", RID_TYPEOF, 0 },
+ { "__typeof__", RID_TYPEOF, 0 },
+ { "__unbounded", RID_UNBOUNDED, 0 },
+ { "__unbounded__", RID_UNBOUNDED, 0 },
+ { "__volatile", RID_VOLATILE, 0 },
+ { "__volatile__", RID_VOLATILE, 0 },
+ { "asm", RID_ASM, D_EXT },
+ { "auto", RID_AUTO, 0 },
+ { "break", RID_BREAK, 0 },
+ { "case", RID_CASE, 0 },
+ { "char", RID_CHAR, 0 },
+ { "const", RID_CONST, D_TRAD },
+ { "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_TRAD|D_EXT89 },
+ { "int", RID_INT, 0 },
+ { "long", RID_LONG, 0 },
+ { "register", RID_REGISTER, 0 },
+ { "restrict", RID_RESTRICT, D_TRAD|D_C89 },
+ { "return", RID_RETURN, 0 },
+ { "short", RID_SHORT, 0 },
+ { "signed", RID_SIGNED, D_TRAD },
+ { "sizeof", RID_SIZEOF, 0 },
+ { "static", RID_STATIC, 0 },
+ { "struct", RID_STRUCT, 0 },
+ { "switch", RID_SWITCH, 0 },
+ { "typedef", RID_TYPEDEF, 0 },
+ { "typeof", RID_TYPEOF, D_TRAD|D_EXT },
+ { "union", RID_UNION, 0 },
+ { "unsigned", RID_UNSIGNED, 0 },
+ { "void", RID_VOID, 0 },
+ { "volatile", RID_VOLATILE, D_TRAD },
+ { "while", RID_WHILE, 0 },
+ifobjc
+ { "@class", RID_AT_CLASS, D_OBJC },
+ { "@compatibility_alias", RID_AT_ALIAS, D_OBJC },
+ { "@defs", RID_AT_DEFS, D_OBJC },
+ { "@encode", RID_AT_ENCODE, D_OBJC },
+ { "@end", RID_AT_END, D_OBJC },
+ { "@implementation", RID_AT_IMPLEMENTATION, D_OBJC },
+ { "@interface", RID_AT_INTERFACE, D_OBJC },
+ { "@private", RID_AT_PRIVATE, D_OBJC },
+ { "@protected", RID_AT_PROTECTED, D_OBJC },
+ { "@protocol", RID_AT_PROTOCOL, D_OBJC },
+ { "@public", RID_AT_PUBLIC, D_OBJC },
+ { "@selector", RID_AT_SELECTOR, D_OBJC },
+ { "id", RID_ID, D_OBJC },
+ { "bycopy", RID_BYCOPY, D_OBJC|D_YES },
+ { "byref", RID_BYREF, D_OBJC|D_YES },
+ { "in", RID_IN, D_OBJC|D_YES },
+ { "inout", RID_INOUT, D_OBJC|D_YES },
+ { "oneway", RID_ONEWAY, D_OBJC|D_YES },
+ { "out", RID_OUT, D_OBJC|D_YES },
+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 */ SCSPEC,
+ /* 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_BOUNDED */ TYPE_QUAL,
+ /* RID_UNBOUNDED */ TYPE_QUAL,
+ /* RID_COMPLEX */ TYPESPEC,
+
+ /* C++ */
+ /* RID_FRIEND */ 0,
+ /* RID_VIRTUAL */ 0,
+ /* RID_EXPLICIT */ 0,
+ /* RID_EXPORT */ 0,
+ /* RID_MUTABLE */ 0,
+
+ /* ObjC */
+ /* RID_IN */ TYPE_QUAL,
+ /* RID_OUT */ TYPE_QUAL,
+ /* RID_INOUT */ TYPE_QUAL,
+ /* RID_BYCOPY */ TYPE_QUAL,
+ /* RID_BYREF */ TYPE_QUAL,
+ /* RID_ONEWAY */ 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_PTRBASE */ PTR_BASE,
+ /* RID_PTREXTENT */ PTR_EXTENT,
+ /* RID_PTRVALUE */ PTR_VALUE,
+
+ /* C++ */
+ /* RID_BOOL */ 0,
+ /* 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_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,
+
+ /* alternate spellings */
+ /* RID_AND */ 0,
+ /* RID_AND_EQ */ 0,
+ /* RID_NOT */ 0,
+ /* RID_NOT_EQ */ 0,
+ /* RID_OR */ 0,
+ /* RID_OR_EQ */ 0,
+ /* RID_XOR */ 0,
+ /* RID_XOR_EQ */ 0,
+ /* RID_BITAND */ 0,
+ /* RID_BITOR */ 0,
+ /* RID_COMPL */ 0,
+
+ /* Objective C */
+ /* RID_ID */ OBJECTNAME,
+ /* RID_AT_ENCODE */ ENCODE,
+ /* RID_AT_END */ END,
+ /* RID_AT_CLASS */ CLASS,
+ /* RID_AT_ALIAS */ ALIAS,
+ /* RID_AT_DEFS */ DEFS,
+ /* RID_AT_PRIVATE */ PRIVATE,
+ /* RID_AT_PROTECTED */ PROTECTED,
+ /* RID_AT_PUBLIC */ PUBLIC,
+ /* RID_AT_PROTOCOL */ PROTOCOL,
+ /* RID_AT_SELECTOR */ SELECTOR,
+ /* RID_AT_INTERFACE */ INTERFACE,
+ /* RID_AT_IMPLEMENTATION */ IMPLEMENTATION
+};
+
+static void
+init_reswords ()
+{
+ unsigned int i;
+ tree id;
+ int mask = ((doing_objc_thang ? 0 : D_OBJC)
+ | (flag_isoc99 ? 0 : D_C89)
+ | (flag_traditional ? D_TRAD : 0)
+ | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0));
+
+ /* It is not necessary to register ridpointers as a GC root, because
+ all the trees it points to are permanently interned in the
+ get_identifier hash anyway. */
+ ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+ 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;
+ ridpointers [(int) reswords[i].rid] = id;
+
+ /* Objective C does tricky things with enabling and disabling
+ keywords. So these we must not elide in the test above, but
+ wait and not mark them reserved now. */
+ if (! (reswords[i].disable & D_YES))
+ C_IS_RESERVED_WORD (id) = 1;
+ }
+}
+
+const char *
+init_parse (filename)
+ const char *filename;
+{
+ add_c_tree_codes ();
+
+ /* Make identifier nodes long enough for the language-specific slots. */
+ set_identifier_size (sizeof (struct lang_identifier));
+
+ init_reswords ();
+ init_pragma ();
+
+ return init_c_lex (filename);
+}
+
+void
+finish_parse ()
+{
+#if USE_CPPLIB
+ cpp_finish (&parse_in);
+ errorcount += parse_in.errors;
+#else
+ fclose (finput);
+#endif
+}
+
+#if USE_CPPLIB
+#define NAME(type) cpp_type2name (type)
+#else
+/* Bleah */
+#include "symcat.h"
+#define OP(e, s) s,
+#define TK(e, s) STRINGX(e),
+
+static const char *type2name[N_TTYPES] = { TTYPE_TABLE };
+#define NAME(type) type2name[type]
+#endif
+
+static void
+yyerror (msgid)
+ const char *msgid;
+{
+ const char *string = _(msgid);
+
+ if (last_token == CPP_EOF)
+ error ("%s at end of input", string);
+ else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
+ {
+ unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
+ const char *ell = (last_token == CPP_CHAR) ? "" : "L";
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ error ("%s before %s'%c'", string, ell, val);
+ else
+ error ("%s before %s'\\x%x'", string, ell, val);
+ }
+ else if (last_token == CPP_STRING
+ || last_token == CPP_WSTRING
+ || last_token == CPP_OSTRING)
+ error ("%s before string constant", string);
+ else if (last_token == CPP_NUMBER
+ || last_token == CPP_INT
+ || last_token == CPP_FLOAT)
+ error ("%s before numeric constant", string);
+ else if (last_token == CPP_NAME)
+ error ("%s before \"%s\"", string, IDENTIFIER_POINTER (yylval.ttype));
+ else
+ error ("%s before '%s' token", string, NAME(last_token));
+}
+
+static inline int
+_yylex ()
+{
+ retry:
+ 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_COLON: return ':';
+ case CPP_COMMA: return ',';
+ case CPP_OPEN_PAREN: return '(';
+ case CPP_CLOSE_PAREN: return ')';
+ case CPP_EQ_EQ: yylval.code = EQ_EXPR; return EQCOMPARE;
+ case CPP_NOT_EQ: yylval.code = NE_EXPR; return EQCOMPARE;
+ case CPP_GREATER_EQ:yylval.code = GE_EXPR; return ARITHCOMPARE;
+ 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_SEMICOLON: 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 '.';
+
+ case CPP_EOF:
+#if USE_CPPLIB
+ cpp_pop_buffer (&parse_in);
+ if (! CPP_BUFFER (&parse_in))
+#endif
+ return 0;
+ goto retry;
+
+ case CPP_NAME:
+ if (C_IS_RESERVED_WORD (yylval.ttype))
+ {
+ enum rid rid_code = C_RID_CODE (yylval.ttype);
+ /* Return the canonical spelling for this keyword. */
+ yylval.ttype = ridpointers[(int) rid_code];
+ return rid_to_yy[(int) rid_code];
+ }
+
+ if (IDENTIFIER_POINTER (yylval.ttype)[0] == '@')
+ {
+ error ("invalid identifier `%s'", IDENTIFIER_POINTER (yylval.ttype));
+ return IDENTIFIER;
+ }
+
+ {
+ tree decl;
+
+ decl = lookup_name (yylval.ttype);
+
+ if (decl)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return TYPENAME;
+ /* A user-invisible read-only initialized variable
+ should be replaced by its value.
+ We handle only strings since that's the only case used in C. */
+ else if (TREE_CODE (decl) == VAR_DECL
+ && DECL_IGNORED_P (decl)
+ && TREE_READONLY (decl)
+ && DECL_INITIAL (decl) != 0
+ && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+ {
+ tree stringval = DECL_INITIAL (decl);
+
+ /* Copy the string value so that we won't clobber anything
+ if we put something in the TREE_CHAIN of this one. */
+ yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
+ TREE_STRING_POINTER (stringval));
+ return STRING;
+ }
+ }
+ else if (doing_objc_thang)
+ {
+ tree objc_interface_decl = is_class_name (yylval.ttype);
+
+ if (objc_interface_decl)
+ {
+ yylval.ttype = objc_interface_decl;
+ return CLASSNAME;
+ }
+ }
+
+ return IDENTIFIER;
+ }
+
+ case CPP_INT:
+ case CPP_FLOAT:
+ case CPP_NUMBER:
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ return CONSTANT;
+
+ case CPP_STRING:
+ case CPP_WSTRING:
+ return STRING;
+
+ case CPP_OSTRING:
+ 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 before '%s' token", NAME(last_token));
+ goto retry;
+
+ default:
+ abort ();
+ }
+
+ /* NOTREACHED */
+}
+
+static int
+yylex()
+{
+ int r;
+ timevar_push (TV_LEX);
+ r = _yylex();
+ timevar_pop (TV_LEX);
+ return r;
+}
+
+/* Sets the value of the 'yydebug' variable to VALUE.
+ This is a function so we don't have to have YYDEBUG defined
+ in order to build the compiler. */
+
+void
+set_yydebug (value)
+ int value;
+{
+#if YYDEBUG != 0
+ yydebug = value;
+#else
+ warning ("YYDEBUG not defined.");
+#endif
+}
+
+/* Function used when yydebug is set, to print a token in more detail. */
+
+static void
+yyprint (file, yychar, yyl)
+ FILE *file;
+ int yychar;
+ YYSTYPE yyl;
+{
+ tree t = yyl.ttype;
+
+ fprintf (file, " [%s]", NAME(last_token));
+
+ switch (yychar)
+ {
+ case IDENTIFIER:
+ case TYPENAME:
+ case OBJECTNAME:
+ case TYPESPEC:
+ case TYPE_QUAL:
+ case SCSPEC:
+ 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)
+ fprintf (file,
+#if HOST_BITS_PER_WIDE_INT == 64
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ " 0x%x%016x",
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ " 0x%lx%016lx",
+#else
+ " 0x%llx%016llx",
+#endif
+#endif
+#else
+#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+ " 0x%lx%08lx",
+#else
+ " 0x%x%08x",
+#endif
+#endif
+ TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+ break;
+ }
+}
+\f
+/* This is not the ideal place to put these, but we have to get them out
+ of c-lex.c because cp/lex.c has its own versions. */
+
+/* Return something to represent absolute declarators containing a *.
+ TARGET is the absolute declarator that the * contains.
+ TYPE_QUALS is a list of modifiers such as const or volatile
+ to apply to the pointer type, represented as identifiers.
+
+ We return an INDIRECT_REF whose "contents" are TARGET
+ and whose type is the modifier list. */
+
+tree
+make_pointer_declarator (type_quals, target)
+ tree type_quals, target;
+{
+ return build1 (INDIRECT_REF, type_quals, target);
+}