written by AT&T, but I have never seen it. */
ifobjc
-%expect 52
+%expect 66
end ifobjc
ifc
-%expect 34
+%expect 46
/* These are the 23 conflicts you should get in parse.output;
the state numbers may vary if minor changes in the grammar are made.
%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
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. */
assemble_asm ($3);
else
error ("argument of `asm' is not a constant string"); }
+ | extension extdef
+ { pedantic = $<itype>1; }
;
datadef:
\f
fndef:
typed_declspecs setspecs declarator
- { if (! start_function ($1, $3, prefix_attributes,
- NULL_TREE, 0))
+ { if (! start_function (current_declspecs, $3,
+ prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
- xdecls
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
{ finish_function (0);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary ($2); }
| declmods setspecs notype_declarator
- { if (! start_function ($1, $3, prefix_attributes,
- NULL_TREE, 0))
+ { if (! start_function (current_declspecs, $3,
+ prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
- xdecls
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
{ finish_function (0);
prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
- xdecls
+ old_style_parm_decls
{ store_parm_decls (); }
compstmt_or_error
{ finish_function (0);
| '*' 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;
+ | extension cast_expr %prec UNARY
+ { $$ = $2;
pedantic = $<itype>1; }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
$$ = build_unary_op (ADDR_EXPR, $$, 0);
} }
*/
- | SIZEOF unary_expr %prec UNARY
- { if (TREE_CODE ($2) == COMPONENT_REF
+ | sizeof unary_expr %prec UNARY
+ { skip_evaluation--;
+ if (TREE_CODE ($2) == COMPONENT_REF
&& DECL_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); }
;
+sizeof:
+ SIZEOF { skip_evaluation++; }
+ ;
+
+alignof:
+ ALIGNOF { skip_evaluation++; }
+ ;
+
cast_expr:
unary_expr
| '(' typename ')' cast_expr %prec UNARY
{ $$ = 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));
+ $<itype>2 = $1 == boolean_false_node;
+ skip_evaluation += $<itype>2; }
+ expr_no_commas
+ { skip_evaluation -= $<itype>2;
+ $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
+ | expr_no_commas OROR
+ { $1 = truthvalue_conversion (default_conversion ($1));
+ $<itype>3 = $1 == boolean_true_node;
+ skip_evaluation += $<itype>3; }
+ expr_no_commas
+ { skip_evaluation -= $<itype>3;
+ $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
+ | expr_no_commas '?'
+ { $1 = truthvalue_conversion (default_conversion ($1));
+ $<itype>3 = $1 == boolean_true_node;
+ $<itype>2 = $1 == boolean_false_node;
+ skip_evaluation += $<itype>2; }
+ expr ':'
+ { skip_evaluation += $<itype>3 - $<itype>2; }
+ expr_no_commas
+ { skip_evaluation -= $<itype>3;
+ $$ = build_conditional_expr ($1, $4, $7); }
+ | expr_no_commas '?'
+ { if (pedantic)
+ pedwarn ("ANSI 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));
+ $<itype>3 = $1 == boolean_true_node;
+ skip_evaluation += $<itype>3; }
+ ':' expr_no_commas
+ { skip_evaluation -= $<itype>3;
+ $$ = 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); }
;
end ifobjc
-xdecls:
+old_style_parm_decls:
/* empty */
| datadecls
| datadecls ELLIPSIS
| 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 ';'
+ | 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 ';'
+ | typed_declspecs_no_prefix_attr ';'
{ shadow_tag_warned ($1, 1);
pedwarn ("empty declaration"); }
- | declmods ';'
+ | declmods_no_prefix_attr ';'
{ pedwarn ("empty declaration"); }
;
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); }
;
{ shadow_tag ($1); }
| declmods ';'
{ pedwarn ("empty declaration"); }
+ | extension decl
+ { pedantic = $<itype>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));
YYERROR1;
}
reinit_parse_for_function (); }
- xdecls
+ old_style_parm_decls
{ store_parm_decls (); }
/* This used to use compstmt_or_error.
That caused a bug with input `f(g) int g {}',
YYERROR1;
}
reinit_parse_for_function (); }
- xdecls
+ old_style_parm_decls
{ store_parm_decls (); }
/* This used to use compstmt_or_error.
That caused a bug with input `f(g) int g {}',
{ $$ = 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
{ $$ = 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
{ $$ = 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
$$ = NULL_TREE; }
| error
{ $$ = NULL_TREE; }
+ | extension component_decl
+ { $$ = $2;
+ pedantic = $<itype>1; }
;
components:
{ $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
| '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
- | attributes setattrs absdcl1
- { $$ = $3; }
+ /* ??? It appears we have to support attributes here, however
+ using prefix_attributes is wrong. */
;
/* at least one statement, the first of which parses without error. */
| identifiers_or_typenames ',' identifier
{ $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
;
+
+extension:
+ EXTENSION
+ { $<itype>$ = pedantic;
+ pedantic = 0; }
+ ;
\f
ifobjc
/* Objective-C productions. */