/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
02111-1307, USA. */
/* This file defines the grammar of C and that of Objective C.
- ifobjc ... end ifobjc conditionals contain code for Objective C only.
- ifc ... end ifc conditionals contain code for C only.
+ @@ifobjc ... @@end_ifobjc conditionals contain code for Objective C only.
+ @@ifc ... @@end_ifc conditionals contain code for C only.
Sed commands in Makefile.in are used to convert this file into
c-parse.y and into objc-parse.y. */
/* To whomever it may concern: I have heard that such a thing was once
written by AT&T, but I have never seen it. */
-ifc
+@@ifc
%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
-end ifc
+@@end_ifc
%{
#include "config.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "langhooks.h"
#include "input.h"
#include "cpplib.h"
#include "intl.h"
#include "toplev.h"
#include "ggc.h"
-ifobjc
+@@ifobjc
#include "objc-act.h"
-end ifobjc
+@@end_ifobjc
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
%token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
%token PTR_VALUE PTR_BASE PTR_EXTENT
-%token FUNC_NAME
+%token FUNC_NAME OFFSETOF
/* Add precedence rules to solve dangling else s/r conflict */
%nonassoc IF
Objective C, so that the token codes are the same in both. */
%token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE
%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
+%token AT_THROW AT_TRY AT_CATCH AT_FINALLY AT_SYNCHRONIZED
%token OBJC_STRING
%type <code> unop
%type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
+%type <ttype> offsetof_member_designator
-%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
-%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
-%type <ttype> init maybeasm
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
+%type <ttype> initdecls notype_initdecls initdcl notype_initdcl init
+%type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word extension
+%type <ttype> any_word
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
-%type <ttype> do_stmt_start poplevel stmt label
+%type <ttype> do_stmt_start pop_scope stmt label
%type <ttype> c99_block_start c99_block_end
%type <ttype> declarator
%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
%type <ttype> identifiers_or_typenames
-%type <itype> setspecs setspecs_fp
+%type <itype> setspecs setspecs_fp extension
%type <location> save_location
\f
-ifobjc
+@@ifobjc
/* the Objective-C nonterminals */
%type <ttype> ivar_decl_list ivar_decls ivar_decl ivars ivar_declarator
%type <ttype> non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
%type <ttype> CLASSNAME OBJECTNAME OBJC_STRING
-end ifobjc
+
+%type <ttype> superclass
+%type <itype> objc_try_catch_stmt objc_finally_block
+@@end_ifobjc
\f
%{
/* Number of statements (loosely speaking) and compound statements
/* For __extension__, save/restore the warning flags which are
controlled by __extension__. */
-#define SAVE_EXT_FLAGS() \
- size_int (pedantic \
- | (warn_pointer_arith << 1) \
- | (warn_traditional << 2) \
- | (flag_iso << 3))
+#define SAVE_EXT_FLAGS() \
+ (pedantic \
+ | (warn_pointer_arith << 1) \
+ | (warn_traditional << 2) \
+ | (flag_iso << 3))
-#define RESTORE_EXT_FLAGS(tval) \
+#define RESTORE_EXT_FLAGS(val) \
do { \
- int val = tree_low_cst (tval, 0); \
pedantic = val & 1; \
warn_pointer_arith = (val >> 1) & 1; \
warn_traditional = (val >> 2) & 1; \
flag_iso = (val >> 3) & 1; \
} while (0)
-ifobjc
+@@ifobjc
/* Objective-C specific parser/lexer information */
static enum tree_code objc_inherit_code;
exists. */
static int objc_need_raw_identifier;
#define OBJC_NEED_RAW_IDENTIFIER(VAL) objc_need_raw_identifier = VAL
-end ifobjc
+@@end_ifobjc
-ifc
+@@ifc
#define OBJC_NEED_RAW_IDENTIFIER(VAL) /* nothing */
-end ifc
-
-static bool parsing_iso_function_signature;
+@@end_ifc
/* Tell yyparse how to print a token's value, if yydebug is set. */
;
extdef:
- extdef_1
- { parsing_iso_function_signature = false; } /* Reset after any external definition. */
- ;
-
-extdef_1:
fndef
| datadef
-ifobjc
- | objcdef
-end ifobjc
- | ASM_KEYWORD '(' expr ')' ';'
- { STRIP_NOPS ($3);
- if ((TREE_CODE ($3) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND ($3, 0)) == STRING_CST)
- || TREE_CODE ($3) == STRING_CST)
- assemble_asm ($3);
- else
- error ("argument of `asm' is not a constant string"); }
+ | asmdef
| extension extdef
{ RESTORE_EXT_FLAGS ($1); }
+@@ifobjc
+ | objcdef
+@@end_ifobjc
;
datadef:
identifier:
IDENTIFIER
| TYPENAME
-ifobjc
+@@ifobjc
| OBJECTNAME
| CLASSNAME
-end ifobjc
+@@end_ifobjc
;
unop: '&'
{ $$ = NEGATE_EXPR; }
| '+'
{ $$ = CONVERT_EXPR;
-ifc
+@@ifc
if (warn_traditional && !in_system_header)
warning ("traditional C rejects the unary plus operator");
-end ifc
+@@end_ifc
}
| PLUSPLUS
{ $$ = PREINCREMENT_EXPR; }
| expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas ANDAND
- { $1 = c_common_truthvalue_conversion
+ { $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_false_node; }
expr_no_commas
{ skip_evaluation -= $1 == truthvalue_false_node;
$$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
| expr_no_commas OROR
- { $1 = c_common_truthvalue_conversion
+ { $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_true_node; }
expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node;
$$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
| expr_no_commas '?'
- { $1 = c_common_truthvalue_conversion
+ { $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_false_node; }
expr ':'
{ 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 = c_common_truthvalue_conversion
- (default_conversion ($<ttype>2));
+ $<ttype>2 = save_expr (default_conversion ($1));
+ $1 = lang_hooks.truthvalue_conversion ($<ttype>2);
skip_evaluation += $1 == truthvalue_true_node; }
':' expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node;
finish_init ();
if (pedantic && ! flag_isoc99)
- pedwarn ("ISO C89 forbids compound literals");
+ pedwarn ("ISO C90 forbids compound literals");
$$ = build_compound_literal (type, constructor);
}
| '(' expr ')'
last_expr_type = void_type_node;
$$ = build1 (STMT_EXPR, last_expr_type, $1);
TREE_SIDE_EFFECTS ($$) = 1;
+ annotate_with_locus ($$, input_location);
}
| compstmt_primary_start error ')'
{
| VA_ARG '(' expr_no_commas ',' typename ')'
{ $$ = build_va_arg ($3, groktypename ($5)); }
- | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')'
+ | OFFSETOF '(' typename ',' offsetof_member_designator ')'
+ { $$ = build_offsetof (groktypename ($3), $5); }
+ | OFFSETOF '(' error ')'
+ { $$ = error_mark_node; }
+ | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
+ expr_no_commas ')'
{
tree c;
c = fold ($3);
STRIP_NOPS (c);
if (TREE_CODE (c) != INTEGER_CST)
- error ("first argument to __builtin_choose_expr not a constant");
+ error ("first argument to __builtin_choose_expr not"
+ " a constant");
$$ = integer_zerop (c) ? $7 : $5;
}
- | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
+ | CHOOSE_EXPR '(' error ')'
+ { $$ = error_mark_node; }
+ | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
{
tree e1, e2;
$$ = comptypes (e1, e2, COMPARE_STRICT)
? build_int_2 (1, 0) : build_int_2 (0, 0);
}
+ | TYPES_COMPATIBLE_P '(' error ')'
+ { $$ = error_mark_node; }
| primary '[' expr ']' %prec '.'
{ $$ = build_array_ref ($1, $3); }
| primary '.' identifier
- {
-ifobjc
- if (!is_public ($1, $3))
- $$ = error_mark_node;
- else
-end ifobjc
- $$ = build_component_ref ($1, $3);
- }
+ { $$ = build_component_ref ($1, $3); }
| primary POINTSAT identifier
{
tree expr = build_indirect_ref ($1, "->");
-
-ifobjc
- if (!is_public (expr, $3))
- $$ = error_mark_node;
- else
-end ifobjc
- $$ = build_component_ref (expr, $3);
+ $$ = build_component_ref (expr, $3);
}
| primary PLUSPLUS
{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
| primary MINUSMINUS
{ $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
-ifobjc
+@@ifobjc
| objcmessageexpr
{ $$ = build_message_expr ($1); }
| objcselectorexpr
{ $$ = build_encode_expr ($1); }
| OBJC_STRING
{ $$ = build_objc_string_object ($1); }
-end ifobjc
+@@end_ifobjc
;
-old_style_parm_decls:
- old_style_parm_decls_1
- {
- parsing_iso_function_signature = false; /* Reset after decls. */
- }
+/* This is the second argument to __builtin_offsetof. We must have one
+ identifier, and beyond that we want to accept sub structure and sub
+ array references. We return tree list where each element has
+ PURPOSE set for component refs or VALUE set for array refs. We'll
+ turn this into something real inside build_offsetof. */
+
+offsetof_member_designator:
+ identifier
+ { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+ | offsetof_member_designator '.' identifier
+ { $$ = tree_cons ($3, NULL_TREE, $1); }
+ | offsetof_member_designator '[' expr ']'
+ { $$ = tree_cons (NULL_TREE, $3, $1); }
;
-old_style_parm_decls_1:
+old_style_parm_decls:
/* empty */
- {
- if (warn_traditional && !in_system_header
- && parsing_iso_function_signature)
- warning ("traditional C rejects ISO C style function definitions");
- if (warn_old_style_definition && !in_system_header
- && !parsing_iso_function_signature)
- warning ("old-style parameter declaration");
- parsing_iso_function_signature = false; /* Reset after warning. */
- }
| datadecls
- {
- if (warn_old_style_definition && !in_system_header)
- warning ("old-style parameter declaration");
- }
;
/* The following are analogous to lineno_decl, decls and decl
{ /* For a typedef name, record the meaning, not the name.
In case of `foo foo, bar;'. */
$$ = lookup_name ($1); }
-ifobjc
+@@ifobjc
| CLASSNAME protocolrefs
{ $$ = get_static_reference ($1, $2); }
| OBJECTNAME protocolrefs
- nisse@lysator.liu.se */
| non_empty_protocolrefs
{ $$ = get_object_reference ($1); }
-end ifobjc
+@@end_ifobjc
| typeof '(' expr ')'
- { skip_evaluation--; $$ = TREE_TYPE ($3); }
+ { skip_evaluation--;
+ if (TREE_CODE ($3) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND ($3, 1)))
+ error ("`typeof' applied to a bit-field");
+ $$ = TREE_TYPE ($3); }
| typeof '(' typename ')'
{ skip_evaluation--; $$ = groktypename ($3); }
;
| notype_initdecls ',' maybe_resetattrs notype_initdcl
;
-maybeasm:
- /* empty */
- { $$ = NULL_TREE; }
- | ASM_KEYWORD '(' STRING ')'
- { $$ = $3; }
- ;
-
initdcl:
declarator maybeasm maybe_attribute '='
{ $<ttype>$ = start_decl ($1, current_declspecs, 1,
;
attribute:
- ATTRIBUTE '(' '(' attribute_list ')' ')'
- { $$ = $4; }
+ ATTRIBUTE stop_string_translation
+ '(' '(' attribute_list ')' ')' start_string_translation
+ { $$ = $5; }
+ | ATTRIBUTE error start_string_translation
+ {}
;
attribute_list:
initelt:
designator_list '=' initval
{ if (pedantic && ! flag_isoc99)
- pedwarn ("ISO C89 forbids specifying subobject to initialize"); }
+ pedwarn ("ISO C90 forbids specifying subobject to initialize"); }
| designator initval
{ if (pedantic)
pedwarn ("obsolete use of designated initializer without `='"); }
pop_function_context ();
YYERROR1;
}
- parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls save_location
{ tree decl = current_function_decl;
pop_function_context ();
YYERROR1;
}
- parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls save_location
{ tree decl = current_function_decl;
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | after_type_declarator '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| after_type_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
-ifobjc
+@@ifobjc
| OBJECTNAME
-end ifobjc
+@@end_ifobjc
;
/* Kinds of declarator that can appear in a parameter list
parm_declarator_starttypename:
parm_declarator_starttypename '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | parm_declarator_starttypename '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| parm_declarator_starttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| TYPENAME
-ifobjc
+@@ifobjc
| OBJECTNAME
-end ifobjc
+@@end_ifobjc
;
parm_declarator_nostarttypename:
parm_declarator_nostarttypename '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | parm_declarator_nostarttypename '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| parm_declarator_nostarttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_attrs parm_declarator_starttypename %prec UNARY
notype_declarator:
notype_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | notype_declarator '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| '(' maybe_attribute notype_declarator ')'
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| '*' maybe_type_quals_attrs notype_declarator %prec UNARY
| component_decl_list2 ';'
{ if (pedantic)
pedwarn ("extra semicolon in struct or union specified"); }
-ifobjc
+@@ifobjc
/* foo(sizeof(struct{ @defs(ClassName)})); */
| DEFS '(' CLASSNAME ')'
- {
- tree interface = lookup_interface ($3);
-
- if (interface)
- $$ = nreverse (get_class_ivars (interface));
- else
- {
- error ("cannot find interface declaration for `%s'",
- IDENTIFIER_POINTER ($3));
- $$ = NULL_TREE;
- }
- }
-end ifobjc
+ { $$ = nreverse (get_class_ivars_from_name ($3)); }
+@@end_ifobjc
;
component_decl:
/* The [...] part of a declarator for an array type. */
array_declarator:
- '[' maybe_type_quals_attrs expr ']'
+ '[' maybe_type_quals_attrs expr_no_commas ']'
{ $$ = build_array_declarator ($3, $2, 0, 0); }
| '[' maybe_type_quals_attrs ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
| '[' maybe_type_quals_attrs '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
- | '[' STATIC maybe_type_quals_attrs expr ']'
+ | '[' STATIC maybe_type_quals_attrs expr_no_commas ']'
{ $$ = build_array_declarator ($4, $3, 1, 0); }
/* declspecs_nosc_nots is a synonym for type_quals_attrs. */
- | '[' declspecs_nosc_nots STATIC expr ']'
+ | '[' declspecs_nosc_nots STATIC expr_no_commas ']'
{ $$ = build_array_declarator ($4, $2, 1, 0); }
;
| lineno_stmt_decl_or_labels_ending_decl
| lineno_stmt_decl_or_labels_ending_label
{
- pedwarn ("deprecated use of label at end of compound statement");
+ error ("label at end of compound statement");
}
| lineno_stmt_decl_or_labels_ending_error
;
errstmt: error ';'
;
-pushlevel: /* empty */
- { pushlevel (0);
+push_scope: /* empty */
+ { push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-ifobjc
- if (objc_method_context)
- add_objc_decls ();
-end ifobjc
}
;
-poplevel: /* empty */
- { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+pop_scope: /* empty */
+ {
+@@ifobjc
+ if (c_dialect_objc ())
+ objc_clear_super_receiver ();
+@@end_ifobjc
+ $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+ }
;
/* Start and end blocks created for the new scopes of C99. */
{ if (flag_isoc99)
{
$$ = c_begin_compound_stmt ();
- pushlevel (0);
+ push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-ifobjc
- if (objc_method_context)
- add_objc_decls ();
-end ifobjc
}
else
$$ = NULL_TREE;
{ if (flag_isoc99)
{
tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- $$ = poplevel (KEEP_MAYBE, 0, 0);
+ $$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
= $$;
compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
- | pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
- { $$ = poplevel (KEEP_MAYBE, 0, 0);
+ | push_scope maybe_label_decls compstmt_contents_nonempty '}' pop_scope
+ { $$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
= SCOPE_STMT_BLOCK (TREE_VALUE ($5))
= $$; }
keep_next_level ();
compstmt_count++;
$$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
+ last_expr_type = NULL_TREE;
}
;
if_prefix:
/* We must build the IF_STMT node before parsing its
- condition so that STMT_LINENO refers to the line
+ condition so that EXPR_LOCUS refers to the line
containing the "if", and not the line containing
the close-parenthesis.
IF
{ $<ttype>$ = c_begin_if_stmt (); }
'(' expr ')'
- { c_expand_start_cond (c_common_truthvalue_conversion ($4),
+ { c_expand_start_cond (lang_hooks.truthvalue_conversion ($4),
compstmt_count,$<ttype>2);
$<itype>$ = stmt_count;
if_stmt_locus = $<location>-1; }
DO
{ stmt_count++;
compstmt_count++;
+ c_in_iteration_stmt++;
$<ttype>$
= add_stmt (build_stmt (DO_STMT, NULL_TREE,
NULL_TREE));
DO_COND ($<ttype>$) = error_mark_node; }
c99_block_lineno_labeled_stmt WHILE
{ $$ = $<ttype>2;
- RECHAIN_STMTS ($$, DO_BODY ($$)); }
+ RECHAIN_STMTS ($$, DO_BODY ($$));
+ c_in_iteration_stmt--; }
;
/* The forced readahead in here is because we might be at the end of a
save_location stmt
{ if ($2)
{
- STMT_LINENO ($2) = $1.line;
- /* ??? We currently have no way of recording
- the filename for a statement. This probably
- matters little in practice at the moment,
- but I suspect that problems will occur when
- doing inlining at the tree level. */
+ SET_EXPR_LOCUS ($2, NULL);
+ annotate_with_locus ($2, $1);
}
}
;
save_location label
{ if ($2)
{
- STMT_LINENO ($2) = $1.line;
+ SET_EXPR_LOCUS ($2, NULL);
+ annotate_with_locus ($2, $1);
}
}
;
| simple_if ELSE error
{ c_expand_end_cond (); }
/* We must build the WHILE_STMT node before parsing its
- condition so that STMT_LINENO refers to the line
+ condition so that EXPR_LOCUS refers to the line
containing the "while", and not the line containing
the close-parenthesis.
{ stmt_count++;
$<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
- { $4 = c_common_truthvalue_conversion ($4);
+ { c_in_iteration_stmt++;
+ $4 = lang_hooks.truthvalue_conversion ($4);
c_finish_while_stmt_cond
- (c_common_truthvalue_conversion ($4), $<ttype>2);
+ (lang_hooks.truthvalue_conversion ($4), $<ttype>2);
$<ttype>$ = add_stmt ($<ttype>2); }
c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
+ { c_in_iteration_stmt--;
+ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
- { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
+ { DO_COND ($1) = lang_hooks.truthvalue_conversion ($3); }
| do_stmt_start error
{ }
| FOR
xexpr ';'
{ if ($6)
FOR_COND ($<ttype>2)
- = c_common_truthvalue_conversion ($6); }
+ = lang_hooks.truthvalue_conversion ($6); }
xexpr ')'
- { FOR_EXPR ($<ttype>2) = $9; }
+ { c_in_iteration_stmt++;
+ FOR_EXPR ($<ttype>2) = $9; }
c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
+ { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2));
+ c_in_iteration_stmt--;}
| SWITCH '(' expr ')'
{ stmt_count++;
- $<ttype>$ = c_start_case ($3); }
+ $<ttype>$ = c_start_case ($3);
+ c_in_case_stmt++; }
c99_block_lineno_labeled_stmt
- { c_finish_case (); }
+ { c_finish_case ();
+ c_in_case_stmt--; }
;
for_init_stmt:
{ check_for_loop_decls (); }
;
+xexpr:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | expr
+ ;
+
/* Parse a single real statement, not including any labels. */
stmt:
compstmt
$$ = NULL_TREE; }
| BREAK ';'
{ stmt_count++;
+ if (!(c_in_iteration_stmt || c_in_case_stmt))
+ {
+ error ("break statement not within loop or switch");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
+ if (!c_in_iteration_stmt)
+ {
+ error ("continue statement not within a loop");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
| RETURN expr ';'
{ stmt_count++;
$$ = c_expand_return ($2); }
- | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
- { stmt_count++;
- $$ = simple_asm_stmt ($4); }
- /* This is the case with just output operands. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
- { stmt_count++;
- $$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
- /* This is the case with input operands as well. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
- asm_operands ')' ';'
- { stmt_count++;
- $$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
- /* This is the case with clobbered registers as well. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
- asm_operands ':' asm_clobbers ')' ';'
- { stmt_count++;
- $$ = build_asm_stmt ($2, $4, $6, $8, $10); }
+ | asm_stmt
| GOTO identifier ';'
{ tree decl;
stmt_count++;
$$ = add_stmt (build_stmt (GOTO_STMT, $3)); }
| ';'
{ $$ = NULL_TREE; }
+@@ifobjc
+ | AT_THROW expr ';'
+ { stmt_count++;
+ $$ = objc_build_throw_stmt ($2);
+ }
+ | AT_THROW ';'
+ { stmt_count++;
+ $$ = objc_build_throw_stmt (NULL_TREE);
+ }
+ | objc_try_catch_stmt
+ { objc_build_finally_prologue (); }
+ objc_finally_block
+ { $$ = objc_build_try_catch_finally_stmt ($1, $3); }
+ | AT_SYNCHRONIZED '(' expr ')'
+ { objc_build_synchronized_prologue ($3); }
+ compstmt
+ { $$ = objc_build_synchronized_epilogue (); }
+ ;
+
+objc_try_catch_stmt:
+ objc_try_stmt
+ { objc_build_try_epilogue (1); }
+ objc_catch_list
+ { objc_build_catch_epilogue (); $$ = 1; }
+ | objc_try_stmt
+ { objc_build_try_epilogue (0); $$ = 0; }
+ ;
+
+
+objc_try_stmt:
+ AT_TRY
+ { objc_build_try_prologue (); }
+ compstmt
+ ;
+
+objc_catch_list:
+ objc_catch_list objc_catch_block
+ | objc_catch_block
+ ;
+
+objc_catch_block:
+ AT_CATCH '(' parm ')'
+ { objc_build_catch_stmt ($3); }
+ compstmt
+ { stmt_count++; }
+ ;
+
+objc_finally_block:
+ AT_FINALLY compstmt
+ { $$ = 1; }
+ | /* NULL */
+ { $$ = 0; }
+@@end_ifobjc
;
/* Any kind of label, including jump labels and case labels.
}
;
-/* Either a type-qualifier or nothing. First thing in an `asm' statement. */
+/* Asm expressions and statements */
-maybe_type_qual:
- /* empty */
- { emit_line_note (input_location);
- $$ = NULL_TREE; }
- | TYPE_QUAL
- { emit_line_note (input_location); }
+/* simple_asm_expr is used in restricted contexts, where a full
+ expression with inputs and outputs does not make sense. */
+simple_asm_expr:
+ ASM_KEYWORD stop_string_translation
+ '(' STRING ')' start_string_translation
+ { $$ = $4; }
;
-xexpr:
- /* empty */
+/* maybeasm: used for assembly names for declarations */
+maybeasm:
+ /* empty */
{ $$ = NULL_TREE; }
- | expr
+ | simple_asm_expr
+ ;
+
+/* asmdef: asm() outside a function body. */
+asmdef:
+ simple_asm_expr ';'
+ { assemble_asm ($1); }
+ | ASM_KEYWORD error start_string_translation ';'
+ {}
+ ;
+
+/* Full-blown asm statement with inputs, outputs, clobbers, and
+ volatile tag allowed. */
+asm_stmt:
+ ASM_KEYWORD maybe_volatile stop_string_translation
+ '(' asm_argument ')' start_string_translation ';'
+ { stmt_count++;
+ $$ = build_asm_stmt ($2, $5); }
+ ;
+
+asm_argument:
+ /* no operands */
+ STRING
+ { $$ = build_asm_expr ($1, 0, 0, 0, true); }
+ /* output operands */
+ | STRING ':' asm_operands
+ { $$ = build_asm_expr ($1, $3, 0, 0, false); }
+ /* output and input operands */
+ | STRING ':' asm_operands ':' asm_operands
+ { $$ = build_asm_expr ($1, $3, $5, 0, false); }
+ /* output and input operands and clobbers */
+ | STRING ':' asm_operands ':' asm_operands ':' asm_clobbers
+ { $$ = build_asm_expr ($1, $3, $5, $7, false); }
+ ;
+
+/* Either 'volatile' or nothing. First thing in an `asm' statement. */
+
+maybe_volatile:
+ /* empty */
+ { $$ = 0; }
+ | TYPE_QUAL
+ { if ($1 != ridpointers[RID_VOLATILE])
+ {
+ warning ("%E qualifier ignored on asm", $1);
+ $$ = 0;
+ }
+ else
+ $$ = $1;
+ }
;
/* These are the operands other than the first string and colon
;
asm_operand:
- STRING '(' expr ')'
- { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
- | '[' identifier ']' STRING '(' expr ')'
+ STRING start_string_translation '(' expr ')' stop_string_translation
+ { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $4); }
+ | '[' identifier ']' STRING start_string_translation
+ '(' expr ')' stop_string_translation
{ $2 = build_string (IDENTIFIER_LENGTH ($2),
IDENTIFIER_POINTER ($2));
- $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+ $$ = build_tree_list (build_tree_list ($2, $4), $7); }
;
asm_clobbers:
| asm_clobbers ',' STRING
{ $$ = tree_cons (NULL_TREE, $3, $1); }
;
+
+stop_string_translation:
+ { c_lex_string_translate = false; }
+ ;
+
+start_string_translation:
+ { c_lex_string_translate = true; }
+ ;
+
\f
/* This is what appears inside the parens in a function declarator.
Its value is a list of ..._TYPE nodes. Attributes must appear here
"void bar (int (__attribute__((__mode__(SI))) int foo));". */
parmlist:
maybe_attribute
- { pushlevel (0);
+ { push_scope ();
declare_parm_level (); }
parmlist_1
{ $$ = $3;
- poplevel (0, 0, 0); }
+ pop_scope (); }
;
parmlist_1:
parmlist_1
{ $$ = $6; }
| error ')'
- { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
+ { $$ = make_node (TREE_LIST); }
;
/* This is what appears inside the parens in a function declarator.
Is value is represented in the format that grokdeclarator expects. */
parmlist_2: /* empty */
- { $$ = get_parm_info (0); }
+ { $$ = make_node (TREE_LIST); }
| ELLIPSIS
- { $$ = get_parm_info (0);
- /* Gcc used to allow this as an extension. However, it does
- not work for all targets, and thus has been disabled.
- Also, since func (...) and func () are indistinguishable,
- it caused problems with the code in expand_builtin which
- tries to verify that BUILT_IN_NEXT_ARG is being used
- correctly. */
+ { $$ = make_node (TREE_LIST);
+ /* Suppress -Wold-style-definition for this case. */
+ TREE_CHAIN ($$) = error_mark_node;
error ("ISO C requires a named argument before `...'");
}
| parms
- { $$ = get_parm_info (1);
- parsing_iso_function_signature = true;
- }
+ { $$ = get_parm_info (/*ellipsis=*/false); }
| parms ',' ELLIPSIS
- { $$ = get_parm_info (0); }
+ { $$ = get_parm_info (/*ellipsis=*/true); }
;
parms:
Its value is a list of ..._TYPE nodes or a list of identifiers. */
parmlist_or_identifiers:
maybe_attribute
- { pushlevel (0);
+ { push_scope ();
declare_parm_level (); }
parmlist_or_identifiers_1
{ $$ = $3;
- poplevel (0, 0, 0); }
+ pop_scope (); }
;
parmlist_or_identifiers_1:
flag_iso = 0; }
;
\f
-ifobjc
+@@ifobjc
/* Objective-C productions. */
objcdef:
}
;
-classdef:
- INTERFACE identifier protocolrefs '{'
- {
- objc_interface_context = objc_ivar_context
- = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
- objc_public_flag = 0;
- }
- ivar_decl_list '}'
- {
- continue_class (objc_interface_context);
- }
- methodprotolist
- END
- {
- finish_class (objc_interface_context);
- objc_interface_context = NULL_TREE;
- }
+superclass:
+ ':' identifier { $$ = $2; }
+ | /* NULL */ %prec HYPERUNARY { $$ = NULL_TREE; }
+ ;
- | INTERFACE identifier protocolrefs
- {
- objc_interface_context
- = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
- continue_class (objc_interface_context);
- }
- methodprotolist
- END
- {
- finish_class (objc_interface_context);
- objc_interface_context = NULL_TREE;
- }
+class_ivars:
+ '{' ivar_decl_list '}'
+ | /* NULL */
+ ;
- | INTERFACE identifier ':' identifier protocolrefs '{'
+classdef:
+ INTERFACE identifier superclass protocolrefs
{
objc_interface_context = objc_ivar_context
- = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
+ = start_class (CLASS_INTERFACE_TYPE, $2, $3, $4);
objc_public_flag = 0;
}
- ivar_decl_list '}'
+ class_ivars
{
continue_class (objc_interface_context);
}
- methodprotolist
- END
- {
- finish_class (objc_interface_context);
- objc_interface_context = NULL_TREE;
- }
-
- | INTERFACE identifier ':' identifier protocolrefs
- {
- objc_interface_context
- = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
- continue_class (objc_interface_context);
- }
- methodprotolist
- END
+ methodprotolist END
{
finish_class (objc_interface_context);
objc_interface_context = NULL_TREE;
}
- | IMPLEMENTATION identifier '{'
- {
- objc_implementation_context = objc_ivar_context
- = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
- objc_public_flag = 0;
- }
- ivar_decl_list '}'
- {
- objc_ivar_chain
- = continue_class (objc_implementation_context);
- }
-
- | IMPLEMENTATION identifier
- {
- objc_implementation_context
- = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
- objc_ivar_chain
- = continue_class (objc_implementation_context);
- }
-
- | IMPLEMENTATION identifier ':' identifier '{'
+ | IMPLEMENTATION identifier superclass
{
objc_implementation_context = objc_ivar_context
- = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
+ = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $3, NULL_TREE);
objc_public_flag = 0;
}
- ivar_decl_list '}'
+ class_ivars
{
objc_ivar_chain
= continue_class (objc_implementation_context);
}
- | IMPLEMENTATION identifier ':' identifier
- {
- objc_implementation_context
- = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
- objc_ivar_chain
- = continue_class (objc_implementation_context);
- }
-
| INTERFACE identifier '(' identifier ')' protocolrefs
{
objc_interface_context
= start_class (CATEGORY_INTERFACE_TYPE, $2, $4, $6);
continue_class (objc_interface_context);
}
- methodprotolist
- END
+ methodprotolist END
{
finish_class (objc_interface_context);
objc_interface_context = NULL_TREE;
methoddecl
{
objc_pq_context = 0;
- if (objc_inherit_code == CLASS_METHOD_DECL)
- add_class_method (objc_implementation_context, $3);
- else
- add_instance_method (objc_implementation_context, $3);
+ objc_add_method (objc_implementation_context,
+ $3,
+ objc_inherit_code == CLASS_METHOD_DECL);
start_method_def ($3);
}
optarglist
methodprotolist:
/* empty */
- | {$<ttype>$ = NULL_TREE; } methodprotolist2
- ;
-
-methodprotolist2: /* eliminates a shift/reduce conflict */
- methodproto
- | datadef
- | methodprotolist2 methodproto
- | methodprotolist2 {$<ttype>$ = NULL_TREE; } datadef
+ | methodprotolist methodproto
+ | methodprotolist { $<ttype>$ = NULL_TREE; } datadef
;
semi_or_error:
{
/* Forget protocol qualifiers here. */
objc_pq_context = 0;
- if (objc_inherit_code == CLASS_METHOD_DECL)
- add_class_method (objc_interface_context, $3);
- else
- add_instance_method (objc_interface_context, $3);
+ objc_add_method (objc_interface_context,
+ $3,
+ objc_inherit_code == CLASS_METHOD_DECL);
}
semi_or_error
;
}
| ','
{
- pushlevel (0);
+ push_scope ();
}
parmlist_2
{
/* returns a tree list node generated by get_parm_info */
$$ = $3;
- poplevel (0, 0, 0);
+ pop_scope ();
}
;
{
$$ = get_class_reference ($1);
}
+ | TYPENAME
+ {
+ $$ = get_class_reference ($1);
+ }
;
objcmessageexpr:
}
;
-end ifobjc
+@@end_ifobjc
%%
/* yylex() is a thin wrapper around c_lex(), all it does is translate
{ "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+ { "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
{ "__builtin_va_arg", RID_VA_ARG, 0 },
{ "__complex", RID_COMPLEX, 0 },
{ "void", RID_VOID, 0 },
{ "volatile", RID_VOLATILE, 0 },
{ "while", RID_WHILE, 0 },
-ifobjc
+@@ifobjc
{ "id", RID_ID, D_OBJC },
/* These objc keywords are recognized only immediately after
{ "protocol", RID_AT_PROTOCOL, D_OBJC },
{ "public", RID_AT_PUBLIC, D_OBJC },
{ "selector", RID_AT_SELECTOR, D_OBJC },
-
+ { "throw", RID_AT_THROW, D_OBJC },
+ { "try", RID_AT_TRY, D_OBJC },
+ { "catch", RID_AT_CATCH, D_OBJC },
+ { "finally", RID_AT_FINALLY, D_OBJC },
+ { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC },
/* These are recognized only in protocol-qualifier context
(see above) */
{ "bycopy", RID_BYCOPY, D_OBJC },
{ "inout", RID_INOUT, D_OBJC },
{ "oneway", RID_ONEWAY, D_OBJC },
{ "out", RID_OUT, D_OBJC },
-end ifobjc
+@@end_ifobjc
};
#define N_reswords (sizeof reswords / sizeof (struct resword))
/* RID_FALSE */ 0,
/* RID_NAMESPACE */ 0,
/* RID_NEW */ 0,
+ /* RID_OFFSETOF */ OFFSETOF,
/* RID_OPERATOR */ 0,
/* RID_THIS */ 0,
/* RID_THROW */ 0,
/* RID_AT_PUBLIC */ PUBLIC,
/* RID_AT_PROTOCOL */ PROTOCOL,
/* RID_AT_SELECTOR */ SELECTOR,
+ /* RID_AT_THROW */ AT_THROW,
+ /* RID_AT_TRY */ AT_TRY,
+ /* RID_AT_CATCH */ AT_CATCH,
+ /* RID_AT_FINALLY */ AT_FINALLY,
+ /* RID_AT_SYNCHRONIZED */ AT_SYNCHRONIZED,
/* RID_AT_INTERFACE */ INTERFACE,
/* RID_AT_IMPLEMENTATION */ IMPLEMENTATION
};
static void
yyerror (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 *const 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)
- error ("%s before string constant", string);
- else if (last_token == CPP_NUMBER)
- error ("%s before numeric constant", string);
- else if (last_token == CPP_NAME)
- error ("%s before \"%s\"", string, IDENTIFIER_POINTER (yylval.ttype));
- else
- error ("%s before '%s' token", string, NAME(last_token));
+ c_parse_error (msgid, last_token, yylval.ttype);
}
static int
{
tree decl;
-ifobjc
+@@ifobjc
int objc_force_identifier = objc_need_raw_identifier;
OBJC_NEED_RAW_IDENTIFIER (0);
-end ifobjc
+@@end_ifobjc
if (C_IS_RESERVED_WORD (yylval.ttype))
{
enum rid rid_code = C_RID_CODE (yylval.ttype);
-ifobjc
+@@ifobjc
/* Turn non-typedefed refs to "id" into plain identifiers; this
allows constructs like "void foo(id id);" to work. */
if (rid_code == RID_ID)
if (!OBJC_IS_AT_KEYWORD (rid_code)
&& (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
-end ifobjc
+@@end_ifobjc
{
/* Return the canonical spelling for this keyword. */
yylval.ttype = ridpointers[(int) rid_code];
if (TREE_CODE (decl) == TYPE_DECL)
return TYPENAME;
}
-ifobjc
+@@ifobjc
else
{
tree objc_interface_decl = is_class_name (yylval.ttype);
return CLASSNAME;
}
}
-end ifobjc
+@@end_ifobjc
return IDENTIFIER;
}
case CPP_STRING:
case CPP_WSTRING:
return STRING;
-
+
case CPP_OBJC_STRING:
return OBJC_STRING;
}
}
\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. */
-
-/* Free malloced parser stacks if necessary. */
-
-void
-free_parser_stacks (void)
-{
-}
+/* This is not the ideal place to put this, but we have to get it out
+ of c-lex.c because cp/lex.c has its own version. */
/* Parse the file. */
void
c_parse_file (void)
{
yyparse ();
- /* In case there were missing closebraces, get us back to the global
- binding level. */
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
- /* __FUNCTION__ is defined at file scope (""). This
- call may not be necessary as my tests indicate it
- still works without it. */
- finish_fname_decls ();
if (malloced_yyss)
{