1 /* Objective-C++ Parser plugin
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
24 /* Objective-C++ Productions */
27 /* Parse an Objective-C expression, which feeds into a primary-expression
31 objc-message-expression
33 objc-encode-expression
34 objc-protocol-expression
35 objc-selector-expression
37 Returns a tree representation of the expression. */
40 cp_parser_objc_expression (cp_parser* parser)
42 /* Try to figure out what kind of declaration is present. */
43 cp_token *kwd = cp_lexer_peek_token (parser->lexer);
48 return cp_parser_objc_message_expression (parser);
51 kwd = cp_lexer_consume_token (parser->lexer);
52 return objc_build_string_object (kwd->u.value);
58 return cp_parser_objc_encode_expression (parser);
61 return cp_parser_objc_protocol_expression (parser);
64 return cp_parser_objc_selector_expression (parser);
70 error_at (kwd->location,
71 "misplaced %<@%D%> Objective-C++ construct",
73 cp_parser_skip_to_end_of_block_or_statement (parser);
76 return error_mark_node;
79 /* Parse an Objective-C message expression.
81 objc-message-expression:
82 [ objc-message-receiver objc-message-args ]
84 Returns a representation of an Objective-C message. */
87 cp_parser_objc_message_expression (cp_parser* parser)
89 tree receiver, messageargs;
91 cp_lexer_consume_token (parser->lexer); /* Eat '['. */
92 receiver = cp_parser_objc_message_receiver (parser);
93 messageargs = cp_parser_objc_message_args (parser);
94 cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
96 return objc_build_message_expr (build_tree_list (receiver, messageargs));
99 /* Parse an objc-message-receiver.
101 objc-message-receiver:
103 simple-type-specifier
105 Returns a representation of the type or expression. */
108 cp_parser_objc_message_receiver (cp_parser* parser)
112 /* An Objective-C message receiver may be either (1) a type
113 or (2) an expression. */
114 cp_parser_parse_tentatively (parser);
115 rcv = cp_parser_expression (parser, false, NULL);
117 if (cp_parser_parse_definitely (parser))
120 rcv = cp_parser_simple_type_specifier (parser,
122 CP_PARSER_FLAGS_NONE);
124 return objc_get_class_reference (rcv);
127 /* Parse the arguments and selectors comprising an Objective-C message.
132 objc-selector-args , objc-comma-args
135 objc-selector [opt] : assignment-expression
136 objc-selector-args objc-selector [opt] : assignment-expression
139 assignment-expression
140 objc-comma-args , assignment-expression
142 Returns a TREE_LIST, with TREE_PURPOSE containing a list of
143 selector arguments and TREE_VALUE containing a list of comma
147 cp_parser_objc_message_args (cp_parser* parser)
149 tree sel_args = NULL_TREE, addl_args = NULL_TREE;
150 bool maybe_unary_selector_p = true;
151 cp_token *token = cp_lexer_peek_token (parser->lexer);
153 while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
155 tree selector = NULL_TREE, arg;
157 if (token->type != CPP_COLON)
158 selector = cp_parser_objc_selector (parser);
160 /* Detect if we have a unary selector. */
161 if (maybe_unary_selector_p
162 && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
163 return build_tree_list (selector, NULL_TREE);
165 maybe_unary_selector_p = false;
166 cp_parser_require (parser, CPP_COLON, RT_COLON);
167 arg = cp_parser_assignment_expression (parser, false, NULL);
171 build_tree_list (selector, arg));
173 token = cp_lexer_peek_token (parser->lexer);
176 /* Handle non-selector arguments, if any. */
177 while (token->type == CPP_COMMA)
181 cp_lexer_consume_token (parser->lexer);
182 arg = cp_parser_assignment_expression (parser, false, NULL);
185 = chainon (addl_args,
186 build_tree_list (NULL_TREE, arg));
188 token = cp_lexer_peek_token (parser->lexer);
191 if (sel_args == NULL_TREE && addl_args == NULL_TREE)
193 cp_parser_error (parser, "objective-c++ message argument(s) are expected");
194 return build_tree_list (error_mark_node, error_mark_node);
197 return build_tree_list (sel_args, addl_args);
200 /* Parse an Objective-C encode expression.
202 objc-encode-expression:
203 @encode objc-typename
205 Returns an encoded representation of the type argument. */
208 cp_parser_objc_encode_expression (cp_parser* parser)
213 cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
214 cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
215 token = cp_lexer_peek_token (parser->lexer);
216 type = complete_type (cp_parser_type_id (parser));
217 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
221 error_at (token->location,
222 "%<@encode%> must specify a type as an argument");
223 return error_mark_node;
226 /* This happens if we find @encode(T) (where T is a template
227 typename or something dependent on a template typename) when
228 parsing a template. In that case, we can't compile it
229 immediately, but we rather create an AT_ENCODE_EXPR which will
230 need to be instantiated when the template is used.
232 if (dependent_type_p (type))
234 tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
235 TREE_READONLY (value) = 1;
239 return objc_build_encode_expr (type);
242 /* Parse an Objective-C @defs expression. */
245 cp_parser_objc_defs_expression (cp_parser *parser)
249 cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */
250 cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
251 name = cp_parser_identifier (parser);
252 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
254 return objc_get_class_ivars (name);
257 /* Parse an Objective-C protocol expression.
259 objc-protocol-expression:
260 @protocol ( identifier )
262 Returns a representation of the protocol expression. */
265 cp_parser_objc_protocol_expression (cp_parser* parser)
269 cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
270 cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
271 proto = cp_parser_identifier (parser);
272 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
274 return objc_build_protocol_expr (proto);
277 /* Parse an Objective-C selector expression.
279 objc-selector-expression:
280 @selector ( objc-method-signature )
282 objc-method-signature:
288 objc-selector-seq objc-selector :
290 Returns a representation of the method selector. */
293 cp_parser_objc_selector_expression (cp_parser* parser)
295 tree sel_seq = NULL_TREE;
296 bool maybe_unary_selector_p = true;
298 location_t loc = cp_lexer_peek_token (parser->lexer)->location;
300 cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
301 cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
302 token = cp_lexer_peek_token (parser->lexer);
304 while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
305 || token->type == CPP_SCOPE)
307 tree selector = NULL_TREE;
309 if (token->type != CPP_COLON
310 || token->type == CPP_SCOPE)
311 selector = cp_parser_objc_selector (parser);
313 if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
314 && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
316 /* Detect if we have a unary selector. */
317 if (maybe_unary_selector_p)
320 goto finish_selector;
324 cp_parser_error (parser, "expected %<:%>");
327 maybe_unary_selector_p = false;
328 token = cp_lexer_consume_token (parser->lexer);
330 if (token->type == CPP_SCOPE)
334 build_tree_list (selector, NULL_TREE));
337 build_tree_list (NULL_TREE, NULL_TREE));
342 build_tree_list (selector, NULL_TREE));
344 token = cp_lexer_peek_token (parser->lexer);
348 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
350 return objc_build_selector_expr (loc, sel_seq);
353 /* Parse a list of identifiers.
355 objc-identifier-list:
357 objc-identifier-list , identifier
359 Returns a TREE_LIST of identifier nodes. */
362 cp_parser_objc_identifier_list (cp_parser* parser)
368 identifier = cp_parser_identifier (parser);
369 if (identifier == error_mark_node)
370 return error_mark_node;
372 list = build_tree_list (NULL_TREE, identifier);
373 sep = cp_lexer_peek_token (parser->lexer);
375 while (sep->type == CPP_COMMA)
377 cp_lexer_consume_token (parser->lexer); /* Eat ','. */
378 identifier = cp_parser_identifier (parser);
379 if (identifier == error_mark_node)
382 list = chainon (list, build_tree_list (NULL_TREE,
384 sep = cp_lexer_peek_token (parser->lexer);
390 /* Parse an Objective-C alias declaration.
392 objc-alias-declaration:
393 @compatibility_alias identifier identifier ;
395 This function registers the alias mapping with the Objective-C front end.
396 It returns nothing. */
399 cp_parser_objc_alias_declaration (cp_parser* parser)
403 cp_lexer_consume_token (parser->lexer); /* Eat '@compatibility_alias'. */
404 alias = cp_parser_identifier (parser);
405 orig = cp_parser_identifier (parser);
406 objc_declare_alias (alias, orig);
407 cp_parser_consume_semicolon_at_end_of_statement (parser);
410 /* Parse an Objective-C class forward-declaration.
412 objc-class-declaration:
413 @class objc-identifier-list ;
415 The function registers the forward declarations with the Objective-C
416 front end. It returns nothing. */
419 cp_parser_objc_class_declaration (cp_parser* parser)
421 cp_lexer_consume_token (parser->lexer); /* Eat '@class'. */
422 objc_declare_class (cp_parser_objc_identifier_list (parser));
423 cp_parser_consume_semicolon_at_end_of_statement (parser);
426 /* Parse a list of Objective-C protocol references.
428 objc-protocol-refs-opt:
429 objc-protocol-refs [opt]
432 < objc-identifier-list >
434 Returns a TREE_LIST of identifiers, if any. */
437 cp_parser_objc_protocol_refs_opt (cp_parser* parser)
439 tree protorefs = NULL_TREE;
441 if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
443 cp_lexer_consume_token (parser->lexer); /* Eat '<'. */
444 protorefs = cp_parser_objc_identifier_list (parser);
445 cp_parser_require (parser, CPP_GREATER, RT_GREATER);
451 /* Parse a Objective-C visibility specification. */
454 cp_parser_objc_visibility_spec (cp_parser* parser)
456 cp_token *vis = cp_lexer_peek_token (parser->lexer);
458 switch (vis->keyword)
461 objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
463 case RID_AT_PROTECTED:
464 objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
467 objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
470 objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
476 /* Eat '@private'/'@protected'/'@public'. */
477 cp_lexer_consume_token (parser->lexer);
480 /* Parse an Objective-C method type. Return 'true' if it is a class
481 (+) method, and 'false' if it is an instance (-) method. */
484 cp_parser_objc_method_type (cp_parser* parser)
486 if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
492 /* Parse an Objective-C protocol qualifier. */
495 cp_parser_objc_protocol_qualifiers (cp_parser* parser)
497 tree quals = NULL_TREE, node;
498 cp_token *token = cp_lexer_peek_token (parser->lexer);
500 node = token->u.value;
502 while (node && TREE_CODE (node) == IDENTIFIER_NODE
503 && (node == ridpointers [(int) RID_IN]
504 || node == ridpointers [(int) RID_OUT]
505 || node == ridpointers [(int) RID_INOUT]
506 || node == ridpointers [(int) RID_BYCOPY]
507 || node == ridpointers [(int) RID_BYREF]
508 || node == ridpointers [(int) RID_ONEWAY]))
510 quals = tree_cons (NULL_TREE, node, quals);
511 cp_lexer_consume_token (parser->lexer);
512 token = cp_lexer_peek_token (parser->lexer);
513 node = token->u.value;
519 /* Parse an Objective-C typename. */
522 cp_parser_objc_typename (cp_parser* parser)
524 tree type_name = NULL_TREE;
526 if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
528 tree proto_quals, cp_type = NULL_TREE;
530 cp_lexer_consume_token (parser->lexer); /* Eat '('. */
531 proto_quals = cp_parser_objc_protocol_qualifiers (parser);
533 /* An ObjC type name may consist of just protocol qualifiers, in which
534 case the type shall default to 'id'. */
535 if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
537 cp_type = cp_parser_type_id (parser);
539 /* If the type could not be parsed, an error has already
540 been produced. For error recovery, behave as if it had
541 not been specified, which will use the default type
543 if (cp_type == error_mark_node)
546 /* We need to skip to the closing parenthesis as
547 cp_parser_type_id() does not seem to do it for
549 cp_parser_skip_to_closing_parenthesis (parser,
552 /*consume_paren=*/false);
556 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
557 type_name = build_tree_list (proto_quals, cp_type);
563 /* Check to see if TYPE refers to an Objective-C selector name. */
566 cp_parser_objc_selector_p (enum cpp_ttype type)
568 return (type == CPP_NAME || type == CPP_KEYWORD
569 || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
570 || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
571 || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
572 || type == CPP_XOR || type == CPP_XOR_EQ);
575 /* Parse an Objective-C selector. */
578 cp_parser_objc_selector (cp_parser* parser)
580 cp_token *token = cp_lexer_consume_token (parser->lexer);
582 if (!cp_parser_objc_selector_p (token->type))
584 error_at (token->location, "invalid Objective-C++ selector name");
585 return error_mark_node;
588 /* C++ operator names are allowed to appear in ObjC selectors. */
591 case CPP_AND_AND: return get_identifier ("and");
592 case CPP_AND_EQ: return get_identifier ("and_eq");
593 case CPP_AND: return get_identifier ("bitand");
594 case CPP_OR: return get_identifier ("bitor");
595 case CPP_COMPL: return get_identifier ("compl");
596 case CPP_NOT: return get_identifier ("not");
597 case CPP_NOT_EQ: return get_identifier ("not_eq");
598 case CPP_OR_OR: return get_identifier ("or");
599 case CPP_OR_EQ: return get_identifier ("or_eq");
600 case CPP_XOR: return get_identifier ("xor");
601 case CPP_XOR_EQ: return get_identifier ("xor_eq");
602 default: return token->u.value;
606 /* Parse an Objective-C params list. */
609 cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
611 tree params = NULL_TREE;
612 bool maybe_unary_selector_p = true;
613 cp_token *token = cp_lexer_peek_token (parser->lexer);
615 while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
617 tree selector = NULL_TREE, type_name, identifier;
618 tree parm_attr = NULL_TREE;
620 if (token->keyword == RID_ATTRIBUTE)
623 if (token->type != CPP_COLON)
624 selector = cp_parser_objc_selector (parser);
626 /* Detect if we have a unary selector. */
627 if (maybe_unary_selector_p
628 && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
630 params = selector; /* Might be followed by attributes. */
634 maybe_unary_selector_p = false;
635 if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
637 /* Something went quite wrong. There should be a colon
638 here, but there is not. Stop parsing parameters. */
641 type_name = cp_parser_objc_typename (parser);
642 /* New ObjC allows attributes on parameters too. */
643 if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
644 parm_attr = cp_parser_attributes_opt (parser);
645 identifier = cp_parser_identifier (parser);
649 objc_build_keyword_decl (selector,
654 token = cp_lexer_peek_token (parser->lexer);
657 if (params == NULL_TREE)
659 cp_parser_error (parser, "objective-c++ method declaration is expected");
660 return error_mark_node;
663 /* We allow tail attributes for the method. */
664 if (token->keyword == RID_ATTRIBUTE)
666 *attributes = cp_parser_attributes_opt (parser);
667 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
668 || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
670 cp_parser_error (parser,
671 "method attributes must be specified at the end");
672 return error_mark_node;
675 if (params == NULL_TREE)
677 cp_parser_error (parser, "objective-c++ method declaration is expected");
678 return error_mark_node;
683 /* Parse the non-keyword Objective-C params. */
686 cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
689 tree params = make_node (TREE_LIST);
690 cp_token *token = cp_lexer_peek_token (parser->lexer);
691 *ellipsisp = false; /* Initially, assume no ellipsis. */
693 while (token->type == CPP_COMMA)
695 cp_parameter_declarator *parmdecl;
698 cp_lexer_consume_token (parser->lexer); /* Eat ','. */
699 token = cp_lexer_peek_token (parser->lexer);
701 if (token->type == CPP_ELLIPSIS)
703 cp_lexer_consume_token (parser->lexer); /* Eat '...'. */
705 token = cp_lexer_peek_token (parser->lexer);
709 /* TODO: parse attributes for tail parameters. */
710 parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
711 parm = grokdeclarator (parmdecl->declarator,
712 &parmdecl->decl_specifiers,
713 PARM, /*initialized=*/0,
716 chainon (params, build_tree_list (NULL_TREE, parm));
717 token = cp_lexer_peek_token (parser->lexer);
720 /* We allow tail attributes for the method. */
721 if (token->keyword == RID_ATTRIBUTE)
723 if (*attributes == NULL_TREE)
725 *attributes = cp_parser_attributes_opt (parser);
726 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
727 || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
731 /* We have an error, but parse the attributes, so that we can
733 *attributes = cp_parser_attributes_opt (parser);
735 cp_parser_error (parser,
736 "method attributes must be specified at the end");
737 return error_mark_node;
743 /* Parse a linkage specification, a pragma, an extra semicolon or a block. */
746 cp_parser_objc_interstitial_code (cp_parser* parser)
748 cp_token *token = cp_lexer_peek_token (parser->lexer);
750 /* If the next token is `extern' and the following token is a string
751 literal, then we have a linkage specification. */
752 if (token->keyword == RID_EXTERN
753 && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
754 cp_parser_linkage_specification (parser);
755 /* Handle #pragma, if any. */
756 else if (token->type == CPP_PRAGMA)
757 cp_parser_pragma (parser, pragma_external);
758 /* Allow stray semicolons. */
759 else if (token->type == CPP_SEMICOLON)
760 cp_lexer_consume_token (parser->lexer);
761 /* Mark methods as optional or required, when building protocols. */
762 else if (token->keyword == RID_AT_OPTIONAL)
764 cp_lexer_consume_token (parser->lexer);
765 objc_set_method_opt (true);
767 else if (token->keyword == RID_AT_REQUIRED)
769 cp_lexer_consume_token (parser->lexer);
770 objc_set_method_opt (false);
772 else if (token->keyword == RID_NAMESPACE)
773 cp_parser_namespace_definition (parser);
774 /* Other stray characters must generate errors. */
775 else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
777 cp_lexer_consume_token (parser->lexer);
778 error ("stray %qs between Objective-C++ methods",
779 token->type == CPP_OPEN_BRACE ? "{" : "}");
781 /* Finally, try to parse a block-declaration, or a function-definition. */
783 cp_parser_block_declaration (parser, /*statement_p=*/false);
786 /* Parse a method signature. */
789 cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
791 tree rettype, kwdparms, optparms;
792 bool ellipsis = false;
793 bool is_class_method;
795 is_class_method = cp_parser_objc_method_type (parser);
796 rettype = cp_parser_objc_typename (parser);
797 *attributes = NULL_TREE;
798 kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
799 if (kwdparms == error_mark_node)
800 return error_mark_node;
801 optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
802 if (optparms == error_mark_node)
803 return error_mark_node;
805 return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
809 cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
812 cp_lexer_save_tokens (parser->lexer);
813 tattr = cp_parser_attributes_opt (parser);
816 /* If the attributes are followed by a method introducer, this is not allowed.
817 Dump the attributes and flag the situation. */
818 if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
819 || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
822 /* Otherwise, the attributes introduce some interstitial code, possibly so
823 rewind to allow that check. */
824 cp_lexer_rollback_tokens (parser->lexer);
828 /* Parse an Objective-C method prototype list. */
831 cp_parser_objc_method_prototype_list (cp_parser* parser)
833 cp_token *token = cp_lexer_peek_token (parser->lexer);
835 while (token->keyword != RID_AT_END && token->type != CPP_EOF)
837 if (token->type == CPP_PLUS || token->type == CPP_MINUS)
839 tree attributes, sig;
840 bool is_class_method;
841 if (token->type == CPP_PLUS)
842 is_class_method = true;
844 is_class_method = false;
845 sig = cp_parser_objc_method_signature (parser, &attributes);
846 if (sig == error_mark_node)
848 cp_parser_skip_to_end_of_block_or_statement (parser);
849 token = cp_lexer_peek_token (parser->lexer);
852 objc_add_method_declaration (is_class_method, sig, attributes);
853 cp_parser_consume_semicolon_at_end_of_statement (parser);
855 else if (token->keyword == RID_AT_PROPERTY)
856 cp_parser_objc_at_property_declaration (parser);
857 else if (token->keyword == RID_ATTRIBUTE
858 && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
859 warning_at (cp_lexer_peek_token (parser->lexer)->location,
861 "prefix attributes are ignored for methods");
863 /* Allow for interspersed non-ObjC++ code. */
864 cp_parser_objc_interstitial_code (parser);
866 token = cp_lexer_peek_token (parser->lexer);
869 if (token->type != CPP_EOF)
870 cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
872 cp_parser_error (parser, "expected %<@end%>");
874 objc_finish_interface ();
877 /* Parse an Objective-C method definition list. */
880 cp_parser_objc_method_definition_list (cp_parser* parser)
882 cp_token *token = cp_lexer_peek_token (parser->lexer);
884 while (token->keyword != RID_AT_END && token->type != CPP_EOF)
888 if (token->type == CPP_PLUS || token->type == CPP_MINUS)
892 bool is_class_method;
893 if (token->type == CPP_PLUS)
894 is_class_method = true;
896 is_class_method = false;
897 push_deferring_access_checks (dk_deferred);
898 sig = cp_parser_objc_method_signature (parser, &attribute);
899 if (sig == error_mark_node)
901 cp_parser_skip_to_end_of_block_or_statement (parser);
902 token = cp_lexer_peek_token (parser->lexer);
905 objc_start_method_definition (is_class_method, sig, attribute);
907 /* For historical reasons, we accept an optional semicolon. */
908 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
909 cp_lexer_consume_token (parser->lexer);
911 ptk = cp_lexer_peek_token (parser->lexer);
912 if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
913 || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
915 perform_deferred_access_checks ();
916 stop_deferring_access_checks ();
917 meth = cp_parser_function_definition_after_declarator (parser,
919 pop_deferring_access_checks ();
920 objc_finish_method_definition (meth);
923 /* The following case will be removed once @synthesize is
924 completely implemented. */
925 else if (token->keyword == RID_AT_PROPERTY)
926 cp_parser_objc_at_property_declaration (parser);
927 else if (token->keyword == RID_AT_SYNTHESIZE)
928 cp_parser_objc_at_synthesize_declaration (parser);
929 else if (token->keyword == RID_AT_DYNAMIC)
930 cp_parser_objc_at_dynamic_declaration (parser);
931 else if (token->keyword == RID_ATTRIBUTE
932 && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
933 warning_at (token->location, OPT_Wattributes,
934 "prefix attributes are ignored for methods");
936 /* Allow for interspersed non-ObjC++ code. */
937 cp_parser_objc_interstitial_code (parser);
939 token = cp_lexer_peek_token (parser->lexer);
942 if (token->type != CPP_EOF)
943 cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
945 cp_parser_error (parser, "expected %<@end%>");
947 objc_finish_implementation ();
950 /* Parse Objective-C ivars. */
953 cp_parser_objc_class_ivars (cp_parser* parser)
955 cp_token *token = cp_lexer_peek_token (parser->lexer);
957 if (token->type != CPP_OPEN_BRACE)
958 return; /* No ivars specified. */
960 cp_lexer_consume_token (parser->lexer); /* Eat '{'. */
961 token = cp_lexer_peek_token (parser->lexer);
963 while (token->type != CPP_CLOSE_BRACE
964 && token->keyword != RID_AT_END && token->type != CPP_EOF)
966 cp_decl_specifier_seq declspecs;
967 int decl_class_or_enum_p;
968 tree prefix_attributes;
970 cp_parser_objc_visibility_spec (parser);
972 if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
975 cp_parser_decl_specifier_seq (parser,
976 CP_PARSER_FLAGS_OPTIONAL,
978 &decl_class_or_enum_p);
980 /* auto, register, static, extern, mutable. */
981 if (declspecs.storage_class != sc_none)
983 cp_parser_error (parser, "invalid type for instance variable");
984 declspecs.storage_class = sc_none;
988 if (declspecs.specs[(int) ds_thread])
990 cp_parser_error (parser, "invalid type for instance variable");
991 declspecs.specs[(int) ds_thread] = 0;
995 if (declspecs.specs[(int) ds_typedef])
997 cp_parser_error (parser, "invalid type for instance variable");
998 declspecs.specs[(int) ds_typedef] = 0;
1001 prefix_attributes = declspecs.attributes;
1002 declspecs.attributes = NULL_TREE;
1004 /* Keep going until we hit the `;' at the end of the
1006 while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
1008 tree width = NULL_TREE, attributes, first_attribute, decl;
1009 cp_declarator *declarator = NULL;
1010 int ctor_dtor_or_conv_p;
1012 /* Check for a (possibly unnamed) bitfield declaration. */
1013 token = cp_lexer_peek_token (parser->lexer);
1014 if (token->type == CPP_COLON)
1017 if (token->type == CPP_NAME
1018 && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
1021 /* Get the name of the bitfield. */
1022 declarator = make_id_declarator (NULL_TREE,
1023 cp_parser_identifier (parser),
1027 cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
1028 /* Get the width of the bitfield. */
1030 = cp_parser_constant_expression (parser,
1031 /*allow_non_constant=*/false,
1036 /* Parse the declarator. */
1038 = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
1039 &ctor_dtor_or_conv_p,
1040 /*parenthesized_p=*/NULL,
1041 /*member_p=*/false);
1044 /* Look for attributes that apply to the ivar. */
1045 attributes = cp_parser_attributes_opt (parser);
1046 /* Remember which attributes are prefix attributes and
1048 first_attribute = attributes;
1049 /* Combine the attributes. */
1050 attributes = chainon (prefix_attributes, attributes);
1053 /* Create the bitfield declaration. */
1054 decl = grokbitfield (declarator, &declspecs,
1058 decl = grokfield (declarator, &declspecs,
1059 NULL_TREE, /*init_const_expr_p=*/false,
1060 NULL_TREE, attributes);
1062 /* Add the instance variable. */
1063 objc_add_instance_variable (decl);
1065 /* Reset PREFIX_ATTRIBUTES. */
1066 while (attributes && TREE_CHAIN (attributes) != first_attribute)
1067 attributes = TREE_CHAIN (attributes);
1069 TREE_CHAIN (attributes) = NULL_TREE;
1071 token = cp_lexer_peek_token (parser->lexer);
1073 if (token->type == CPP_COMMA)
1075 cp_lexer_consume_token (parser->lexer); /* Eat ','. */
1081 cp_parser_consume_semicolon_at_end_of_statement (parser);
1082 token = cp_lexer_peek_token (parser->lexer);
1085 if (token->keyword == RID_AT_END)
1086 cp_parser_error (parser, "expected %<}%>");
1088 /* Do not consume the RID_AT_END, so it will be read again as terminating
1089 the @interface of @implementation. */
1090 if (token->keyword != RID_AT_END && token->type != CPP_EOF)
1091 cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
1093 /* For historical reasons, we accept an optional semicolon. */
1094 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
1095 cp_lexer_consume_token (parser->lexer);
1098 /* Parse an Objective-C protocol declaration. */
1101 cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
1103 tree proto, protorefs;
1106 cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
1107 if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
1109 tok = cp_lexer_peek_token (parser->lexer);
1110 error_at (tok->location, "identifier expected after %<@protocol%>");
1114 /* See if we have a forward declaration or a definition. */
1115 tok = cp_lexer_peek_nth_token (parser->lexer, 2);
1117 /* Try a forward declaration first. */
1118 if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
1120 objc_declare_protocols (cp_parser_objc_identifier_list (parser),
1123 cp_parser_consume_semicolon_at_end_of_statement (parser);
1126 /* Ok, we got a full-fledged definition (or at least should). */
1129 proto = cp_parser_identifier (parser);
1130 protorefs = cp_parser_objc_protocol_refs_opt (parser);
1131 objc_start_protocol (proto, protorefs, attributes);
1132 cp_parser_objc_method_prototype_list (parser);
1136 /* Parse an Objective-C superclass or category. */
1139 cp_parser_objc_superclass_or_category (cp_parser *parser,
1142 tree *categ, bool *is_class_extension)
1144 cp_token *next = cp_lexer_peek_token (parser->lexer);
1146 *super = *categ = NULL_TREE;
1147 *is_class_extension = false;
1148 if (next->type == CPP_COLON)
1150 cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
1151 *super = cp_parser_identifier (parser);
1153 else if (next->type == CPP_OPEN_PAREN)
1155 cp_lexer_consume_token (parser->lexer); /* Eat '('. */
1157 /* If there is no category name, and this is an @interface, we
1158 have a class extension. */
1159 if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
1162 *is_class_extension = true;
1165 *categ = cp_parser_identifier (parser);
1167 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
1171 /* Parse an Objective-C class interface. */
1174 cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
1176 tree name, super, categ, protos;
1177 bool is_class_extension;
1179 cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
1180 name = cp_parser_identifier (parser);
1181 if (name == error_mark_node)
1183 /* It's hard to recover because even if valid @interface stuff
1184 is to follow, we can't compile it (or validate it) if we
1185 don't even know which class it refers to. Let's assume this
1186 was a stray '@interface' token in the stream and skip it.
1190 cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
1191 &is_class_extension);
1192 protos = cp_parser_objc_protocol_refs_opt (parser);
1194 /* We have either a class or a category on our hands. */
1195 if (categ || is_class_extension)
1196 objc_start_category_interface (name, categ, protos, attributes);
1199 objc_start_class_interface (name, super, protos, attributes);
1200 /* Handle instance variable declarations, if any. */
1201 cp_parser_objc_class_ivars (parser);
1202 objc_continue_interface ();
1205 cp_parser_objc_method_prototype_list (parser);
1208 /* Parse an Objective-C class implementation. */
1211 cp_parser_objc_class_implementation (cp_parser* parser)
1213 tree name, super, categ;
1214 bool is_class_extension;
1216 cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
1217 name = cp_parser_identifier (parser);
1218 if (name == error_mark_node)
1220 /* It's hard to recover because even if valid @implementation
1221 stuff is to follow, we can't compile it (or validate it) if
1222 we don't even know which class it refers to. Let's assume
1223 this was a stray '@implementation' token in the stream and
1228 cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
1229 &is_class_extension);
1231 /* We have either a class or a category on our hands. */
1233 objc_start_category_implementation (name, categ);
1236 objc_start_class_implementation (name, super);
1237 /* Handle instance variable declarations, if any. */
1238 cp_parser_objc_class_ivars (parser);
1239 objc_continue_implementation ();
1242 cp_parser_objc_method_definition_list (parser);
1245 /* Consume the @end token and finish off the implementation. */
1248 cp_parser_objc_end_implementation (cp_parser* parser)
1250 cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
1251 objc_finish_implementation ();
1254 /* Parse an Objective-C declaration. */
1257 cp_parser_objc_declaration (cp_parser* parser, tree attributes)
1259 /* Try to figure out what kind of declaration is present. */
1260 cp_token *kwd = cp_lexer_peek_token (parser->lexer);
1263 switch (kwd->keyword)
1268 error_at (kwd->location, "attributes may not be specified before"
1269 " the %<@%D%> Objective-C++ keyword",
1273 case RID_AT_IMPLEMENTATION:
1274 warning_at (kwd->location, OPT_Wattributes,
1275 "prefix attributes are ignored before %<@%D%>",
1282 switch (kwd->keyword)
1285 cp_parser_objc_alias_declaration (parser);
1288 cp_parser_objc_class_declaration (parser);
1290 case RID_AT_PROTOCOL:
1291 cp_parser_objc_protocol_declaration (parser, attributes);
1293 case RID_AT_INTERFACE:
1294 cp_parser_objc_class_interface (parser, attributes);
1296 case RID_AT_IMPLEMENTATION:
1297 cp_parser_objc_class_implementation (parser);
1300 cp_parser_objc_end_implementation (parser);
1303 error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
1305 cp_parser_skip_to_end_of_block_or_statement (parser);
1309 /* Parse an Objective-C try-catch-finally statement.
1311 objc-try-catch-finally-stmt:
1312 @try compound-statement objc-catch-clause-seq [opt]
1313 objc-finally-clause [opt]
1315 objc-catch-clause-seq:
1316 objc-catch-clause objc-catch-clause-seq [opt]
1319 @catch ( objc-exception-declaration ) compound-statement
1321 objc-finally-clause:
1322 @finally compound-statement
1324 objc-exception-declaration:
1325 parameter-declaration
1328 where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
1332 PS: This function is identical to c_parser_objc_try_catch_finally_statement
1333 for C. Keep them in sync. */
1336 cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
1338 location_t location;
1341 cp_parser_require_keyword (parser, RID_AT_TRY, RT_AT_TRY);
1342 location = cp_lexer_peek_token (parser->lexer)->location;
1343 objc_maybe_warn_exceptions (location);
1344 /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
1345 node, lest it get absorbed into the surrounding block. */
1346 stmt = push_stmt_list ();
1347 cp_parser_compound_statement (parser, NULL, false);
1348 objc_begin_try_stmt (location, pop_stmt_list (stmt));
1350 while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
1352 cp_parameter_declarator *parm;
1353 tree parameter_declaration = error_mark_node;
1354 bool seen_open_paren = false;
1356 cp_lexer_consume_token (parser->lexer);
1357 if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
1358 seen_open_paren = true;
1359 if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
1361 /* We have "@catch (...)" (where the '...' are literally
1362 what is in the code). Skip the '...'.
1363 parameter_declaration is set to NULL_TREE, and
1364 objc_being_catch_clauses() knows that that means
1366 cp_lexer_consume_token (parser->lexer);
1367 parameter_declaration = NULL_TREE;
1371 /* We have "@catch (NSException *exception)" or something
1372 like that. Parse the parameter declaration. */
1373 parm = cp_parser_parameter_declaration (parser, false, NULL);
1375 parameter_declaration = error_mark_node;
1377 parameter_declaration = grokdeclarator (parm->declarator,
1378 &parm->decl_specifiers,
1379 PARM, /*initialized=*/0,
1382 if (seen_open_paren)
1383 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
1386 /* If there was no open parenthesis, we are recovering from
1387 an error, and we are trying to figure out what mistake
1388 the user has made. */
1390 /* If there is an immediate closing parenthesis, the user
1391 probably forgot the opening one (ie, they typed "@catch
1392 NSException *e)". Parse the closing parenthesis and keep
1394 if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
1395 cp_lexer_consume_token (parser->lexer);
1397 /* If these is no immediate closing parenthesis, the user
1398 probably doesn't know that parenthesis are required at
1399 all (ie, they typed "@catch NSException *e"). So, just
1400 forget about the closing parenthesis and keep going. */
1402 objc_begin_catch_clause (parameter_declaration);
1403 cp_parser_compound_statement (parser, NULL, false);
1404 objc_finish_catch_clause ();
1406 if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
1408 cp_lexer_consume_token (parser->lexer);
1409 location = cp_lexer_peek_token (parser->lexer)->location;
1410 /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
1411 node, lest it get absorbed into the surrounding block. */
1412 stmt = push_stmt_list ();
1413 cp_parser_compound_statement (parser, NULL, false);
1414 objc_build_finally_clause (location, pop_stmt_list (stmt));
1417 return objc_finish_try_stmt ();
1420 /* Parse an Objective-C synchronized statement.
1422 objc-synchronized-stmt:
1423 @synchronized ( expression ) compound-statement
1425 Returns NULL_TREE. */
1428 cp_parser_objc_synchronized_statement (cp_parser *parser)
1430 location_t location;
1433 cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
1435 location = cp_lexer_peek_token (parser->lexer)->location;
1436 objc_maybe_warn_exceptions (location);
1437 cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
1438 lock = cp_parser_expression (parser, false, NULL);
1439 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
1441 /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
1442 node, lest it get absorbed into the surrounding block. */
1443 stmt = push_stmt_list ();
1444 cp_parser_compound_statement (parser, NULL, false);
1446 return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
1449 /* Parse an Objective-C throw statement.
1452 @throw assignment-expression [opt] ;
1454 Returns a constructed '@throw' statement. */
1457 cp_parser_objc_throw_statement (cp_parser *parser)
1459 tree expr = NULL_TREE;
1460 location_t loc = cp_lexer_peek_token (parser->lexer)->location;
1462 cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
1464 if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
1465 expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
1467 cp_parser_consume_semicolon_at_end_of_statement (parser);
1469 return objc_build_throw_stmt (loc, expr);
1472 /* Parse an Objective-C statement. */
1475 cp_parser_objc_statement (cp_parser * parser)
1477 /* Try to figure out what kind of declaration is present. */
1478 cp_token *kwd = cp_lexer_peek_token (parser->lexer);
1480 switch (kwd->keyword)
1483 return cp_parser_objc_try_catch_finally_statement (parser);
1484 case RID_AT_SYNCHRONIZED:
1485 return cp_parser_objc_synchronized_statement (parser);
1487 return cp_parser_objc_throw_statement (parser);
1489 error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
1491 cp_parser_skip_to_end_of_block_or_statement (parser);
1494 return error_mark_node;
1497 /* If we are compiling ObjC++ and we see an __attribute__ we neeed to
1498 look ahead to see if an objc keyword follows the attributes. This
1499 is to detect the use of prefix attributes on ObjC @interface and
1503 cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
1505 cp_lexer_save_tokens (parser->lexer);
1506 *attrib = cp_parser_attributes_opt (parser);
1507 gcc_assert (*attrib);
1508 if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
1510 cp_lexer_commit_tokens (parser->lexer);
1513 cp_lexer_rollback_tokens (parser->lexer);
1517 /* This routine is a minimal replacement for
1518 c_parser_struct_declaration () used when parsing the list of
1519 types/names or ObjC++ properties. For example, when parsing the
1522 @property (readonly) int a, b, c;
1524 this function is responsible for parsing "int a, int b, int c" and
1525 returning the declarations as CHAIN of DECLs.
1527 TODO: Share this code with cp_parser_objc_class_ivars. It's very
1530 cp_parser_objc_struct_declaration (cp_parser *parser)
1532 tree decls = NULL_TREE;
1533 cp_decl_specifier_seq declspecs;
1534 int decl_class_or_enum_p;
1535 tree prefix_attributes;
1537 cp_parser_decl_specifier_seq (parser,
1538 CP_PARSER_FLAGS_NONE,
1540 &decl_class_or_enum_p);
1542 if (declspecs.type == error_mark_node)
1543 return error_mark_node;
1545 /* auto, register, static, extern, mutable. */
1546 if (declspecs.storage_class != sc_none)
1548 cp_parser_error (parser, "invalid type for property");
1549 declspecs.storage_class = sc_none;
1553 if (declspecs.specs[(int) ds_thread])
1555 cp_parser_error (parser, "invalid type for property");
1556 declspecs.specs[(int) ds_thread] = 0;
1560 if (declspecs.specs[(int) ds_typedef])
1562 cp_parser_error (parser, "invalid type for property");
1563 declspecs.specs[(int) ds_typedef] = 0;
1566 prefix_attributes = declspecs.attributes;
1567 declspecs.attributes = NULL_TREE;
1569 /* Keep going until we hit the `;' at the end of the declaration. */
1570 while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
1572 tree attributes, first_attribute, decl;
1573 cp_declarator *declarator;
1576 /* Parse the declarator. */
1577 declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
1580 /* Look for attributes that apply to the ivar. */
1581 attributes = cp_parser_attributes_opt (parser);
1582 /* Remember which attributes are prefix attributes and
1584 first_attribute = attributes;
1585 /* Combine the attributes. */
1586 attributes = chainon (prefix_attributes, attributes);
1588 decl = grokfield (declarator, &declspecs,
1589 NULL_TREE, /*init_const_expr_p=*/false,
1590 NULL_TREE, attributes);
1592 if (decl == error_mark_node || decl == NULL_TREE)
1593 return error_mark_node;
1595 /* Reset PREFIX_ATTRIBUTES. */
1596 while (attributes && TREE_CHAIN (attributes) != first_attribute)
1597 attributes = TREE_CHAIN (attributes);
1599 TREE_CHAIN (attributes) = NULL_TREE;
1601 DECL_CHAIN (decl) = decls;
1604 token = cp_lexer_peek_token (parser->lexer);
1605 if (token->type == CPP_COMMA)
1607 cp_lexer_consume_token (parser->lexer); /* Eat ','. */
1616 /* Parse an Objective-C @property declaration. The syntax is:
1618 objc-property-declaration:
1619 '@property' objc-property-attributes[opt] struct-declaration ;
1621 objc-property-attributes:
1622 '(' objc-property-attribute-list ')'
1624 objc-property-attribute-list:
1625 objc-property-attribute
1626 objc-property-attribute-list, objc-property-attribute
1628 objc-property-attribute
1629 'getter' = identifier
1630 'setter' = identifier
1639 @property NSString *name;
1640 @property (readonly) id object;
1641 @property (retain, nonatomic, getter=getTheName) id name;
1642 @property int a, b, c;
1644 PS: This function is identical to
1645 c_parser_objc_at_property_declaration for C. Keep them in sync. */
1647 cp_parser_objc_at_property_declaration (cp_parser *parser)
1649 /* The following variables hold the attributes of the properties as
1650 parsed. They are 'false' or 'NULL_TREE' if the attribute was not
1651 seen. When we see an attribute, we set them to 'true' (if they
1652 are boolean properties) or to the identifier (if they have an
1653 argument, ie, for getter and setter). Note that here we only
1654 parse the list of attributes, check the syntax and accumulate the
1655 attributes that we find. objc_add_property_declaration() will
1656 then process the information. */
1657 bool property_assign = false;
1658 bool property_copy = false;
1659 tree property_getter_ident = NULL_TREE;
1660 bool property_nonatomic = false;
1661 bool property_readonly = false;
1662 bool property_readwrite = false;
1663 bool property_retain = false;
1664 tree property_setter_ident = NULL_TREE;
1666 /* 'properties' is the list of properties that we read. Usually a
1667 single one, but maybe more (eg, in "@property int a, b, c;" there
1672 loc = cp_lexer_peek_token (parser->lexer)->location;
1674 cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
1676 /* Parse the optional attribute list... */
1677 if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
1680 cp_lexer_consume_token (parser->lexer);
1684 bool syntax_error = false;
1685 cp_token *token = cp_lexer_peek_token (parser->lexer);
1688 if (token->type != CPP_NAME)
1690 cp_parser_error (parser, "expected identifier");
1693 keyword = C_RID_CODE (token->u.value);
1694 cp_lexer_consume_token (parser->lexer);
1697 case RID_ASSIGN: property_assign = true; break;
1698 case RID_COPY: property_copy = true; break;
1699 case RID_NONATOMIC: property_nonatomic = true; break;
1700 case RID_READONLY: property_readonly = true; break;
1701 case RID_READWRITE: property_readwrite = true; break;
1702 case RID_RETAIN: property_retain = true; break;
1706 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
1708 if (keyword == RID_GETTER)
1709 cp_parser_error (parser,
1710 "missing %<=%> (after %<getter%> attribute)");
1712 cp_parser_error (parser,
1713 "missing %<=%> (after %<setter%> attribute)");
1714 syntax_error = true;
1717 cp_lexer_consume_token (parser->lexer); /* eat the = */
1718 if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
1720 cp_parser_error (parser, "expected identifier");
1721 syntax_error = true;
1724 if (keyword == RID_SETTER)
1726 if (property_setter_ident != NULL_TREE)
1727 cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
1729 property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
1730 cp_lexer_consume_token (parser->lexer);
1731 if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
1732 cp_parser_error (parser, "setter name must terminate with %<:%>");
1734 cp_lexer_consume_token (parser->lexer);
1738 if (property_getter_ident != NULL_TREE)
1739 cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
1741 property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
1742 cp_lexer_consume_token (parser->lexer);
1746 cp_parser_error (parser, "unknown property attribute");
1747 syntax_error = true;
1754 if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
1755 cp_lexer_consume_token (parser->lexer);
1760 /* FIXME: "@property (setter, assign);" will generate a spurious
1761 "error: expected ‘)’ before ‘,’ token". This is because
1762 cp_parser_require, unlike the C counterpart, will produce an
1763 error even if we are in error recovery. */
1764 if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
1766 cp_parser_skip_to_closing_parenthesis (parser,
1767 /*recovering=*/true,
1769 /*consume_paren=*/true);
1773 /* ... and the property declaration(s). */
1774 properties = cp_parser_objc_struct_declaration (parser);
1776 if (properties == error_mark_node)
1778 cp_parser_skip_to_end_of_statement (parser);
1779 /* If the next token is now a `;', consume it. */
1780 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
1781 cp_lexer_consume_token (parser->lexer);
1785 if (properties == NULL_TREE)
1786 cp_parser_error (parser, "expected identifier");
1789 /* Comma-separated properties are chained together in
1790 reverse order; add them one by one. */
1791 properties = nreverse (properties);
1793 for (; properties; properties = TREE_CHAIN (properties))
1794 objc_add_property_declaration (loc, copy_node (properties),
1795 property_readonly, property_readwrite,
1796 property_assign, property_retain,
1797 property_copy, property_nonatomic,
1798 property_getter_ident, property_setter_ident);
1801 cp_parser_consume_semicolon_at_end_of_statement (parser);
1804 /* Parse an Objective-C++ @synthesize declaration. The syntax is:
1806 objc-synthesize-declaration:
1807 @synthesize objc-synthesize-identifier-list ;
1809 objc-synthesize-identifier-list:
1810 objc-synthesize-identifier
1811 objc-synthesize-identifier-list, objc-synthesize-identifier
1813 objc-synthesize-identifier
1815 identifier = identifier
1818 @synthesize MyProperty;
1819 @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
1821 PS: This function is identical to c_parser_objc_at_synthesize_declaration
1822 for C. Keep them in sync.
1825 cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
1827 tree list = NULL_TREE;
1829 loc = cp_lexer_peek_token (parser->lexer)->location;
1831 cp_lexer_consume_token (parser->lexer); /* Eat '@synthesize'. */
1834 tree property, ivar;
1835 property = cp_parser_identifier (parser);
1836 if (property == error_mark_node)
1838 cp_parser_consume_semicolon_at_end_of_statement (parser);
1841 if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
1843 cp_lexer_consume_token (parser->lexer);
1844 ivar = cp_parser_identifier (parser);
1845 if (ivar == error_mark_node)
1847 cp_parser_consume_semicolon_at_end_of_statement (parser);
1853 list = chainon (list, build_tree_list (ivar, property));
1854 if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
1855 cp_lexer_consume_token (parser->lexer);
1859 cp_parser_consume_semicolon_at_end_of_statement (parser);
1860 objc_add_synthesize_declaration (loc, list);
1863 /* Parse an Objective-C++ @dynamic declaration. The syntax is:
1865 objc-dynamic-declaration:
1866 @dynamic identifier-list ;
1869 @dynamic MyProperty;
1870 @dynamic MyProperty, AnotherProperty;
1872 PS: This function is identical to c_parser_objc_at_dynamic_declaration
1873 for C. Keep them in sync.
1876 cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
1878 tree list = NULL_TREE;
1880 loc = cp_lexer_peek_token (parser->lexer)->location;
1882 cp_lexer_consume_token (parser->lexer); /* Eat '@dynamic'. */
1886 property = cp_parser_identifier (parser);
1887 if (property == error_mark_node)
1889 cp_parser_consume_semicolon_at_end_of_statement (parser);
1892 list = chainon (list, build_tree_list (NULL, property));
1893 if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
1894 cp_lexer_consume_token (parser->lexer);
1898 cp_parser_consume_semicolon_at_end_of_statement (parser);
1899 objc_add_dynamic_declaration (loc, list);