OSDN Git Service

2011-02-13 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / objcp / plugin / parser.c
1 /* Objective-C++ Parser plugin
2    Copyright (C) 2000, 2001, 2002, 2003, 2004,
3    2005, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
4
5    This file is part of GCC.
6
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)
10    any later version.
11
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.
16
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/>.  */
20
21
22 #ifndef HIDE_OBJC
23
24 /* Objective-C++ Productions */
25
26
27 /* Parse an Objective-C expression, which feeds into a primary-expression
28    above.
29
30    objc-expression:
31      objc-message-expression
32      objc-string-literal
33      objc-encode-expression
34      objc-protocol-expression
35      objc-selector-expression
36
37   Returns a tree representation of the expression.  */
38
39 static tree
40 cp_parser_objc_expression (cp_parser* parser)
41 {
42   /* Try to figure out what kind of declaration is present.  */
43   cp_token *kwd = cp_lexer_peek_token (parser->lexer);
44
45   switch (kwd->type)
46     {
47     case CPP_OPEN_SQUARE:
48       return cp_parser_objc_message_expression (parser);
49
50     case CPP_OBJC_STRING:
51       kwd = cp_lexer_consume_token (parser->lexer);
52       return objc_build_string_object (kwd->u.value);
53
54     case CPP_KEYWORD:
55       switch (kwd->keyword)
56         {
57         case RID_AT_ENCODE:
58           return cp_parser_objc_encode_expression (parser);
59
60         case RID_AT_PROTOCOL:
61           return cp_parser_objc_protocol_expression (parser);
62
63         case RID_AT_SELECTOR:
64           return cp_parser_objc_selector_expression (parser);
65
66         default:
67           break;
68         }
69     default:
70       error_at (kwd->location,
71                 "misplaced %<@%D%> Objective-C++ construct",
72                 kwd->u.value);
73       cp_parser_skip_to_end_of_block_or_statement (parser);
74     }
75
76   return error_mark_node;
77 }
78
79 /* Parse an Objective-C message expression.
80
81    objc-message-expression:
82      [ objc-message-receiver objc-message-args ]
83
84    Returns a representation of an Objective-C message.  */
85
86 static tree
87 cp_parser_objc_message_expression (cp_parser* parser)
88 {
89   tree receiver, messageargs;
90
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);
95
96   return objc_build_message_expr (build_tree_list (receiver, messageargs));
97 }
98
99 /* Parse an objc-message-receiver.
100
101    objc-message-receiver:
102      expression
103      simple-type-specifier
104
105   Returns a representation of the type or expression.  */
106
107 static tree
108 cp_parser_objc_message_receiver (cp_parser* parser)
109 {
110   tree rcv;
111
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);
116
117   if (cp_parser_parse_definitely (parser))
118     return rcv;
119
120   rcv = cp_parser_simple_type_specifier (parser,
121                                          /*decl_specs=*/NULL,
122                                          CP_PARSER_FLAGS_NONE);
123
124   return objc_get_class_reference (rcv);
125 }
126
127 /* Parse the arguments and selectors comprising an Objective-C message.
128
129    objc-message-args:
130      objc-selector
131      objc-selector-args
132      objc-selector-args , objc-comma-args
133
134    objc-selector-args:
135      objc-selector [opt] : assignment-expression
136      objc-selector-args objc-selector [opt] : assignment-expression
137
138    objc-comma-args:
139      assignment-expression
140      objc-comma-args , assignment-expression
141
142    Returns a TREE_LIST, with TREE_PURPOSE containing a list of
143    selector arguments and TREE_VALUE containing a list of comma
144    arguments.  */
145
146 static tree
147 cp_parser_objc_message_args (cp_parser* parser)
148 {
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);
152
153   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
154     {
155       tree selector = NULL_TREE, arg;
156
157       if (token->type != CPP_COLON)
158         selector = cp_parser_objc_selector (parser);
159
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);
164
165       maybe_unary_selector_p = false;
166       cp_parser_require (parser, CPP_COLON, RT_COLON);
167       arg = cp_parser_assignment_expression (parser, false, NULL);
168
169       sel_args
170         = chainon (sel_args,
171                    build_tree_list (selector, arg));
172
173       token = cp_lexer_peek_token (parser->lexer);
174     }
175
176   /* Handle non-selector arguments, if any. */
177   while (token->type == CPP_COMMA)
178     {
179       tree arg;
180
181       cp_lexer_consume_token (parser->lexer);
182       arg = cp_parser_assignment_expression (parser, false, NULL);
183
184       addl_args
185         = chainon (addl_args,
186                    build_tree_list (NULL_TREE, arg));
187
188       token = cp_lexer_peek_token (parser->lexer);
189     }
190
191   if (sel_args == NULL_TREE && addl_args == NULL_TREE)
192     {
193       cp_parser_error (parser, "objective-c++ message argument(s) are expected");
194       return build_tree_list (error_mark_node, error_mark_node);
195     }
196
197   return build_tree_list (sel_args, addl_args);
198 }
199
200 /* Parse an Objective-C encode expression.
201
202    objc-encode-expression:
203      @encode objc-typename
204
205    Returns an encoded representation of the type argument.  */
206
207 static tree
208 cp_parser_objc_encode_expression (cp_parser* parser)
209 {
210   tree type;
211   cp_token *token;
212
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);
218
219   if (!type)
220     {
221       error_at (token->location, 
222                 "%<@encode%> must specify a type as an argument");
223       return error_mark_node;
224     }
225
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.
231   */
232   if (dependent_type_p (type))
233     {
234       tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
235       TREE_READONLY (value) = 1;
236       return value;
237     }
238
239   return objc_build_encode_expr (type);
240 }
241
242 /* Parse an Objective-C @defs expression.  */
243
244 static tree
245 cp_parser_objc_defs_expression (cp_parser *parser)
246 {
247   tree name;
248
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);
253
254   return objc_get_class_ivars (name);
255 }
256
257 /* Parse an Objective-C protocol expression.
258
259   objc-protocol-expression:
260     @protocol ( identifier )
261
262   Returns a representation of the protocol expression.  */
263
264 static tree
265 cp_parser_objc_protocol_expression (cp_parser* parser)
266 {
267   tree proto;
268
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);
273
274   return objc_build_protocol_expr (proto);
275 }
276
277 /* Parse an Objective-C selector expression.
278
279    objc-selector-expression:
280      @selector ( objc-method-signature )
281
282    objc-method-signature:
283      objc-selector
284      objc-selector-seq
285
286    objc-selector-seq:
287      objc-selector :
288      objc-selector-seq objc-selector :
289
290   Returns a representation of the method selector.  */
291
292 static tree
293 cp_parser_objc_selector_expression (cp_parser* parser)
294 {
295   tree sel_seq = NULL_TREE;
296   bool maybe_unary_selector_p = true;
297   cp_token *token;
298   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
299
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);
303
304   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
305          || token->type == CPP_SCOPE)
306     {
307       tree selector = NULL_TREE;
308
309       if (token->type != CPP_COLON
310           || token->type == CPP_SCOPE)
311         selector = cp_parser_objc_selector (parser);
312
313       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
314           && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
315         {
316           /* Detect if we have a unary selector.  */
317           if (maybe_unary_selector_p)
318             {
319               sel_seq = selector;
320               goto finish_selector;
321             }
322           else
323             {
324               cp_parser_error (parser, "expected %<:%>");
325             }
326         }
327       maybe_unary_selector_p = false;
328       token = cp_lexer_consume_token (parser->lexer);
329
330       if (token->type == CPP_SCOPE)
331         {
332           sel_seq
333             = chainon (sel_seq,
334                        build_tree_list (selector, NULL_TREE));
335           sel_seq
336             = chainon (sel_seq,
337                        build_tree_list (NULL_TREE, NULL_TREE));
338         }
339       else
340         sel_seq
341           = chainon (sel_seq,
342                      build_tree_list (selector, NULL_TREE));
343
344       token = cp_lexer_peek_token (parser->lexer);
345     }
346
347  finish_selector:
348   cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
349
350   return objc_build_selector_expr (loc, sel_seq);
351 }
352
353 /* Parse a list of identifiers.
354
355    objc-identifier-list:
356      identifier
357      objc-identifier-list , identifier
358
359    Returns a TREE_LIST of identifier nodes.  */
360
361 static tree
362 cp_parser_objc_identifier_list (cp_parser* parser)
363 {
364   tree identifier;
365   tree list;
366   cp_token *sep;
367
368   identifier = cp_parser_identifier (parser);
369   if (identifier == error_mark_node)
370     return error_mark_node;      
371
372   list = build_tree_list (NULL_TREE, identifier);
373   sep = cp_lexer_peek_token (parser->lexer);
374
375   while (sep->type == CPP_COMMA)
376     {
377       cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
378       identifier = cp_parser_identifier (parser);
379       if (identifier == error_mark_node)
380         return list;
381
382       list = chainon (list, build_tree_list (NULL_TREE,
383                                              identifier));
384       sep = cp_lexer_peek_token (parser->lexer);
385     }
386   
387   return list;
388 }
389
390 /* Parse an Objective-C alias declaration.
391
392    objc-alias-declaration:
393      @compatibility_alias identifier identifier ;
394
395    This function registers the alias mapping with the Objective-C front end.
396    It returns nothing.  */
397
398 static void
399 cp_parser_objc_alias_declaration (cp_parser* parser)
400 {
401   tree alias, orig;
402
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);
408 }
409
410 /* Parse an Objective-C class forward-declaration.
411
412    objc-class-declaration:
413      @class objc-identifier-list ;
414
415    The function registers the forward declarations with the Objective-C
416    front end.  It returns nothing.  */
417
418 static void
419 cp_parser_objc_class_declaration (cp_parser* parser)
420 {
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);
424 }
425
426 /* Parse a list of Objective-C protocol references.
427
428    objc-protocol-refs-opt:
429      objc-protocol-refs [opt]
430
431    objc-protocol-refs:
432      < objc-identifier-list >
433
434    Returns a TREE_LIST of identifiers, if any.  */
435
436 static tree
437 cp_parser_objc_protocol_refs_opt (cp_parser* parser)
438 {
439   tree protorefs = NULL_TREE;
440
441   if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
442     {
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);
446     }
447
448   return protorefs;
449 }
450
451 /* Parse a Objective-C visibility specification.  */
452
453 static void
454 cp_parser_objc_visibility_spec (cp_parser* parser)
455 {
456   cp_token *vis = cp_lexer_peek_token (parser->lexer);
457
458   switch (vis->keyword)
459     {
460     case RID_AT_PRIVATE:
461       objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
462       break;
463     case RID_AT_PROTECTED:
464       objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
465       break;
466     case RID_AT_PUBLIC:
467       objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
468       break;
469     case RID_AT_PACKAGE:
470       objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
471       break;
472     default:
473       return;
474     }
475
476   /* Eat '@private'/'@protected'/'@public'.  */
477   cp_lexer_consume_token (parser->lexer);
478 }
479
480 /* Parse an Objective-C method type.  Return 'true' if it is a class
481    (+) method, and 'false' if it is an instance (-) method.  */
482
483 static inline bool
484 cp_parser_objc_method_type (cp_parser* parser)
485 {
486   if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
487     return true;
488   else
489     return false;
490 }
491
492 /* Parse an Objective-C protocol qualifier.  */
493
494 static tree
495 cp_parser_objc_protocol_qualifiers (cp_parser* parser)
496 {
497   tree quals = NULL_TREE, node;
498   cp_token *token = cp_lexer_peek_token (parser->lexer);
499
500   node = token->u.value;
501
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]))
509     {
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;
514     }
515
516   return quals;
517 }
518
519 /* Parse an Objective-C typename.  */
520
521 static tree
522 cp_parser_objc_typename (cp_parser* parser)
523 {
524   tree type_name = NULL_TREE;
525
526   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
527     {
528       tree proto_quals, cp_type = NULL_TREE;
529
530       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
531       proto_quals = cp_parser_objc_protocol_qualifiers (parser);
532
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))
536         {
537           cp_type = cp_parser_type_id (parser);
538           
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
542              'id'.  */
543           if (cp_type == error_mark_node)
544             {
545               cp_type = NULL_TREE;
546               /* We need to skip to the closing parenthesis as
547                  cp_parser_type_id() does not seem to do it for
548                  us.  */
549               cp_parser_skip_to_closing_parenthesis (parser,
550                                                      /*recovering=*/true,
551                                                      /*or_comma=*/false,
552                                                      /*consume_paren=*/false);
553             }
554         }
555
556       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
557       type_name = build_tree_list (proto_quals, cp_type);
558     }
559
560   return type_name;
561 }
562
563 /* Check to see if TYPE refers to an Objective-C selector name.  */
564
565 static bool
566 cp_parser_objc_selector_p (enum cpp_ttype type)
567 {
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);
573 }
574
575 /* Parse an Objective-C selector.  */
576
577 static tree
578 cp_parser_objc_selector (cp_parser* parser)
579 {
580   cp_token *token = cp_lexer_consume_token (parser->lexer);
581
582   if (!cp_parser_objc_selector_p (token->type))
583     {
584       error_at (token->location, "invalid Objective-C++ selector name");
585       return error_mark_node;
586     }
587
588   /* C++ operator names are allowed to appear in ObjC selectors.  */
589   switch (token->type)
590     {
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;
603     }
604 }
605
606 /* Parse an Objective-C params list.  */
607
608 static tree
609 cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
610 {
611   tree params = NULL_TREE;
612   bool maybe_unary_selector_p = true;
613   cp_token *token = cp_lexer_peek_token (parser->lexer);
614
615   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
616     {
617       tree selector = NULL_TREE, type_name, identifier;
618       tree parm_attr = NULL_TREE;
619
620       if (token->keyword == RID_ATTRIBUTE)
621         break;
622
623       if (token->type != CPP_COLON)
624         selector = cp_parser_objc_selector (parser);
625
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))
629         {
630           params = selector; /* Might be followed by attributes.  */
631           break;
632         }
633
634       maybe_unary_selector_p = false;
635       if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
636         {
637           /* Something went quite wrong.  There should be a colon
638              here, but there is not.  Stop parsing parameters.  */
639           break;
640         }
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);
646
647       params
648         = chainon (params,
649                    objc_build_keyword_decl (selector,
650                                             type_name,
651                                             identifier,
652                                             parm_attr));
653
654       token = cp_lexer_peek_token (parser->lexer);
655     }
656
657   if (params == NULL_TREE)
658     {
659       cp_parser_error (parser, "objective-c++ method declaration is expected");
660       return error_mark_node;
661     }
662
663   /* We allow tail attributes for the method.  */
664   if (token->keyword == RID_ATTRIBUTE)
665     {
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))
669         return params;
670       cp_parser_error (parser, 
671                        "method attributes must be specified at the end");
672       return error_mark_node;
673     }
674
675   if (params == NULL_TREE)
676     {
677       cp_parser_error (parser, "objective-c++ method declaration is expected");
678       return error_mark_node;
679     }
680   return params;
681 }
682
683 /* Parse the non-keyword Objective-C params.  */
684
685 static tree
686 cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, 
687                                        tree* attributes)
688 {
689   tree params = make_node (TREE_LIST);
690   cp_token *token = cp_lexer_peek_token (parser->lexer);
691   *ellipsisp = false;  /* Initially, assume no ellipsis.  */
692
693   while (token->type == CPP_COMMA)
694     {
695       cp_parameter_declarator *parmdecl;
696       tree parm;
697
698       cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
699       token = cp_lexer_peek_token (parser->lexer);
700
701       if (token->type == CPP_ELLIPSIS)
702         {
703           cp_lexer_consume_token (parser->lexer);  /* Eat '...'.  */
704           *ellipsisp = true;
705           token = cp_lexer_peek_token (parser->lexer);
706           break;
707         }
708
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,
714                              /*attrlist=*/NULL);
715
716       chainon (params, build_tree_list (NULL_TREE, parm));
717       token = cp_lexer_peek_token (parser->lexer);
718     }
719
720   /* We allow tail attributes for the method.  */
721   if (token->keyword == RID_ATTRIBUTE)
722     {
723       if (*attributes == NULL_TREE)
724         {
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))
728             return params;
729         }
730       else        
731         /* We have an error, but parse the attributes, so that we can 
732            carry on.  */
733         *attributes = cp_parser_attributes_opt (parser);
734
735       cp_parser_error (parser, 
736                        "method attributes must be specified at the end");
737       return error_mark_node;
738     }
739
740   return params;
741 }
742
743 /* Parse a linkage specification, a pragma, an extra semicolon or a block.  */
744
745 static void
746 cp_parser_objc_interstitial_code (cp_parser* parser)
747 {
748   cp_token *token = cp_lexer_peek_token (parser->lexer);
749
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)
763     {
764       cp_lexer_consume_token (parser->lexer);
765       objc_set_method_opt (true);
766     }
767   else if (token->keyword == RID_AT_REQUIRED)
768     {
769       cp_lexer_consume_token (parser->lexer);
770       objc_set_method_opt (false);
771     }
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)
776     {
777       cp_lexer_consume_token (parser->lexer);
778       error ("stray %qs between Objective-C++ methods",
779              token->type == CPP_OPEN_BRACE ? "{" : "}");
780     }
781   /* Finally, try to parse a block-declaration, or a function-definition.  */
782   else
783     cp_parser_block_declaration (parser, /*statement_p=*/false);
784 }
785
786 /* Parse a method signature.  */
787
788 static tree
789 cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
790 {
791   tree rettype, kwdparms, optparms;
792   bool ellipsis = false;
793   bool is_class_method;
794
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;
804
805   return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
806 }
807
808 static bool
809 cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
810 {
811   tree tattr;  
812   cp_lexer_save_tokens (parser->lexer);
813   tattr = cp_parser_attributes_opt (parser);
814   gcc_assert (tattr) ;
815   
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))
820     return true;
821
822   /* Otherwise, the attributes introduce some interstitial code, possibly so
823      rewind to allow that check.  */
824   cp_lexer_rollback_tokens (parser->lexer);
825   return false;  
826 }
827
828 /* Parse an Objective-C method prototype list.  */
829
830 static void
831 cp_parser_objc_method_prototype_list (cp_parser* parser)
832 {
833   cp_token *token = cp_lexer_peek_token (parser->lexer);
834
835   while (token->keyword != RID_AT_END && token->type != CPP_EOF)
836     {
837       if (token->type == CPP_PLUS || token->type == CPP_MINUS)
838         {
839           tree attributes, sig;
840           bool is_class_method;
841           if (token->type == CPP_PLUS)
842             is_class_method = true;
843           else
844             is_class_method = false;
845           sig = cp_parser_objc_method_signature (parser, &attributes);
846           if (sig == error_mark_node)
847             {
848               cp_parser_skip_to_end_of_block_or_statement (parser);
849               token = cp_lexer_peek_token (parser->lexer);
850               continue;
851             }
852           objc_add_method_declaration (is_class_method, sig, attributes);
853           cp_parser_consume_semicolon_at_end_of_statement (parser);
854         }
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, 
860                     OPT_Wattributes, 
861                     "prefix attributes are ignored for methods");
862       else
863         /* Allow for interspersed non-ObjC++ code.  */
864         cp_parser_objc_interstitial_code (parser);
865
866       token = cp_lexer_peek_token (parser->lexer);
867     }
868
869   if (token->type != CPP_EOF)
870     cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
871   else
872     cp_parser_error (parser, "expected %<@end%>");
873
874   objc_finish_interface ();
875 }
876
877 /* Parse an Objective-C method definition list.  */
878
879 static void
880 cp_parser_objc_method_definition_list (cp_parser* parser)
881 {
882   cp_token *token = cp_lexer_peek_token (parser->lexer);
883
884   while (token->keyword != RID_AT_END && token->type != CPP_EOF)
885     {
886       tree meth;
887
888       if (token->type == CPP_PLUS || token->type == CPP_MINUS)
889         {
890           cp_token *ptk;
891           tree sig, attribute;
892           bool is_class_method;
893           if (token->type == CPP_PLUS)
894             is_class_method = true;
895           else
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)
900             {
901               cp_parser_skip_to_end_of_block_or_statement (parser);
902               token = cp_lexer_peek_token (parser->lexer);
903               continue;
904             }
905           objc_start_method_definition (is_class_method, sig, attribute);
906
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);
910
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))
914             {
915               perform_deferred_access_checks ();
916               stop_deferring_access_checks ();
917               meth = cp_parser_function_definition_after_declarator (parser,
918                                                                      false);
919               pop_deferring_access_checks ();
920               objc_finish_method_definition (meth);
921             }
922         }
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");
935       else
936         /* Allow for interspersed non-ObjC++ code.  */
937         cp_parser_objc_interstitial_code (parser);
938
939       token = cp_lexer_peek_token (parser->lexer);
940     }
941
942   if (token->type != CPP_EOF)
943     cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
944   else
945     cp_parser_error (parser, "expected %<@end%>");
946
947   objc_finish_implementation ();
948 }
949
950 /* Parse Objective-C ivars.  */
951
952 static void
953 cp_parser_objc_class_ivars (cp_parser* parser)
954 {
955   cp_token *token = cp_lexer_peek_token (parser->lexer);
956
957   if (token->type != CPP_OPEN_BRACE)
958     return;     /* No ivars specified.  */
959
960   cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
961   token = cp_lexer_peek_token (parser->lexer);
962
963   while (token->type != CPP_CLOSE_BRACE 
964         && token->keyword != RID_AT_END && token->type != CPP_EOF)
965     {
966       cp_decl_specifier_seq declspecs;
967       int decl_class_or_enum_p;
968       tree prefix_attributes;
969
970       cp_parser_objc_visibility_spec (parser);
971
972       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
973         break;
974
975       cp_parser_decl_specifier_seq (parser,
976                                     CP_PARSER_FLAGS_OPTIONAL,
977                                     &declspecs,
978                                     &decl_class_or_enum_p);
979
980       /* auto, register, static, extern, mutable.  */
981       if (declspecs.storage_class != sc_none)
982         {
983           cp_parser_error (parser, "invalid type for instance variable");         
984           declspecs.storage_class = sc_none;
985         }
986
987       /* __thread.  */
988       if (declspecs.specs[(int) ds_thread])
989         {
990           cp_parser_error (parser, "invalid type for instance variable");
991           declspecs.specs[(int) ds_thread] = 0;
992         }
993       
994       /* typedef.  */
995       if (declspecs.specs[(int) ds_typedef])
996         {
997           cp_parser_error (parser, "invalid type for instance variable");
998           declspecs.specs[(int) ds_typedef] = 0;
999         }
1000
1001       prefix_attributes = declspecs.attributes;
1002       declspecs.attributes = NULL_TREE;
1003
1004       /* Keep going until we hit the `;' at the end of the
1005          declaration.  */
1006       while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
1007         {
1008           tree width = NULL_TREE, attributes, first_attribute, decl;
1009           cp_declarator *declarator = NULL;
1010           int ctor_dtor_or_conv_p;
1011
1012           /* Check for a (possibly unnamed) bitfield declaration.  */
1013           token = cp_lexer_peek_token (parser->lexer);
1014           if (token->type == CPP_COLON)
1015             goto eat_colon;
1016
1017           if (token->type == CPP_NAME
1018               && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
1019                   == CPP_COLON))
1020             {
1021               /* Get the name of the bitfield.  */
1022               declarator = make_id_declarator (NULL_TREE,
1023                                                cp_parser_identifier (parser),
1024                                                sfk_none);
1025
1026              eat_colon:
1027               cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
1028               /* Get the width of the bitfield.  */
1029               width
1030                 = cp_parser_constant_expression (parser,
1031                                                  /*allow_non_constant=*/false,
1032                                                  NULL);
1033             }
1034           else
1035             {
1036               /* Parse the declarator.  */
1037               declarator
1038                 = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
1039                                         &ctor_dtor_or_conv_p,
1040                                         /*parenthesized_p=*/NULL,
1041                                         /*member_p=*/false);
1042             }
1043
1044           /* Look for attributes that apply to the ivar.  */
1045           attributes = cp_parser_attributes_opt (parser);
1046           /* Remember which attributes are prefix attributes and
1047              which are not.  */
1048           first_attribute = attributes;
1049           /* Combine the attributes.  */
1050           attributes = chainon (prefix_attributes, attributes);
1051
1052           if (width)
1053               /* Create the bitfield declaration.  */
1054               decl = grokbitfield (declarator, &declspecs,
1055                                    width,
1056                                    attributes);
1057           else
1058             decl = grokfield (declarator, &declspecs,
1059                               NULL_TREE, /*init_const_expr_p=*/false,
1060                               NULL_TREE, attributes);
1061
1062           /* Add the instance variable.  */
1063           objc_add_instance_variable (decl);
1064
1065           /* Reset PREFIX_ATTRIBUTES.  */
1066           while (attributes && TREE_CHAIN (attributes) != first_attribute)
1067             attributes = TREE_CHAIN (attributes);
1068           if (attributes)
1069             TREE_CHAIN (attributes) = NULL_TREE;
1070
1071           token = cp_lexer_peek_token (parser->lexer);
1072
1073           if (token->type == CPP_COMMA)
1074             {
1075               cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
1076               continue;
1077             }
1078           break;
1079         }
1080
1081       cp_parser_consume_semicolon_at_end_of_statement (parser);
1082       token = cp_lexer_peek_token (parser->lexer);
1083     }
1084
1085   if (token->keyword == RID_AT_END)
1086     cp_parser_error (parser, "expected %<}%>");
1087
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 '}'.  */
1092     
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);
1096 }
1097
1098 /* Parse an Objective-C protocol declaration.  */
1099
1100 static void
1101 cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
1102 {
1103   tree proto, protorefs;
1104   cp_token *tok;
1105
1106   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
1107   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
1108     {
1109       tok = cp_lexer_peek_token (parser->lexer);
1110       error_at (tok->location, "identifier expected after %<@protocol%>");
1111       goto finish;
1112     }
1113
1114   /* See if we have a forward declaration or a definition.  */
1115   tok = cp_lexer_peek_nth_token (parser->lexer, 2);
1116
1117   /* Try a forward declaration first.  */
1118   if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
1119     {
1120       objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
1121                               attributes);
1122      finish:
1123       cp_parser_consume_semicolon_at_end_of_statement (parser);
1124     }
1125
1126   /* Ok, we got a full-fledged definition (or at least should).  */
1127   else
1128     {
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);
1133     }
1134 }
1135
1136 /* Parse an Objective-C superclass or category.  */
1137
1138 static void
1139 cp_parser_objc_superclass_or_category (cp_parser *parser, 
1140                                        bool iface_p,
1141                                        tree *super,
1142                                        tree *categ, bool *is_class_extension)
1143 {
1144   cp_token *next = cp_lexer_peek_token (parser->lexer);
1145
1146   *super = *categ = NULL_TREE;
1147   *is_class_extension = false;
1148   if (next->type == CPP_COLON)
1149     {
1150       cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
1151       *super = cp_parser_identifier (parser);
1152     }
1153   else if (next->type == CPP_OPEN_PAREN)
1154     {
1155       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
1156
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))
1160         {
1161           *categ = NULL_TREE;
1162           *is_class_extension = true;
1163         }
1164       else
1165         *categ = cp_parser_identifier (parser);
1166
1167       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
1168     }
1169 }
1170
1171 /* Parse an Objective-C class interface.  */
1172
1173 static void
1174 cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
1175 {
1176   tree name, super, categ, protos;
1177   bool is_class_extension;
1178
1179   cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
1180   name = cp_parser_identifier (parser);
1181   if (name == error_mark_node)
1182     {
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.
1187       */
1188       return;
1189     }
1190   cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
1191                                          &is_class_extension);
1192   protos = cp_parser_objc_protocol_refs_opt (parser);
1193
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);
1197   else
1198     {
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 ();
1203     }
1204
1205   cp_parser_objc_method_prototype_list (parser);
1206 }
1207
1208 /* Parse an Objective-C class implementation.  */
1209
1210 static void
1211 cp_parser_objc_class_implementation (cp_parser* parser)
1212 {
1213   tree name, super, categ;
1214   bool is_class_extension;
1215
1216   cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
1217   name = cp_parser_identifier (parser);
1218   if (name == error_mark_node)
1219     {
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
1224          skip it.
1225       */
1226       return;
1227     }
1228   cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
1229                                          &is_class_extension);
1230
1231   /* We have either a class or a category on our hands.  */
1232   if (categ)
1233     objc_start_category_implementation (name, categ);
1234   else
1235     {
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 ();
1240     }
1241
1242   cp_parser_objc_method_definition_list (parser);
1243 }
1244
1245 /* Consume the @end token and finish off the implementation.  */
1246
1247 static void
1248 cp_parser_objc_end_implementation (cp_parser* parser)
1249 {
1250   cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
1251   objc_finish_implementation ();
1252 }
1253
1254 /* Parse an Objective-C declaration.  */
1255
1256 static void
1257 cp_parser_objc_declaration (cp_parser* parser, tree attributes)
1258 {
1259   /* Try to figure out what kind of declaration is present.  */
1260   cp_token *kwd = cp_lexer_peek_token (parser->lexer);
1261
1262   if (attributes)
1263     switch (kwd->keyword)
1264       {
1265         case RID_AT_ALIAS:
1266         case RID_AT_CLASS:
1267         case RID_AT_END:
1268           error_at (kwd->location, "attributes may not be specified before"
1269                     " the %<@%D%> Objective-C++ keyword",
1270                     kwd->u.value);
1271           attributes = NULL;
1272           break;
1273         case RID_AT_IMPLEMENTATION:
1274           warning_at (kwd->location, OPT_Wattributes,
1275                       "prefix attributes are ignored before %<@%D%>",
1276                       kwd->u.value);
1277           attributes = NULL;
1278         default:
1279           break;
1280       }
1281
1282   switch (kwd->keyword)
1283     {
1284     case RID_AT_ALIAS:
1285       cp_parser_objc_alias_declaration (parser);
1286       break;
1287     case RID_AT_CLASS:
1288       cp_parser_objc_class_declaration (parser);
1289       break;
1290     case RID_AT_PROTOCOL:
1291       cp_parser_objc_protocol_declaration (parser, attributes);
1292       break;
1293     case RID_AT_INTERFACE:
1294       cp_parser_objc_class_interface (parser, attributes);
1295       break;
1296     case RID_AT_IMPLEMENTATION:
1297       cp_parser_objc_class_implementation (parser);
1298       break;
1299     case RID_AT_END:
1300       cp_parser_objc_end_implementation (parser);
1301       break;
1302     default:
1303       error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
1304                 kwd->u.value);
1305       cp_parser_skip_to_end_of_block_or_statement (parser);
1306     }
1307 }
1308
1309 /* Parse an Objective-C try-catch-finally statement.
1310
1311    objc-try-catch-finally-stmt:
1312      @try compound-statement objc-catch-clause-seq [opt]
1313        objc-finally-clause [opt]
1314
1315    objc-catch-clause-seq:
1316      objc-catch-clause objc-catch-clause-seq [opt]
1317
1318    objc-catch-clause:
1319      @catch ( objc-exception-declaration ) compound-statement
1320
1321    objc-finally-clause:
1322      @finally compound-statement
1323
1324    objc-exception-declaration:
1325      parameter-declaration
1326      '...'
1327
1328    where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
1329
1330    Returns NULL_TREE.
1331
1332    PS: This function is identical to c_parser_objc_try_catch_finally_statement
1333    for C.  Keep them in sync.  */   
1334
1335 static tree
1336 cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
1337 {
1338   location_t location;
1339   tree stmt;
1340
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));
1349
1350   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
1351     {
1352       cp_parameter_declarator *parm;
1353       tree parameter_declaration = error_mark_node;
1354       bool seen_open_paren = false;
1355
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))
1360         {
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
1365              '...'.  */
1366           cp_lexer_consume_token (parser->lexer);
1367           parameter_declaration = NULL_TREE;
1368         }
1369       else
1370         {
1371           /* We have "@catch (NSException *exception)" or something
1372              like that.  Parse the parameter declaration.  */
1373           parm = cp_parser_parameter_declaration (parser, false, NULL);
1374           if (parm == NULL)
1375             parameter_declaration = error_mark_node;
1376           else
1377             parameter_declaration = grokdeclarator (parm->declarator,
1378                                                     &parm->decl_specifiers,
1379                                                     PARM, /*initialized=*/0,
1380                                                     /*attrlist=*/NULL);
1381         }
1382       if (seen_open_paren)
1383         cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
1384       else
1385         {
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.  */
1389
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
1393              going.  */
1394           if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
1395             cp_lexer_consume_token (parser->lexer);
1396           
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.  */
1401         }
1402       objc_begin_catch_clause (parameter_declaration);
1403       cp_parser_compound_statement (parser, NULL, false);
1404       objc_finish_catch_clause ();
1405     }
1406   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
1407     {
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));
1415     }
1416
1417   return objc_finish_try_stmt ();
1418 }
1419
1420 /* Parse an Objective-C synchronized statement.
1421
1422    objc-synchronized-stmt:
1423      @synchronized ( expression ) compound-statement
1424
1425    Returns NULL_TREE.  */
1426
1427 static tree
1428 cp_parser_objc_synchronized_statement (cp_parser *parser)
1429 {
1430   location_t location;
1431   tree lock, stmt;
1432
1433   cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
1434
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);
1440
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);
1445
1446   return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
1447 }
1448
1449 /* Parse an Objective-C throw statement.
1450
1451    objc-throw-stmt:
1452      @throw assignment-expression [opt] ;
1453
1454    Returns a constructed '@throw' statement.  */
1455
1456 static tree
1457 cp_parser_objc_throw_statement (cp_parser *parser)
1458 {
1459   tree expr = NULL_TREE;
1460   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
1461
1462   cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
1463
1464   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
1465     expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
1466
1467   cp_parser_consume_semicolon_at_end_of_statement (parser);
1468
1469   return objc_build_throw_stmt (loc, expr);
1470 }
1471
1472 /* Parse an Objective-C statement.  */
1473
1474 static tree
1475 cp_parser_objc_statement (cp_parser * parser)
1476 {
1477   /* Try to figure out what kind of declaration is present.  */
1478   cp_token *kwd = cp_lexer_peek_token (parser->lexer);
1479
1480   switch (kwd->keyword)
1481     {
1482     case RID_AT_TRY:
1483       return cp_parser_objc_try_catch_finally_statement (parser);
1484     case RID_AT_SYNCHRONIZED:
1485       return cp_parser_objc_synchronized_statement (parser);
1486     case RID_AT_THROW:
1487       return cp_parser_objc_throw_statement (parser);
1488     default:
1489       error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
1490                kwd->u.value);
1491       cp_parser_skip_to_end_of_block_or_statement (parser);
1492     }
1493
1494   return error_mark_node;
1495 }
1496
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 
1500    @protocol.  */
1501
1502 static bool
1503 cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
1504 {
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))
1509     {
1510       cp_lexer_commit_tokens (parser->lexer);
1511       return true;
1512     }
1513   cp_lexer_rollback_tokens (parser->lexer);
1514   return false;  
1515 }
1516
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
1520    code
1521
1522    @property (readonly) int a, b, c;
1523
1524    this function is responsible for parsing "int a, int b, int c" and
1525    returning the declarations as CHAIN of DECLs.
1526
1527    TODO: Share this code with cp_parser_objc_class_ivars.  It's very
1528    similar parsing.  */
1529 static tree
1530 cp_parser_objc_struct_declaration (cp_parser *parser)
1531 {
1532   tree decls = NULL_TREE;
1533   cp_decl_specifier_seq declspecs;
1534   int decl_class_or_enum_p;
1535   tree prefix_attributes;
1536
1537   cp_parser_decl_specifier_seq (parser,
1538                                 CP_PARSER_FLAGS_NONE,
1539                                 &declspecs,
1540                                 &decl_class_or_enum_p);
1541
1542   if (declspecs.type == error_mark_node)
1543     return error_mark_node;
1544
1545   /* auto, register, static, extern, mutable.  */
1546   if (declspecs.storage_class != sc_none)
1547     {
1548       cp_parser_error (parser, "invalid type for property");
1549       declspecs.storage_class = sc_none;
1550     }
1551   
1552   /* __thread.  */
1553   if (declspecs.specs[(int) ds_thread])
1554     {
1555       cp_parser_error (parser, "invalid type for property");
1556       declspecs.specs[(int) ds_thread] = 0;
1557     }
1558   
1559   /* typedef.  */
1560   if (declspecs.specs[(int) ds_typedef])
1561     {
1562       cp_parser_error (parser, "invalid type for property");
1563       declspecs.specs[(int) ds_typedef] = 0;
1564     }
1565
1566   prefix_attributes = declspecs.attributes;
1567   declspecs.attributes = NULL_TREE;
1568
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))
1571     {
1572       tree attributes, first_attribute, decl;
1573       cp_declarator *declarator;
1574       cp_token *token;
1575
1576       /* Parse the declarator.  */
1577       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
1578                                          NULL, NULL, false);
1579
1580       /* Look for attributes that apply to the ivar.  */
1581       attributes = cp_parser_attributes_opt (parser);
1582       /* Remember which attributes are prefix attributes and
1583          which are not.  */
1584       first_attribute = attributes;
1585       /* Combine the attributes.  */
1586       attributes = chainon (prefix_attributes, attributes);
1587       
1588       decl = grokfield (declarator, &declspecs,
1589                         NULL_TREE, /*init_const_expr_p=*/false,
1590                         NULL_TREE, attributes);
1591
1592       if (decl == error_mark_node || decl == NULL_TREE)
1593         return error_mark_node;
1594       
1595       /* Reset PREFIX_ATTRIBUTES.  */
1596       while (attributes && TREE_CHAIN (attributes) != first_attribute)
1597         attributes = TREE_CHAIN (attributes);
1598       if (attributes)
1599         TREE_CHAIN (attributes) = NULL_TREE;
1600
1601       DECL_CHAIN (decl) = decls;
1602       decls = decl;
1603
1604       token = cp_lexer_peek_token (parser->lexer);
1605       if (token->type == CPP_COMMA)
1606         {
1607           cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
1608           continue;
1609         }
1610       else
1611         break;
1612     }
1613   return decls;
1614 }
1615
1616 /* Parse an Objective-C @property declaration.  The syntax is:
1617
1618    objc-property-declaration:
1619      '@property' objc-property-attributes[opt] struct-declaration ;
1620
1621    objc-property-attributes:
1622     '(' objc-property-attribute-list ')'
1623
1624    objc-property-attribute-list:
1625      objc-property-attribute
1626      objc-property-attribute-list, objc-property-attribute
1627
1628    objc-property-attribute
1629      'getter' = identifier
1630      'setter' = identifier
1631      'readonly'
1632      'readwrite'
1633      'assign'
1634      'retain'
1635      'copy'
1636      'nonatomic'
1637
1638   For example:
1639     @property NSString *name;
1640     @property (readonly) id object;
1641     @property (retain, nonatomic, getter=getTheName) id name;
1642     @property int a, b, c;
1643
1644    PS: This function is identical to
1645    c_parser_objc_at_property_declaration for C.  Keep them in sync.  */
1646 static void 
1647 cp_parser_objc_at_property_declaration (cp_parser *parser)
1648 {
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;
1665
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
1668      are three).  */
1669   tree properties;
1670   location_t loc;
1671
1672   loc = cp_lexer_peek_token (parser->lexer)->location;
1673
1674   cp_lexer_consume_token (parser->lexer);  /* Eat '@property'.  */
1675
1676   /* Parse the optional attribute list...  */
1677   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
1678     {
1679       /* Eat the '('.  */
1680       cp_lexer_consume_token (parser->lexer);
1681
1682       while (true)
1683         {
1684           bool syntax_error = false;
1685           cp_token *token = cp_lexer_peek_token (parser->lexer);
1686           enum rid keyword;
1687
1688           if (token->type != CPP_NAME)
1689             {
1690               cp_parser_error (parser, "expected identifier");
1691               break;
1692             }
1693           keyword = C_RID_CODE (token->u.value);
1694           cp_lexer_consume_token (parser->lexer);
1695           switch (keyword)
1696             {
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;
1703
1704             case RID_GETTER:
1705             case RID_SETTER:
1706               if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
1707                 {
1708                   if (keyword == RID_GETTER)
1709                     cp_parser_error (parser,
1710                                      "missing %<=%> (after %<getter%> attribute)");
1711                   else
1712                     cp_parser_error (parser,
1713                                      "missing %<=%> (after %<setter%> attribute)");
1714                   syntax_error = true;
1715                   break;
1716                 }
1717               cp_lexer_consume_token (parser->lexer); /* eat the = */
1718               if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
1719                 {
1720                   cp_parser_error (parser, "expected identifier");
1721                   syntax_error = true;
1722                   break;
1723                 }
1724               if (keyword == RID_SETTER)
1725                 {
1726                   if (property_setter_ident != NULL_TREE)
1727                     cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
1728                   else
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 %<:%>");
1733                   else
1734                     cp_lexer_consume_token (parser->lexer);
1735                 }
1736               else
1737                 {
1738                   if (property_getter_ident != NULL_TREE)
1739                     cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
1740                   else
1741                     property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
1742                   cp_lexer_consume_token (parser->lexer);
1743                 }
1744               break;
1745             default:
1746               cp_parser_error (parser, "unknown property attribute");
1747               syntax_error = true;
1748               break;
1749             }
1750
1751           if (syntax_error)
1752             break;
1753
1754           if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
1755             cp_lexer_consume_token (parser->lexer);
1756           else
1757             break;
1758         }
1759
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))
1765         {
1766           cp_parser_skip_to_closing_parenthesis (parser,
1767                                                  /*recovering=*/true,
1768                                                  /*or_comma=*/false,
1769                                                  /*consume_paren=*/true);
1770         }
1771     }
1772
1773   /* ... and the property declaration(s).  */
1774   properties = cp_parser_objc_struct_declaration (parser);
1775
1776   if (properties == error_mark_node)
1777     {
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);
1782       return;
1783     }
1784
1785   if (properties == NULL_TREE)
1786     cp_parser_error (parser, "expected identifier");
1787   else
1788     {
1789       /* Comma-separated properties are chained together in
1790          reverse order; add them one by one.  */
1791       properties = nreverse (properties);
1792       
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);
1799     }
1800   
1801   cp_parser_consume_semicolon_at_end_of_statement (parser);
1802 }
1803
1804 /* Parse an Objective-C++ @synthesize declaration.  The syntax is:
1805
1806    objc-synthesize-declaration:
1807      @synthesize objc-synthesize-identifier-list ;
1808
1809    objc-synthesize-identifier-list:
1810      objc-synthesize-identifier
1811      objc-synthesize-identifier-list, objc-synthesize-identifier
1812
1813    objc-synthesize-identifier
1814      identifier
1815      identifier = identifier
1816
1817   For example:
1818     @synthesize MyProperty;
1819     @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
1820
1821   PS: This function is identical to c_parser_objc_at_synthesize_declaration
1822   for C.  Keep them in sync.
1823 */
1824 static void 
1825 cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
1826 {
1827   tree list = NULL_TREE;
1828   location_t loc;
1829   loc = cp_lexer_peek_token (parser->lexer)->location;
1830
1831   cp_lexer_consume_token (parser->lexer);  /* Eat '@synthesize'.  */
1832   while (true)
1833     {
1834       tree property, ivar;
1835       property = cp_parser_identifier (parser);
1836       if (property == error_mark_node)
1837         {
1838           cp_parser_consume_semicolon_at_end_of_statement (parser);
1839           return;
1840         }
1841       if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
1842         {
1843           cp_lexer_consume_token (parser->lexer);
1844           ivar = cp_parser_identifier (parser);
1845           if (ivar == error_mark_node)
1846             {
1847               cp_parser_consume_semicolon_at_end_of_statement (parser);
1848               return;
1849             }
1850         }
1851       else
1852         ivar = NULL_TREE;
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);
1856       else
1857         break;
1858     }
1859   cp_parser_consume_semicolon_at_end_of_statement (parser);
1860   objc_add_synthesize_declaration (loc, list);
1861 }
1862
1863 /* Parse an Objective-C++ @dynamic declaration.  The syntax is:
1864
1865    objc-dynamic-declaration:
1866      @dynamic identifier-list ;
1867
1868    For example:
1869      @dynamic MyProperty;
1870      @dynamic MyProperty, AnotherProperty;
1871
1872   PS: This function is identical to c_parser_objc_at_dynamic_declaration
1873   for C.  Keep them in sync.
1874 */
1875 static void 
1876 cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
1877 {
1878   tree list = NULL_TREE;
1879   location_t loc;
1880   loc = cp_lexer_peek_token (parser->lexer)->location;
1881
1882   cp_lexer_consume_token (parser->lexer);  /* Eat '@dynamic'.  */
1883   while (true)
1884     {
1885       tree property;
1886       property = cp_parser_identifier (parser);
1887       if (property == error_mark_node)
1888         {
1889           cp_parser_consume_semicolon_at_end_of_statement (parser);
1890           return;
1891         }
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);
1895       else
1896         break;
1897     }
1898   cp_parser_consume_semicolon_at_end_of_statement (parser);
1899   objc_add_dynamic_declaration (loc, list);
1900 }
1901
1902 #endif