/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 88, 89, 92-98, 1999 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.
written by AT&T, but I have never seen it. */
ifobjc
-%expect 73
+%expect 74
end ifobjc
ifc
-%expect 52
+%expect 53
end ifc
%{
#include "config.h"
#include "system.h"
#include <setjmp.h>
-
#include "tree.h"
#include "input.h"
#include "c-lex.h"
%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART VA_ARG
+%token PTR_VALUE PTR_BASE PTR_EXTENT
/* Used in c-lex.c for parsing pragmas. */
%token END_OF_LINE
%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 compstmt_nostart compstmt_primary_start
/* 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 PROTO ((FILE *, int, YYSTYPE));
+extern void yyprint PARAMS ((FILE *, int, YYSTYPE));
/* Add GC roots for variables local to this file. */
void
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
}
%}
else
error ("argument of `asm' is not a constant string"); }
| extension extdef
- { pedantic = $<itype>1; }
+ { RESTORE_WARN_FLAGS ($1); }
;
datadef:
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($1); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| typed_declspecs ';'
fndef:
typed_declspecs setspecs declarator
{ if (! start_function (current_declspecs, $3,
- prefix_attributes, NULL_TREE, 0))
+ prefix_attributes, NULL_TREE))
YYERROR1;
reinit_parse_for_function (); }
old_style_parm_decls
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs declarator error
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_declarator
{ if (! start_function (current_declspecs, $3,
- prefix_attributes, NULL_TREE, 0))
+ prefix_attributes, NULL_TREE))
YYERROR1;
reinit_parse_for_function (); }
old_style_parm_decls
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_declarator error
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| setspecs notype_declarator
{ if (! start_function (NULL_TREE, $2,
- prefix_attributes, NULL_TREE, 0))
+ prefix_attributes, NULL_TREE))
YYERROR1;
reinit_parse_for_function (); }
old_style_parm_decls
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($1); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| setspecs notype_declarator error
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($1); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
;
identifier:
/* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY
{ $$ = $2;
- pedantic = $<itype>1; }
+ RESTORE_WARN_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
$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 && ! flag_isoc9x)
+ if (pedantic && ! flag_isoc99)
pedwarn ("ANSI C forbids constructor expressions");
if (TYPE_NAME (type) != 0)
{
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)
string:
STRING
| string STRING
- { $$ = chainon ($1, $2); }
+ { $$ = chainon ($1, $2);
+ifc
+ if (warn_traditional && !in_system_header)
+ warning ("Use of ANSI string concatenation");
+end ifc
+ }
;
ifobjc
typed_declspecs_no_prefix_attr setspecs initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods_no_prefix_attr setspecs notype_initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs_no_prefix_attr ';'
{ shadow_tag_warned ($1, 1);
pedwarn ("empty declaration"); }
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);
typed_declspecs setspecs initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_initdecls ';'
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs nested_function
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_nested_function
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs ';'
{ shadow_tag ($1); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| extension decl
- { pedantic = $<itype>1; }
+ { RESTORE_WARN_FLAGS ($1); }
;
/* Declspecs which contain at least one type specifier or typedef name.
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; }
;
push_function_context ();
if (! start_function (current_declspecs, $1,
- prefix_attributes, NULL_TREE, 1))
+ prefix_attributes, NULL_TREE))
{
pop_function_context ();
YYERROR1;
push_function_context ();
if (! start_function (current_declspecs, $1,
- prefix_attributes, NULL_TREE, 1))
+ prefix_attributes, NULL_TREE))
{
pop_function_context ();
YYERROR1;
ifc
| parm_declarator '[' '*' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
- if (! flag_isoc9x)
- error ("`[*]' in parameter declaration only allowed in ISO C 9x");
+ if (! flag_isoc99)
+ error ("`[*]' in parameter declaration only allowed in ISO C 99");
}
end ifc
| parm_declarator '[' expr ']' %prec '.'
ifc
| notype_declarator '[' '*' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
- if (! flag_isoc9x)
- error ("`[*]' in parameter declaration only allowed in ISO C 9x");
+ if (! flag_isoc99)
+ error ("`[*]' in parameter declaration only allowed in ISO C 99");
}
end ifc
| notype_declarator '[' expr ']' %prec '.'
| union_head identifier
{ $$ = xref_tag (UNION_TYPE, $2); }
| enum_head identifier '{'
- { $<itype>3 = suspend_momentary ();
- $$ = start_enum ($2); }
+ { $$ = start_enum ($2); }
enumlist maybecomma_warn '}' maybe_attribute
- { $$= finish_enum ($<ttype>4, nreverse ($5), chainon ($1, $8));
- resume_momentary ($<itype>3); }
+ { $$ = finish_enum ($<ttype>4, nreverse ($5),
+ chainon ($1, $8)); }
| enum_head '{'
- { $<itype>2 = suspend_momentary ();
- $$ = start_enum (NULL_TREE); }
+ { $$ = start_enum (NULL_TREE); }
enumlist maybecomma_warn '}' maybe_attribute
- { $$= finish_enum ($<ttype>3, nreverse ($4), chainon ($1, $7));
- resume_momentary ($<itype>2); }
+ { $$ = finish_enum ($<ttype>3, nreverse ($4),
+ chainon ($1, $7)); }
| enum_head identifier
{ $$ = xref_tag (ENUMERAL_TYPE, $2); }
;
maybecomma_warn:
/* empty */
| ','
- { if (pedantic && ! flag_isoc9x)
+ { if (pedantic && ! flag_isoc99)
pedwarn ("comma at end of enumerator 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 ("ANSI C doesn't support unnamed structs/unions");
+
+ $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+ current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
- | typed_typespecs
- { if (pedantic)
- pedwarn ("ANSI C forbids member declarations with no members");
- shadow_tag($1);
- $$ = NULL_TREE; }
- | nonempty_type_quals setspecs components
+ }
+ | nonempty_type_quals setspecs components
{ $$ = $3;
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| nonempty_type_quals
{ if (pedantic)
pedwarn ("ANSI C forbids member declarations with no members");
{ $$ = NULL_TREE; }
| extension component_decl
{ $$ = $2;
- pedantic = $<itype>1; }
+ RESTORE_WARN_FLAGS ($1); }
;
components:
{ emit_line_note (input_filename, lineno);
pushlevel (0);
clear_last_expr ();
- push_momentary ();
expand_start_bindings (0);
ifobjc
if (objc_method_context)
| 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 (); }
+ $$ = poplevel (1, 1, 0); }
| pushlevel maybe_label_decls error '}'
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), kept_level_p (), 0);
- $$ = poplevel (kept_level_p (), 0, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
+ $$ = poplevel (kept_level_p (), 0, 0); }
| pushlevel maybe_label_decls stmts '}'
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), kept_level_p (), 0);
- $$ = poplevel (kept_level_p (), 0, 0);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
+ $$ = poplevel (kept_level_p (), 0, 0); }
;
compstmt_primary_start:
|| TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
$1 = default_conversion ($1);
#endif
- iterator_expand ($1);
- clear_momentary (); }
+ iterator_expand ($1); }
| simple_if ELSE
{ c_expand_start_else ();
$<itype>1 = stmt_count;
{ emit_line_note (input_filename, lineno);
expand_exit_loop_if_false (NULL_PTR,
truthvalue_conversion ($3));
- expand_end_loop ();
- clear_momentary (); }
+ expand_end_loop (); }
/* This rule is needed to make sure we end every loop we start. */
| do_stmt_start error
- { expand_end_loop ();
- clear_momentary (); }
+ { expand_end_loop (); }
| FOR
'(' xexpr ';'
{ stmt_count++;
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 (); }
expand_loop_continue_here ();
if ($9)
c_expand_expr_stmt ($9);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary ();
expand_end_loop (); }
| SWITCH '(' expr ')'
{ stmt_count++;
emit_line_note ($<filename>-1, $<lineno>0);
c_expand_start_case ($3);
- /* Don't let the tree nodes for $3 be discarded by
- clear_momentary during the parsing of the next stmt. */
- push_momentary ();
position_after_white_space (); }
lineno_labeled_stmt
- { expand_end_case ($3);
- if (yychar == CONSTANT || yychar == STRING)
- pop_momentary_nofree ();
- else
- pop_momentary (); }
+ { expand_end_case ($3); }
| BREAK ';'
{ stmt_count++;
emit_line_note ($<filename>-1, $<lineno>0);
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 ();
}
*/
$4));
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs notype_declarator maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$3),
$4));
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| typed_declspecs setspecs absdcl maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$3),
$4));
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs notype_declarator maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$3),
$4));
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
| declmods setspecs absdcl maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$4));
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
- declspec_stack = TREE_CHAIN (declspec_stack);
- resume_momentary ($2); }
+ declspec_stack = TREE_CHAIN (declspec_stack); }
;
/* This is used in a function definition
extension:
EXTENSION
- { $<itype>$ = pedantic;
- pedantic = 0; }
+ { $$ = SAVE_WARN_FLAGS();
+ pedantic = 0;
+ warn_pointer_arith = 0; }
;
\f
ifobjc
{ $$ = $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 setspecs ivars
{ $$ = $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); }
| error
{ $$ = NULL_TREE; }
;
typed_declspecs setspecs myparms ';'
{ 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 ';'
| ',' ELLIPSIS
{
/* oh what a kludge! */
- $$ = (tree)1;
+ $$ = objc_ellipsis_node;
}
| ','
{