/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-5, 1996 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.
ifc ... end ifc conditionals contain code for C only.
- The awk script cond.awk is used to convert this file into
+ 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. */
+ written by AT&T, but I have never seen it. */
ifobjc
-%expect 56
+%expect 52
end ifobjc
ifc
-%expect 8
+%expect 34
-/* These are the 8 conflicts you should get in parse.output;
+/* 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 41 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 92 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 99 contains 1 shift/reduce conflict. (Two ways to recover from error.)
+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 119 contains 1 shift/reduce conflict. (See comment at component_decl.)
-State 183 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 193 contains 1 shift/reduce conflict. (Two ways to recover from error.)
-State 199 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.) */
+
end ifc
%{
%start program
%union {long itype; tree ttype; enum tree_code code;
- char *filename; int lineno; }
+ char *filename; int lineno; int ends_in_label; }
/* All identifiers that are not reserved words
and are not declared typedefs in the current block */
/* the reserved words */
/* SCO include files test "ASM", so use something else. */
%token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
-%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF ALIGN
+%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token ATTRIBUTE EXTENSION LABEL
+%token REALPART IMAGPART
/* Add precedence rules to solve dangling else s/r conflict */
%nonassoc IF
/* The Objective-C keywords. These are included in C and in
Objective C, so that the token codes are the same in both. */
%token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE
-%token CLASSNAME PUBLIC
+%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
+
+/* Objective-C string constants in raw form.
+ yylval is an OBJC_STRING_CST node. */
+%token OBJC_STRING
%type <code> unop
%type <ttype> declmods typespec typespecqual_reserved
%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
-%type <ttype> init initlist maybeasm
+%type <ttype> init maybeasm
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
-%type <ttype> maybe_attribute attribute_list attrib
+%type <ttype> maybe_attribute attributes attribute attribute_list attrib
+%type <ttype> any_word
%type <ttype> compstmt
%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> CLASSNAME
+%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
+
+%type <ttype> CLASSNAME OBJC_STRING OBJECTNAME
end ifobjc
\f
%{
/* List of types and structure classes of the current declaration. */
static tree current_declspecs;
+static tree prefix_attributes = NULL_TREE;
-/* Stack of saved values of current_declspecs. */
+/* Stack of saved values of current_declspecs and prefix_attributes. */
static tree declspec_stack;
/* 1 if we explained undeclared var errors. */
program: /* empty */
{ if (pedantic)
pedwarn ("ANSI C forbids an empty source file");
-ifobjc
- objc_finish ();
-end ifobjc
+ finish_file ();
}
| extdefs
{
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
-ifobjc
- objc_finish ();
-end ifobjc
+ finish_file ();
}
;
{ if (pedantic)
error ("ANSI 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);
+ resume_momentary ($1); }
| 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); }
| 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); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| typed_declspecs ';'
\f
fndef:
typed_declspecs setspecs declarator
- { if (! start_function ($1, $3, 0))
+ { if (! start_function ($1, $3, prefix_attributes,
+ NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
xdecls
{ 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);
+ resume_momentary ($2); }
| 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); }
| declmods setspecs notype_declarator
- { if (! start_function ($1, $3, 0))
+ { if (! start_function ($1, $3, prefix_attributes,
+ NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
xdecls
{ 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);
+ resume_momentary ($2); }
| 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); }
| setspecs notype_declarator
- { if (! start_function (NULL_TREE, $2, 0))
+ { if (! start_function (NULL_TREE, $2,
+ prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); }
xdecls
{ 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);
+ resume_momentary ($1); }
| 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); }
;
identifier:
IDENTIFIER
| TYPENAME
ifobjc
+ | OBJECTNAME
| CLASSNAME
- { $$ = CLASS_NAME ($1); }
end ifobjc
;
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
{ tree label = lookup_label ($2);
+ if (pedantic)
+ pedwarn ("ANSI C forbids `&&'");
if (label == 0)
$$ = null_pointer_node;
else
{ $$ = c_alignof_expr ($2); }
| ALIGNOF '(' typename ')' %prec HYPERUNARY
{ $$ = 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); }
;
cast_expr:
| '(' typename ')' cast_expr %prec UNARY
{ tree type = groktypename ($2);
$$ = build_c_cast (type, $4); }
- | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY
- { tree type = groktypename ($2);
- char *name;
+ | '(' typename ')' '{'
+ { start_init (NULL_TREE, NULL, 0);
+ $2 = groktypename ($2);
+ really_start_incremental_init ($2); }
+ initlist_maybe_comma '}' %prec UNARY
+ { char *name;
+ tree result = pop_init_level (0);
+ tree type = $2;
+ finish_init ();
+
if (pedantic)
pedwarn ("ANSI C forbids constructor expressions");
if (TYPE_NAME (type) != 0)
}
else
name = "";
- $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)),
- NULL_PTR, 0, 0, name);
+ $$ = result;
if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
{
int failure = complete_array_type (type, $$, 1);
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
| expr_no_commas ASSIGN expr_no_commas
{ $$ = build_modify_expr ($1, $2, $3);
- C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+ /* This inhibits warnings in truthvalue_conversion. */
+ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
;
primary:
IDENTIFIER
{
- tree context;
-
$$ = lastiddecl;
if (!$$ || $$ == error_mark_node)
{
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
- && is_ivar (objc_ivar_chain, $1))
- $$ = build_ivar_reference ($1);
+ && (decl = is_ivar (objc_ivar_chain, $1)))
+ {
+ if (is_private (decl))
+ $$ = error_mark_node;
+ else
+ $$ = build_ivar_reference ($1);
+ }
else
end ifobjc
{
}
else if (current_function_decl == 0)
{
- error ("`%s' undeclared, outside of functions",
+ 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
- && is_ivar (objc_ivar_chain, $1))
- $$ = build_ivar_reference ($1);
+ && (decl = is_ivar (objc_ivar_chain, $1)))
+ {
+ if (is_private (decl))
+ $$ = error_mark_node;
+ else
+ $$ = build_ivar_reference ($1);
+ }
else
end ifobjc
{
|| (objc_receiver_context
&& strcmp (IDENTIFIER_POINTER ($1), "super")))
{
+ tree decl;
+
if (objc_method_context
- && is_ivar (objc_ivar_chain, $1))
+ && (decl = is_ivar (objc_ivar_chain, $1)))
{
if (IDENTIFIER_LOCAL_VALUE ($1))
warning ("local declaration of `%s' hides instance variable",
IDENTIFIER_POINTER ($1));
else
- $$ = build_ivar_reference ($1);
+ {
+ if (is_private (decl))
+ $$ = error_mark_node;
+ else
+ $$ = build_ivar_reference ($1);
+ }
}
}
else /* we have a message to super */
/* The statements have side effects, so the group does. */
TREE_SIDE_EFFECTS (rtl_exp) = 1;
- /* 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);
+ 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;
}
| primary '(' exprlist ')' %prec '.'
{ $$ = build_function_call ($1, $3); }
{ $$ = build_message_expr ($1); }
| objcselectorexpr
{ $$ = build_selector_expr ($1); }
+ | objcprotocolexpr
+ { $$ = build_protocol_expr ($1); }
| objcencodeexpr
{ $$ = build_encode_expr ($1); }
+ | objc_string
+ { $$ = build_objc_string_object ($1); }
end ifobjc
;
{ $$ = chainon ($1, $2); }
;
+ifobjc
+/* Produces an OBJC_STRING_CST with perhaps more OBJC_STRING_CSTs chained
+ onto it. */
+objc_string:
+ OBJC_STRING
+ | objc_string OBJC_STRING
+ { $$ = chainon ($1, $2); }
+ ;
+end ifobjc
+
xdecls:
/* empty */
| datadecls
datadecl:
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); }
| declmods setspecs notype_initdecls ';'
- { current_declspecs = TREE_VALUE (declspec_stack);
+ { current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary ($2); }
| typed_declspecs ';'
setspecs: /* empty */
{ $$ = suspend_momentary ();
pending_xref_error ();
- declspec_stack = tree_cons (NULL_TREE, current_declspecs,
+ declspec_stack = tree_cons (prefix_attributes,
+ current_declspecs,
declspec_stack);
- current_declspecs = $<ttype>0; }
+ current_declspecs = $<ttype>0;
+ prefix_attributes = NULL_TREE; }
+ ;
+
+setattrs: /* empty */
+ { prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
;
decl:
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); }
| 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); }
| 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); }
| 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); }
| typed_declspecs ';'
In case of `foo foo, bar;'. */
$$ = lookup_name ($1); }
ifobjc
- | CLASSNAME
- { $$ = get_static_reference ($1); }
+ | CLASSNAME protocolrefs
+ { $$ = 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); }
+ { $<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);
+ { finish_init ();
finish_decl ($<ttype>5, $6, $2); }
| declarator maybeasm maybe_attribute
- { tree d = start_decl ($1, current_declspecs, 0);
- decl_attributes (d, $3);
- finish_decl (d, NULL_TREE, $2); }
+ { 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); }
+ { $<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);
+ { finish_init ();
+ 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);
+ { 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
so that the header files compile. */
maybe_attribute:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | attributes
+ { $$ = $1; }
+ ;
+
+attributes:
+ attribute
+ { $$ = $1; }
+ | attributes attribute
+ { $$ = chainon ($1, $2); }
+ ;
+
+attribute:
+ ATTRIBUTE '(' '(' attribute_list ')' ')'
+ { $$ = $4; }
+ ;
+
+attribute_list:
+ attrib
+ { $$ = $1; }
+ | attribute_list ',' attrib
+ { $$ = chainon ($1, $3); }
+ ;
+
+attrib:
/* empty */
{ $$ = NULL_TREE; }
- | ATTRIBUTE '(' '(' attribute_list ')' ')'
- { $$ = $4; }
- ;
-
-attribute_list
- : attrib
- { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
- | attribute_list ',' attrib
- { $$ = tree_cons (NULL_TREE, $3, $1); }
- ;
-
-attrib
- : IDENTIFIER
- { if (strcmp (IDENTIFIER_POINTER ($1), "packed"))
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER ($1));
- $$ = $1; }
- | IDENTIFIER '(' IDENTIFIER ')'
- { /* If not "mode (m)", then issue warning. */
- if (strcmp (IDENTIFIER_POINTER ($1), "mode") != 0)
- {
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER ($1));
- $$ = $1;
- }
- else
- $$ = tree_cons ($1, $3, NULL_TREE); }
- | IDENTIFIER '(' CONSTANT ')'
- { /* if not "aligned(n)", then issue warning */
- if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0
- || TREE_CODE ($3) != INTEGER_CST)
- {
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER ($1));
- $$ = $1;
- }
- else
- $$ = tree_cons ($1, $3, NULL_TREE); }
- | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')'
- { /* if not "format(...)", then issue warning */
- if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0
- || TREE_CODE ($5) != INTEGER_CST
- || TREE_CODE ($7) != INTEGER_CST)
- {
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER ($1));
- $$ = $1;
- }
- else
- $$ = tree_cons ($1,
- tree_cons ($3,
- tree_cons ($5, $7, NULL_TREE),
- NULL_TREE),
- NULL_TREE); }
- ;
+ | any_word
+ { $$ = build_tree_list ($1, NULL_TREE); }
+ | any_word '(' IDENTIFIER ')'
+ { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); }
+ | any_word '(' IDENTIFIER ',' nonnull_exprlist ')'
+ { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); }
+ | any_word '(' exprlist ')'
+ { $$ = build_tree_list ($1, $3); }
+ ;
+
+/* This still leaves out most reserved keywords,
+ shouldn't we include them? */
+
+any_word:
+ identifier
+ | SCSPEC
+ | TYPESPEC
+ | TYPE_QUAL
+ ;
+\f
+/* Initializers. `init' is the entry point. */
init:
expr_no_commas
- | '{' '}'
- { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
- if (pedantic)
- pedwarn ("ANSI C forbids empty initializer braces"); }
- | '{' initlist '}'
- { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
- | '{' initlist ',' '}'
- { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
+ | '{'
+ { really_start_incremental_init (NULL_TREE);
+ /* Note that the call to clear_momentary
+ is in process_init_element. */
+ push_momentary (); }
+ initlist_maybe_comma '}'
+ { $$ = pop_init_level (0);
+ if ($$ == error_mark_node
+ && ! (yychar == STRING || yychar == CONSTANT))
+ pop_momentary ();
+ else
+ pop_momentary_nofree (); }
+
| error
- { $$ = NULL_TREE; }
+ { $$ = error_mark_node; }
;
-/* This chain is built in reverse order,
- and put in forward order where initlist is used. */
-initlist:
- init
- { $$ = build_tree_list (NULL_TREE, $1); }
- | initlist ',' init
- { $$ = tree_cons (NULL_TREE, $3, $1); }
- /* These are for labeled elements. */
- | '[' expr_no_commas ELLIPSIS expr_no_commas ']' init
- { $$ = build_tree_list (tree_cons ($2, NULL_TREE,
- build_tree_list ($4, NULL_TREE)),
- $6); }
- | initlist ',' '[' expr_no_commas ELLIPSIS expr_no_commas ']' init
- { $$ = tree_cons (tree_cons ($4, NULL_TREE,
- build_tree_list ($6, NULL_TREE)),
- $8,
- $1); }
- | '[' expr_no_commas ']' init
- { $$ = build_tree_list ($2, $4); }
- | initlist ',' '[' expr_no_commas ']' init
- { $$ = tree_cons ($4, $6, $1); }
- | identifier ':' init
- { $$ = build_tree_list ($1, $3); }
- | initlist ',' identifier ':' init
- { $$ = tree_cons ($3, $5, $1); }
+/* `initlist_maybe_comma' is the guts of an initializer in braces. */
+initlist_maybe_comma:
+ /* empty */
+ { if (pedantic)
+ pedwarn ("ANSI C forbids empty initializer braces"); }
+ | initlist1 maybecomma
+ ;
+
+initlist1:
+ initelt
+ | initlist1 ',' initelt
;
+/* `initelt' is a single element of an initializer.
+ It may use braces. */
+initelt:
+ expr_no_commas
+ { process_init_element ($1); }
+ | '{'
+ { push_init_level (0); }
+ initlist_maybe_comma '}'
+ { process_init_element (pop_init_level (0)); }
+ | error
+ /* 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 grammar. */
+ifc
+ | '[' 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 (! start_function (current_declspecs, $1, 1))
+ if (! start_function (current_declspecs, $1,
+ prefix_attributes, NULL_TREE, 1))
{
pop_c_function_context ();
YYERROR1;
}
- reinit_parse_for_function ();
- store_parm_decls (); }
+ reinit_parse_for_function (); }
+ xdecls
+ { 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
notype_nested_function:
notype_declarator
{ push_c_function_context ();
- if (! start_function (current_declspecs, $1, 1))
+ if (! start_function (current_declspecs, $1,
+ prefix_attributes, NULL_TREE, 1))
{
pop_c_function_context ();
YYERROR1;
}
- reinit_parse_for_function ();
- store_parm_decls (); }
+ reinit_parse_for_function (); }
+ xdecls
+ { 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
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| '*' type_quals after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ | attributes setattrs after_type_declarator
+ { $$ = $3; }
| TYPENAME
+ifobjc
+ | OBJECTNAME
+end ifobjc
;
/* Kinds of declarator that can appear in a parameter list
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| '*' type_quals parm_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ | attributes setattrs parm_declarator
+ { $$ = $3; }
| TYPENAME
;
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| notype_declarator '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
+ | attributes setattrs notype_declarator
+ { $$ = $3; }
| IDENTIFIER
;
{ $$ = start_struct (RECORD_TYPE, $2);
/* Start scope of tag before parsing components. */
}
- component_decl_list '}'
- { $$ = finish_struct ($<ttype>4, $5);
- /* Really define the structure. */
- }
- | STRUCT '{' component_decl_list '}'
+ component_decl_list '}' maybe_attribute
+ { $$ = finish_struct ($<ttype>4, $5, $7); }
+ | STRUCT '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
- $3); }
+ $3, $5);
+ }
| STRUCT identifier
{ $$ = xref_tag (RECORD_TYPE, $2); }
| UNION identifier '{'
{ $$ = start_struct (UNION_TYPE, $2); }
- component_decl_list '}'
- { $$ = finish_struct ($<ttype>4, $5); }
- | UNION '{' component_decl_list '}'
+ component_decl_list '}' maybe_attribute
+ { $$ = finish_struct ($<ttype>4, $5, $7); }
+ | UNION '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
- $3); }
+ $3, $5);
+ }
| UNION identifier
{ $$ = xref_tag (UNION_TYPE, $2); }
| ENUM identifier '{'
{ $<itype>3 = suspend_momentary ();
$$ = start_enum ($2); }
- enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>4, nreverse ($5));
+ enumlist maybecomma_warn '}' maybe_attribute
+ { $$ = finish_enum ($<ttype>4, nreverse ($5), $8);
resume_momentary ($<itype>3); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
$$ = start_enum (NULL_TREE); }
- enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>3, nreverse ($4));
+ enumlist maybecomma_warn '}' maybe_attribute
+ { $$ = finish_enum ($<ttype>3, nreverse ($4), $7);
resume_momentary ($<itype>2); }
| ENUM identifier
{ $$ = xref_tag (ENUMERAL_TYPE, $2); }
ifobjc
/* foo(sizeof(struct{ @defs(ClassName)})); */
| DEFS '(' CLASSNAME ')'
- { $$ = get_class_ivars ($3); }
+ {
+ tree interface = lookup_interface ($3);
+
+ if (interface)
+ $$ = get_class_ivars (interface);
+ else
+ {
+ error ("Cannot find interface declaration for `%s'",
+ IDENTIFIER_POINTER ($3));
+ $$ = NULL_TREE;
+ }
+ }
end ifobjc
;
typed_typespecs setspecs components
{ $$ = $3;
current_declspecs = TREE_VALUE (declspec_stack);
+ prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary ($2); }
| typed_typespecs
| 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); }
| nonempty_type_quals
component_declarator:
save_filename save_lineno declarator maybe_attribute
{ $$ = grokfield ($1, $2, $3, current_declspecs, NULL_TREE);
- decl_attributes ($$, $4); }
+ decl_attributes ($$, $4, prefix_attributes); }
| save_filename save_lineno
declarator ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, $2, $3, current_declspecs, $5);
- decl_attributes ($$, $6); }
+ decl_attributes ($$, $6, prefix_attributes); }
| save_filename save_lineno ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, $2, NULL_TREE, current_declspecs, $4);
- decl_attributes ($$, $5); }
+ decl_attributes ($$, $5, prefix_attributes); }
;
/* We chain the enumerators in reverse order.
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); }
+ | attributes setattrs absdcl1
+ { $$ = $3; }
;
/* at least one statement, the first of which parses without error. */
is actually regarded as an invalid decl and part of the decls. */
stmts:
+ lineno_stmt_or_labels
+ {
+ if (pedantic && $1)
+ pedwarn ("ANSI 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:
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), 1, 0);
$$ = poplevel (1, 1, 0);
- pop_momentary (); }
+ 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);
- pop_momentary (); }
+ 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);
- pop_momentary (); }
+ if (yychar == CONSTANT || yychar == STRING)
+ pop_momentary_nofree ();
+ else
+ pop_momentary (); }
;
/* Value is number of statements counted as of the closeparen. */
IF '(' expr ')'
{ emit_line_note ($<filename>-1, $<lineno>0);
expand_start_cond (truthvalue_conversion ($3), 0);
- $<itype>1 = stmt_count;
+ $<itype>$ = stmt_count;
if_stmt_file = $<filename>-1;
if_stmt_line = $<lineno>0;
position_after_white_space (); }
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. */
| 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 (); }
| simple_if ELSE
warning ("empty body in an else-statement"); }
| simple_if %prec IF
{ expand_end_cond ();
- if (extra_warnings && stmt_count == $<itype>1)
+ /* 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
+ give a second error if this is a nested `if'. */
+ 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
expand_loop_continue_here ();
if ($9)
c_expand_expr_stmt ($9);
- pop_momentary ();
+ if (yychar == CONSTANT || yychar == STRING)
+ pop_momentary_nofree ();
+ else
+ pop_momentary ();
expand_end_loop (); }
| SWITCH '(' expr ')'
{ stmt_count++;
position_after_white_space (); }
lineno_labeled_stmt
{ expand_end_case ($3);
- pop_momentary (); }
+ if (yychar == CONSTANT || yychar == STRING)
+ pop_momentary_nofree ();
+ else
+ pop_momentary (); }
| BREAK ';'
{ stmt_count++;
emit_line_note ($<filename>-1, $<lineno>0);
}
}
| GOTO '*' expr ';'
- { stmt_count++;
+ { if (pedantic)
+ pedwarn ("ANSI C forbids `goto *expr;'");
+ stmt_count++;
emit_line_note ($<filename>-1, $<lineno>0);
expand_computed_goto (convert (ptr_type_node, $3)); }
| ';'
$<itype>$ = 0;
if (TREE_CODE ($3) != VAR_DECL)
error ("invalid `for (ITERATOR)' syntax");
- if (! ITERATOR_P ($3))
+ 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"
+ error ("`for (%s)' inside expansion of same iterator",
IDENTIFIER_POINTER (DECL_NAME ($3)));
else
{
emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), 1, 0);
$<ttype>$ = poplevel (1, 1, 0);
- pop_momentary ();
+ if (yychar == CONSTANT || yychar == STRING)
+ pop_momentary_nofree ();
+ else
+ pop_momentary ();
}
*/
if (value != error_mark_node)
{
tree duplicate;
- int success = pushcase (value, label, &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)
register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ if (pedantic)
+ pedwarn ("ANSI C forbids case ranges");
stmt_count++;
if (value1 != error_mark_node && value2 != error_mark_node)
{
tree duplicate;
- int success = pushcase_range (value1, value2, label,
+ int success = pushcase_range (value1, value2,
+ convert_and_check, label,
&duplicate);
if (success == 1)
error ("case label not within a switch statement");
tree duplicate;
register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- int success = pushcase (NULL_TREE, label, &duplicate);
+ int success = pushcase (NULL_TREE, 0, label, &duplicate);
stmt_count++;
if (success == 1)
error ("default label not within a switch statement");
maybe_type_qual:
/* empty */
- { emit_line_note (input_filename, lineno); }
+ { emit_line_note (input_filename, lineno);
+ $$ = NULL_TREE; }
| TYPE_QUAL
{ emit_line_note (input_filename, lineno); }
;
{ $$ = get_parm_info (0); }
| ELLIPSIS
{ $$ = get_parm_info (0);
- if (pedantic)
- pedwarn ("ANSI C requires a named argument before `...'");
+ /* 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. */
+ error ("ANSI 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);
+ resume_momentary ($2); }
+ | 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);
+ resume_momentary ($2); }
+ | 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);
+ resume_momentary ($2); }
+ | 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);
+ resume_momentary ($2); }
+
+ | 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);
+ resume_momentary ($2); }
;
/* This is used in a function definition
objcdef:
classdef
+ | classdecl
+ | aliasdecl
+ | protocoldef
| methoddef
| END
{
}
;
+/* A nonempty list of identifiers. */
+identifier_list:
+ identifier
+ { $$ = build_tree_list (NULL_TREE, $1); }
+ | identifier_list ',' identifier
+ { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
+ ;
+
+classdecl:
+ CLASS identifier_list ';'
+ {
+ objc_declare_class ($2);
+ }
+
+aliasdecl:
+ ALIAS identifier identifier ';'
+ {
+ objc_declare_alias ($2, $3);
+ }
+
classdef:
- INTERFACE identifier '{'
+ INTERFACE identifier protocolrefs '{'
{
objc_interface_context = objc_ivar_context
- = start_class (INTERFACE_TYPE, $2, NULL_TREE);
+ = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
objc_public_flag = 0;
}
ivar_decl_list '}'
objc_interface_context = NULL_TREE;
}
- | INTERFACE identifier
+ | INTERFACE identifier protocolrefs
{
objc_interface_context
- = start_class (INTERFACE_TYPE, $2, NULL_TREE);
+ = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3);
continue_class (objc_interface_context);
}
methodprotolist
objc_interface_context = NULL_TREE;
}
- | INTERFACE identifier ':' identifier '{'
+ | INTERFACE identifier ':' identifier protocolrefs '{'
{
objc_interface_context = objc_ivar_context
- = start_class (INTERFACE_TYPE, $2, $4);
+ = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
objc_public_flag = 0;
}
ivar_decl_list '}'
objc_interface_context = NULL_TREE;
}
- | INTERFACE identifier ':' identifier
+ | INTERFACE identifier ':' identifier protocolrefs
{
objc_interface_context
- = start_class (INTERFACE_TYPE, $2, $4);
+ = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5);
continue_class (objc_interface_context);
}
methodprotolist
| IMPLEMENTATION identifier '{'
{
objc_implementation_context = objc_ivar_context
- = start_class (IMPLEMENTATION_TYPE, $2, NULL_TREE);
+ = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
objc_public_flag = 0;
}
ivar_decl_list '}'
| IMPLEMENTATION identifier
{
objc_implementation_context
- = start_class (IMPLEMENTATION_TYPE, $2, NULL_TREE);
+ = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE);
objc_ivar_chain
= continue_class (objc_implementation_context);
}
| IMPLEMENTATION identifier ':' identifier '{'
{
objc_implementation_context = objc_ivar_context
- = start_class (IMPLEMENTATION_TYPE, $2, $4);
+ = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
objc_public_flag = 0;
}
ivar_decl_list '}'
| IMPLEMENTATION identifier ':' identifier
{
objc_implementation_context
- = start_class (IMPLEMENTATION_TYPE, $2, $4);
+ = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
objc_ivar_chain
= continue_class (objc_implementation_context);
}
- | INTERFACE identifier '(' identifier ')'
+ | INTERFACE identifier '(' identifier ')' protocolrefs
{
objc_interface_context
- = start_class (PROTOCOL_TYPE, $2, $4);
+ = start_class (CATEGORY_INTERFACE_TYPE, $2, $4, $6);
continue_class (objc_interface_context);
}
methodprotolist
| IMPLEMENTATION identifier '(' identifier ')'
{
objc_implementation_context
- = start_class (CATEGORY_TYPE, $2, $4);
+ = start_class (CATEGORY_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE);
objc_ivar_chain
= continue_class (objc_implementation_context);
}
;
+protocoldef:
+ PROTOCOL identifier protocolrefs
+ {
+ remember_protocol_qualifiers ();
+ objc_interface_context
+ = start_protocol(PROTOCOL_INTERFACE_TYPE, $2, $3);
+ }
+ methodprotolist END
+ {
+ forget_protocol_qualifiers();
+ finish_protocol(objc_interface_context);
+ objc_interface_context = NULL_TREE;
+ }
+ ;
+
+protocolrefs:
+ /* empty */
+ {
+ $$ = NULL_TREE;
+ }
+ | non_empty_protocolrefs
+ ;
+
+non_empty_protocolrefs:
+ ARITHCOMPARE identifier_list ARITHCOMPARE
+ {
+ if ($1 == LT_EXPR && $3 == GT_EXPR)
+ $$ = $2;
+ else
+ YYERROR1;
+ }
+ ;
+
ivar_decl_list:
- ivar_decls PUBLIC { objc_public_flag = 1; } ivar_decls
+ ivar_decl_list visibility_spec ivar_decls
| ivar_decls
;
+visibility_spec:
+ PRIVATE { objc_public_flag = 2; }
+ | PROTECTED { objc_public_flag = 0; }
+ | PUBLIC { objc_public_flag = 1; }
+ ;
+
ivar_decls:
/* empty */
{
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);
+ resume_momentary ($2); }
| 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);
+ resume_momentary ($2); }
| error
{ $$ = NULL_TREE; }
;
methoddef:
'+'
{
+ remember_protocol_qualifiers ();
if (objc_implementation_context)
objc_inherit_code = CLASS_METHOD_DECL;
else
}
methoddecl
{
+ forget_protocol_qualifiers ();
add_class_method (objc_implementation_context, $3);
start_method_def ($3);
objc_method_context = $3;
| '-'
{
+ remember_protocol_qualifiers ();
if (objc_implementation_context)
objc_inherit_code = INSTANCE_METHOD_DECL;
else
}
methoddecl
{
+ forget_protocol_qualifiers ();
add_instance_method (objc_implementation_context, $3);
start_method_def ($3);
objc_method_context = $3;
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);
+ resume_momentary ($2); }
| 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:
selector:
IDENTIFIER
| TYPENAME
+ | OBJECTNAME
| reservedwords
;
}
;
+objcprotocolexpr:
+ PROTOCOL '(' identifier ')'
+ {
+ $$ = $3;
+ }
+ ;
+
/* extension to support C-structures in the archiver */
objcencodeexpr:
end ifobjc
%%
-ifobjc
-
-/* If STRING is the name of an Objective C @-keyword
- (not including the @), return the token type for that keyword.
- Otherwise return 0. */
-
-int
-recognize_objc_keyword (string)
- char *string;
-{
- switch (string[0])
- {
- case 'd':
- if (!strcmp (string, "defs"))
- return DEFS;
- break;
- case 'e':
- if (!strcmp (string, "end"))
- return END;
- if (!strcmp (string, "encode"))
- return ENCODE;
- break;
- case 'i':
- if (!strcmp (string, "interface"))
- return INTERFACE;
- if (!strcmp (string, "implementation"))
- return IMPLEMENTATION;
- break;
- case 'p':
- if (!strcmp (string, "public"))
- return PUBLIC;
- break;
- case 's':
- if (!strcmp (string, "selector"))
- return SELECTOR;
- break;
- }
- return 0;
-}
-
-end ifobjc