xref: /llvm-project/clang/lib/Parse/ParseObjc.cpp (revision 9e4ac111f04b581b9d85d51c2f7f68af86d6d4ba)
1 //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the Objective-C portions of the Parser interface.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Parse/Parser.h"
15 #include "clang/Parse/DeclSpec.h"
16 #include "clang/Parse/Scope.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "llvm/ADT/SmallVector.h"
19 using namespace clang;
20 
21 
22 /// ParseExternalDeclaration:
23 ///       external-declaration: [C99 6.9]
24 /// [OBJC]  objc-class-definition
25 /// [OBJC]  objc-class-declaration
26 /// [OBJC]  objc-alias-declaration
27 /// [OBJC]  objc-protocol-definition
28 /// [OBJC]  objc-method-definition
29 /// [OBJC]  '@' 'end'
30 Parser::DeclTy *Parser::ParseObjCAtDirectives() {
31   SourceLocation AtLoc = ConsumeToken(); // the "@"
32 
33   switch (Tok.getObjCKeywordID()) {
34   case tok::objc_class:
35     return ParseObjCAtClassDeclaration(AtLoc);
36   case tok::objc_interface:
37     return ParseObjCAtInterfaceDeclaration(AtLoc);
38   case tok::objc_protocol:
39     return ParseObjCAtProtocolDeclaration(AtLoc);
40   case tok::objc_implementation:
41     return ParseObjCAtImplementationDeclaration(AtLoc);
42   case tok::objc_end:
43     return ParseObjCAtEndDeclaration(AtLoc);
44   case tok::objc_compatibility_alias:
45     return ParseObjCAtAliasDeclaration(AtLoc);
46   case tok::objc_synthesize:
47     return ParseObjCPropertySynthesize(AtLoc);
48   case tok::objc_dynamic:
49     return ParseObjCPropertyDynamic(AtLoc);
50   default:
51     Diag(AtLoc, diag::err_unexpected_at);
52     SkipUntil(tok::semi);
53     return 0;
54   }
55 }
56 
57 ///
58 /// objc-class-declaration:
59 ///    '@' 'class' identifier-list ';'
60 ///
61 Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
62   ConsumeToken(); // the identifier "class"
63   llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
64 
65   while (1) {
66     if (Tok.isNot(tok::identifier)) {
67       Diag(Tok, diag::err_expected_ident);
68       SkipUntil(tok::semi);
69       return 0;
70     }
71     ClassNames.push_back(Tok.getIdentifierInfo());
72     ConsumeToken();
73 
74     if (Tok.isNot(tok::comma))
75       break;
76 
77     ConsumeToken();
78   }
79 
80   // Consume the ';'.
81   if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
82     return 0;
83 
84   return Actions.ActOnForwardClassDeclaration(atLoc,
85                                       &ClassNames[0], ClassNames.size());
86 }
87 
88 ///
89 ///   objc-interface:
90 ///     objc-class-interface-attributes[opt] objc-class-interface
91 ///     objc-category-interface
92 ///
93 ///   objc-class-interface:
94 ///     '@' 'interface' identifier objc-superclass[opt]
95 ///       objc-protocol-refs[opt]
96 ///       objc-class-instance-variables[opt]
97 ///       objc-interface-decl-list
98 ///     @end
99 ///
100 ///   objc-category-interface:
101 ///     '@' 'interface' identifier '(' identifier[opt] ')'
102 ///       objc-protocol-refs[opt]
103 ///       objc-interface-decl-list
104 ///     @end
105 ///
106 ///   objc-superclass:
107 ///     ':' identifier
108 ///
109 ///   objc-class-interface-attributes:
110 ///     __attribute__((visibility("default")))
111 ///     __attribute__((visibility("hidden")))
112 ///     __attribute__((deprecated))
113 ///     __attribute__((unavailable))
114 ///     __attribute__((objc_exception)) - used by NSException on 64-bit
115 ///
116 Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
117   SourceLocation atLoc, AttributeList *attrList) {
118   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
119          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
120   ConsumeToken(); // the "interface" identifier
121 
122   if (Tok.isNot(tok::identifier)) {
123     Diag(Tok, diag::err_expected_ident); // missing class or category name.
124     return 0;
125   }
126   // We have a class or category name - consume it.
127   IdentifierInfo *nameId = Tok.getIdentifierInfo();
128   SourceLocation nameLoc = ConsumeToken();
129 
130   if (Tok.is(tok::l_paren)) { // we have a category.
131     SourceLocation lparenLoc = ConsumeParen();
132     SourceLocation categoryLoc, rparenLoc;
133     IdentifierInfo *categoryId = 0;
134 
135     // For ObjC2, the category name is optional (not an error).
136     if (Tok.is(tok::identifier)) {
137       categoryId = Tok.getIdentifierInfo();
138       categoryLoc = ConsumeToken();
139     } else if (!getLang().ObjC2) {
140       Diag(Tok, diag::err_expected_ident); // missing category name.
141       return 0;
142     }
143     if (Tok.isNot(tok::r_paren)) {
144       Diag(Tok, diag::err_expected_rparen);
145       SkipUntil(tok::r_paren, false); // don't stop at ';'
146       return 0;
147     }
148     rparenLoc = ConsumeParen();
149 
150     // Next, we need to check for any protocol references.
151     SourceLocation EndProtoLoc;
152     llvm::SmallVector<DeclTy *, 8> ProtocolRefs;
153     if (Tok.is(tok::less) &&
154         ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
155       return 0;
156 
157     if (attrList) // categories don't support attributes.
158       Diag(Tok, diag::err_objc_no_attributes_on_category);
159 
160     DeclTy *CategoryType = Actions.ActOnStartCategoryInterface(atLoc,
161                                      nameId, nameLoc, categoryId, categoryLoc,
162                                      &ProtocolRefs[0], ProtocolRefs.size(),
163                                      EndProtoLoc);
164 
165     ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
166     return CategoryType;
167   }
168   // Parse a class interface.
169   IdentifierInfo *superClassId = 0;
170   SourceLocation superClassLoc;
171 
172   if (Tok.is(tok::colon)) { // a super class is specified.
173     ConsumeToken();
174     if (Tok.isNot(tok::identifier)) {
175       Diag(Tok, diag::err_expected_ident); // missing super class name.
176       return 0;
177     }
178     superClassId = Tok.getIdentifierInfo();
179     superClassLoc = ConsumeToken();
180   }
181   // Next, we need to check for any protocol references.
182   llvm::SmallVector<Action::DeclTy*, 8> ProtocolRefs;
183   SourceLocation EndProtoLoc;
184   if (Tok.is(tok::less) &&
185       ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
186     return 0;
187 
188   DeclTy *ClsType =
189     Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
190                                      superClassId, superClassLoc,
191                                      &ProtocolRefs[0], ProtocolRefs.size(),
192                                      EndProtoLoc, attrList);
193 
194   if (Tok.is(tok::l_brace))
195     ParseObjCClassInstanceVariables(ClsType, atLoc);
196 
197   ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
198   return ClsType;
199 }
200 
201 /// constructSetterName - Return the setter name for the given
202 /// identifier, i.e. "set" + Name where the initial character of Name
203 /// has been capitalized.
204 static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
205                                            const IdentifierInfo *Name) {
206   llvm::SmallString<100> SelectorName;
207   SelectorName += "set";
208   SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
209   SelectorName[3] = toupper(SelectorName[3]);
210   return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
211 }
212 
213 ///   objc-interface-decl-list:
214 ///     empty
215 ///     objc-interface-decl-list objc-property-decl [OBJC2]
216 ///     objc-interface-decl-list objc-method-requirement [OBJC2]
217 ///     objc-interface-decl-list objc-method-proto ';'
218 ///     objc-interface-decl-list declaration
219 ///     objc-interface-decl-list ';'
220 ///
221 ///   objc-method-requirement: [OBJC2]
222 ///     @required
223 ///     @optional
224 ///
225 void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
226                                         tok::ObjCKeywordKind contextKey) {
227   llvm::SmallVector<DeclTy*, 32> allMethods;
228   llvm::SmallVector<DeclTy*, 16> allProperties;
229   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
230 
231   SourceLocation AtEndLoc;
232 
233   while (1) {
234     // If this is a method prototype, parse it.
235     if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
236       DeclTy *methodPrototype =
237         ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
238       allMethods.push_back(methodPrototype);
239       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
240       // method definitions.
241       ExpectAndConsume(tok::semi, diag::err_expected_semi_after,"method proto");
242       continue;
243     }
244 
245     // Ignore excess semicolons.
246     if (Tok.is(tok::semi)) {
247       ConsumeToken();
248       continue;
249     }
250 
251     // If we got to the end of the file, exit the loop.
252     if (Tok.is(tok::eof))
253       break;
254 
255     // If we don't have an @ directive, parse it as a function definition.
256     if (Tok.isNot(tok::at)) {
257       // FIXME: as the name implies, this rule allows function definitions.
258       // We could pass a flag or check for functions during semantic analysis.
259       ParseDeclarationOrFunctionDefinition();
260       continue;
261     }
262 
263     // Otherwise, we have an @ directive, eat the @.
264     SourceLocation AtLoc = ConsumeToken(); // the "@"
265     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
266 
267     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
268       AtEndLoc = AtLoc;
269       break;
270     }
271 
272     // Eat the identifier.
273     ConsumeToken();
274 
275     switch (DirectiveKind) {
276     default:
277       // FIXME: If someone forgets an @end on a protocol, this loop will
278       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
279       // would probably be better to bail out if we saw an @class or @interface
280       // or something like that.
281       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
282       // Skip until we see an '@' or '}' or ';'.
283       SkipUntil(tok::r_brace, tok::at);
284       break;
285 
286     case tok::objc_required:
287     case tok::objc_optional:
288       // This is only valid on protocols.
289       // FIXME: Should this check for ObjC2 being enabled?
290       if (contextKey != tok::objc_protocol)
291         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
292       else
293         MethodImplKind = DirectiveKind;
294       break;
295 
296     case tok::objc_property:
297       if (!getLang().ObjC2)
298         Diag(AtLoc, diag::err_objc_propertoes_require_objc2);
299 
300       ObjCDeclSpec OCDS;
301       // Parse property attribute list, if any.
302       if (Tok.is(tok::l_paren))
303         ParseObjCPropertyAttribute(OCDS);
304 
305       // Parse all the comma separated declarators.
306       DeclSpec DS;
307       llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
308       ParseStructDeclaration(DS, FieldDeclarators);
309 
310       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
311                        tok::at);
312 
313       // Convert them all to property declarations.
314       for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
315         FieldDeclarator &FD = FieldDeclarators[i];
316         if (FD.D.getIdentifier() == 0) {
317           Diag(AtLoc, diag::err_objc_property_requires_field_name)
318             << FD.D.getSourceRange();
319           continue;
320         }
321 
322         // Install the property declarator into interfaceDecl.
323         IdentifierInfo *SelName =
324           OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
325 
326         Selector GetterSel =
327           PP.getSelectorTable().getNullarySelector(SelName);
328         IdentifierInfo *SetterName = OCDS.getSetterName();
329         if (!SetterName)
330           SetterName = constructSetterName(PP.getIdentifierTable(),
331                                            FD.D.getIdentifier());
332         Selector SetterSel =
333           PP.getSelectorTable().getUnarySelector(SetterName);
334         DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
335                                                  GetterSel, SetterSel,
336                                                  MethodImplKind);
337         allProperties.push_back(Property);
338       }
339       break;
340     }
341   }
342 
343   // We break out of the big loop in two cases: when we see @end or when we see
344   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
345   if (Tok.isObjCAtKeyword(tok::objc_end))
346     ConsumeToken(); // the "end" identifier
347   else
348     Diag(Tok, diag::err_objc_missing_end);
349 
350   // Insert collected methods declarations into the @interface object.
351   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
352   Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
353                      allMethods.empty() ? 0 : &allMethods[0],
354                      allMethods.size(),
355                      allProperties.empty() ? 0 : &allProperties[0],
356                      allProperties.size());
357 }
358 
359 ///   Parse property attribute declarations.
360 ///
361 ///   property-attr-decl: '(' property-attrlist ')'
362 ///   property-attrlist:
363 ///     property-attribute
364 ///     property-attrlist ',' property-attribute
365 ///   property-attribute:
366 ///     getter '=' identifier
367 ///     setter '=' identifier ':'
368 ///     readonly
369 ///     readwrite
370 ///     assign
371 ///     retain
372 ///     copy
373 ///     nonatomic
374 ///
375 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
376   assert(Tok.getKind() == tok::l_paren);
377   SourceLocation LHSLoc = ConsumeParen(); // consume '('
378 
379   while (1) {
380     const IdentifierInfo *II = Tok.getIdentifierInfo();
381 
382     // If this is not an identifier at all, bail out early.
383     if (II == 0) {
384       MatchRHSPunctuation(tok::r_paren, LHSLoc);
385       return;
386     }
387 
388     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
389 
390     if (II->isName("readonly"))
391       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
392     else if (II->isName("assign"))
393       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
394     else if (II->isName("readwrite"))
395       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
396     else if (II->isName("retain"))
397       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
398     else if (II->isName("copy"))
399       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
400     else if (II->isName("nonatomic"))
401       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
402     else if (II->isName("getter") || II->isName("setter")) {
403       // getter/setter require extra treatment.
404       if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "",
405                            tok::r_paren))
406         return;
407 
408       if (Tok.isNot(tok::identifier)) {
409         Diag(Tok, diag::err_expected_ident);
410         SkipUntil(tok::r_paren);
411         return;
412       }
413 
414       if (II->getName()[0] == 's') {
415         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
416         DS.setSetterName(Tok.getIdentifierInfo());
417         ConsumeToken();  // consume method name
418 
419         if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "",
420                              tok::r_paren))
421           return;
422       } else {
423         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
424         DS.setGetterName(Tok.getIdentifierInfo());
425         ConsumeToken();  // consume method name
426       }
427     } else {
428       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
429       SkipUntil(tok::r_paren);
430       return;
431     }
432 
433     if (Tok.isNot(tok::comma))
434       break;
435 
436     ConsumeToken();
437   }
438 
439   MatchRHSPunctuation(tok::r_paren, LHSLoc);
440 }
441 
442 ///   objc-method-proto:
443 ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
444 ///     objc-class-method objc-method-decl objc-method-attributes[opt]
445 ///
446 ///   objc-instance-method: '-'
447 ///   objc-class-method: '+'
448 ///
449 ///   objc-method-attributes:         [OBJC2]
450 ///     __attribute__((deprecated))
451 ///
452 Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
453                           tok::ObjCKeywordKind MethodImplKind) {
454   assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
455 
456   tok::TokenKind methodType = Tok.getKind();
457   SourceLocation mLoc = ConsumeToken();
458 
459   DeclTy *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl, MethodImplKind);
460   // Since this rule is used for both method declarations and definitions,
461   // the caller is (optionally) responsible for consuming the ';'.
462   return MDecl;
463 }
464 
465 ///   objc-selector:
466 ///     identifier
467 ///     one of
468 ///       enum struct union if else while do for switch case default
469 ///       break continue return goto asm sizeof typeof __alignof
470 ///       unsigned long const short volatile signed restrict _Complex
471 ///       in out inout bycopy byref oneway int char float double void _Bool
472 ///
473 IdentifierInfo *Parser::ParseObjCSelector(SourceLocation &SelectorLoc) {
474   switch (Tok.getKind()) {
475   default:
476     return 0;
477   case tok::identifier:
478   case tok::kw_asm:
479   case tok::kw_auto:
480   case tok::kw_bool:
481   case tok::kw_break:
482   case tok::kw_case:
483   case tok::kw_catch:
484   case tok::kw_char:
485   case tok::kw_class:
486   case tok::kw_const:
487   case tok::kw_const_cast:
488   case tok::kw_continue:
489   case tok::kw_default:
490   case tok::kw_delete:
491   case tok::kw_do:
492   case tok::kw_double:
493   case tok::kw_dynamic_cast:
494   case tok::kw_else:
495   case tok::kw_enum:
496   case tok::kw_explicit:
497   case tok::kw_export:
498   case tok::kw_extern:
499   case tok::kw_false:
500   case tok::kw_float:
501   case tok::kw_for:
502   case tok::kw_friend:
503   case tok::kw_goto:
504   case tok::kw_if:
505   case tok::kw_inline:
506   case tok::kw_int:
507   case tok::kw_long:
508   case tok::kw_mutable:
509   case tok::kw_namespace:
510   case tok::kw_new:
511   case tok::kw_operator:
512   case tok::kw_private:
513   case tok::kw_protected:
514   case tok::kw_public:
515   case tok::kw_register:
516   case tok::kw_reinterpret_cast:
517   case tok::kw_restrict:
518   case tok::kw_return:
519   case tok::kw_short:
520   case tok::kw_signed:
521   case tok::kw_sizeof:
522   case tok::kw_static:
523   case tok::kw_static_cast:
524   case tok::kw_struct:
525   case tok::kw_switch:
526   case tok::kw_template:
527   case tok::kw_this:
528   case tok::kw_throw:
529   case tok::kw_true:
530   case tok::kw_try:
531   case tok::kw_typedef:
532   case tok::kw_typeid:
533   case tok::kw_typename:
534   case tok::kw_typeof:
535   case tok::kw_union:
536   case tok::kw_unsigned:
537   case tok::kw_using:
538   case tok::kw_virtual:
539   case tok::kw_void:
540   case tok::kw_volatile:
541   case tok::kw_wchar_t:
542   case tok::kw_while:
543   case tok::kw__Bool:
544   case tok::kw__Complex:
545   case tok::kw___alignof:
546     IdentifierInfo *II = Tok.getIdentifierInfo();
547     SelectorLoc = ConsumeToken();
548     return II;
549   }
550 }
551 
552 ///  objc-for-collection-in: 'in'
553 ///
554 bool Parser::isTokIdentifier_in() const {
555   // FIXME: May have to do additional look-ahead to only allow for
556   // valid tokens following an 'in'; such as an identifier, unary operators,
557   // '[' etc.
558   return (getLang().ObjC2 && Tok.is(tok::identifier) &&
559           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
560 }
561 
562 /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
563 /// qualifier list and builds their bitmask representation in the input
564 /// argument.
565 ///
566 ///   objc-type-qualifiers:
567 ///     objc-type-qualifier
568 ///     objc-type-qualifiers objc-type-qualifier
569 ///
570 void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
571   while (1) {
572     if (Tok.isNot(tok::identifier))
573       return;
574 
575     const IdentifierInfo *II = Tok.getIdentifierInfo();
576     for (unsigned i = 0; i != objc_NumQuals; ++i) {
577       if (II != ObjCTypeQuals[i])
578         continue;
579 
580       ObjCDeclSpec::ObjCDeclQualifier Qual;
581       switch (i) {
582       default: assert(0 && "Unknown decl qualifier");
583       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
584       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
585       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
586       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
587       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
588       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
589       }
590       DS.setObjCDeclQualifier(Qual);
591       ConsumeToken();
592       II = 0;
593       break;
594     }
595 
596     // If this wasn't a recognized qualifier, bail out.
597     if (II) return;
598   }
599 }
600 
601 ///   objc-type-name:
602 ///     '(' objc-type-qualifiers[opt] type-name ')'
603 ///     '(' objc-type-qualifiers[opt] ')'
604 ///
605 Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
606   assert(Tok.is(tok::l_paren) && "expected (");
607 
608   SourceLocation LParenLoc = ConsumeParen();
609   SourceLocation TypeStartLoc = Tok.getLocation();
610 
611   // Parse type qualifiers, in, inout, etc.
612   ParseObjCTypeQualifierList(DS);
613 
614   TypeTy *Ty = 0;
615   if (isTypeSpecifierQualifier())
616     Ty = ParseTypeName();
617 
618   if (Tok.is(tok::r_paren))
619     ConsumeParen();
620   else if (Tok.getLocation() == TypeStartLoc) {
621     // If we didn't eat any tokens, then this isn't a type.
622     Diag(Tok, diag::err_expected_type);
623     SkipUntil(tok::r_paren);
624   } else {
625     // Otherwise, we found *something*, but didn't get a ')' in the right
626     // place.  Emit an error then return what we have as the type.
627     MatchRHSPunctuation(tok::r_paren, LParenLoc);
628   }
629   return Ty;
630 }
631 
632 ///   objc-method-decl:
633 ///     objc-selector
634 ///     objc-keyword-selector objc-parmlist[opt]
635 ///     objc-type-name objc-selector
636 ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
637 ///
638 ///   objc-keyword-selector:
639 ///     objc-keyword-decl
640 ///     objc-keyword-selector objc-keyword-decl
641 ///
642 ///   objc-keyword-decl:
643 ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
644 ///     objc-selector ':' objc-keyword-attributes[opt] identifier
645 ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
646 ///     ':' objc-keyword-attributes[opt] identifier
647 ///
648 ///   objc-parmlist:
649 ///     objc-parms objc-ellipsis[opt]
650 ///
651 ///   objc-parms:
652 ///     objc-parms , parameter-declaration
653 ///
654 ///   objc-ellipsis:
655 ///     , ...
656 ///
657 ///   objc-keyword-attributes:         [OBJC2]
658 ///     __attribute__((unused))
659 ///
660 Parser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
661                                             tok::TokenKind mType,
662                                             DeclTy *IDecl,
663                                             tok::ObjCKeywordKind MethodImplKind)
664 {
665   // Parse the return type if present.
666   TypeTy *ReturnType = 0;
667   ObjCDeclSpec DSRet;
668   if (Tok.is(tok::l_paren))
669     ReturnType = ParseObjCTypeName(DSRet);
670 
671   SourceLocation selLoc;
672   IdentifierInfo *SelIdent = ParseObjCSelector(selLoc);
673 
674   if (!SelIdent) { // missing selector name.
675     Diag(Tok, diag::err_expected_selector_for_method)
676       << SourceRange(mLoc, Tok.getLocation());
677     // Skip until we get a ; or {}.
678     SkipUntil(tok::r_brace);
679     return 0;
680   }
681 
682   if (Tok.isNot(tok::colon)) {
683     // If attributes exist after the method, parse them.
684     AttributeList *MethodAttrs = 0;
685     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
686       MethodAttrs = ParseAttributes();
687 
688     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
689     return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
690                                           mType, IDecl, DSRet, ReturnType, Sel,
691                                           0, 0, 0, MethodAttrs, MethodImplKind);
692   }
693 
694   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
695   llvm::SmallVector<Action::TypeTy *, 12> KeyTypes;
696   llvm::SmallVector<ObjCDeclSpec, 12> ArgTypeQuals;
697   llvm::SmallVector<IdentifierInfo *, 12> ArgNames;
698 
699   Action::TypeTy *TypeInfo;
700   while (1) {
701     KeyIdents.push_back(SelIdent);
702 
703     // Each iteration parses a single keyword argument.
704     if (Tok.isNot(tok::colon)) {
705       Diag(Tok, diag::err_expected_colon);
706       break;
707     }
708     ConsumeToken(); // Eat the ':'.
709     ObjCDeclSpec DSType;
710     if (Tok.is(tok::l_paren)) // Parse the argument type.
711       TypeInfo = ParseObjCTypeName(DSType);
712     else
713       TypeInfo = 0;
714     KeyTypes.push_back(TypeInfo);
715     ArgTypeQuals.push_back(DSType);
716 
717     // If attributes exist before the argument name, parse them.
718     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
719       ParseAttributes(); // FIXME: pass attributes through.
720 
721     if (Tok.isNot(tok::identifier)) {
722       Diag(Tok, diag::err_expected_ident); // missing argument name.
723       break;
724     }
725     ArgNames.push_back(Tok.getIdentifierInfo());
726     ConsumeToken(); // Eat the identifier.
727 
728     // Check for another keyword selector.
729     SourceLocation Loc;
730     SelIdent = ParseObjCSelector(Loc);
731     if (!SelIdent && Tok.isNot(tok::colon))
732       break;
733     // We have a selector or a colon, continue parsing.
734   }
735 
736   bool isVariadic = false;
737 
738   // Parse the (optional) parameter list.
739   while (Tok.is(tok::comma)) {
740     ConsumeToken();
741     if (Tok.is(tok::ellipsis)) {
742       isVariadic = true;
743       ConsumeToken();
744       break;
745     }
746     // FIXME: implement this...
747     // Parse the c-style argument declaration-specifier.
748     DeclSpec DS;
749     ParseDeclarationSpecifiers(DS);
750     // Parse the declarator.
751     Declarator ParmDecl(DS, Declarator::PrototypeContext);
752     ParseDeclarator(ParmDecl);
753   }
754 
755   // FIXME: Add support for optional parmameter list...
756   // If attributes exist after the method, parse them.
757   AttributeList *MethodAttrs = 0;
758   if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
759     MethodAttrs = ParseAttributes();
760 
761   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
762                                                    &KeyIdents[0]);
763   return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
764                                         mType, IDecl, DSRet, ReturnType, Sel,
765                                         &ArgTypeQuals[0], &KeyTypes[0],
766                                         &ArgNames[0], MethodAttrs,
767                                         MethodImplKind, isVariadic);
768 }
769 
770 ///   objc-protocol-refs:
771 ///     '<' identifier-list '>'
772 ///
773 bool Parser::
774 ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclTy*> &Protocols,
775                             bool WarnOnDeclarations, SourceLocation &EndLoc) {
776   assert(Tok.is(tok::less) && "expected <");
777 
778   ConsumeToken(); // the "<"
779 
780   llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
781 
782   while (1) {
783     if (Tok.isNot(tok::identifier)) {
784       Diag(Tok, diag::err_expected_ident);
785       SkipUntil(tok::greater);
786       return true;
787     }
788     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
789                                        Tok.getLocation()));
790     ConsumeToken();
791 
792     if (Tok.isNot(tok::comma))
793       break;
794     ConsumeToken();
795   }
796 
797   // Consume the '>'.
798   if (Tok.isNot(tok::greater)) {
799     Diag(Tok, diag::err_expected_greater);
800     return true;
801   }
802 
803   EndLoc = ConsumeAnyToken();
804 
805   // Convert the list of protocols identifiers into a list of protocol decls.
806   Actions.FindProtocolDeclaration(WarnOnDeclarations,
807                                   &ProtocolIdents[0], ProtocolIdents.size(),
808                                   Protocols);
809   return false;
810 }
811 
812 ///   objc-class-instance-variables:
813 ///     '{' objc-instance-variable-decl-list[opt] '}'
814 ///
815 ///   objc-instance-variable-decl-list:
816 ///     objc-visibility-spec
817 ///     objc-instance-variable-decl ';'
818 ///     ';'
819 ///     objc-instance-variable-decl-list objc-visibility-spec
820 ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
821 ///     objc-instance-variable-decl-list ';'
822 ///
823 ///   objc-visibility-spec:
824 ///     @private
825 ///     @protected
826 ///     @public
827 ///     @package [OBJC2]
828 ///
829 ///   objc-instance-variable-decl:
830 ///     struct-declaration
831 ///
832 void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
833                                              SourceLocation atLoc) {
834   assert(Tok.is(tok::l_brace) && "expected {");
835   llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
836   llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
837 
838   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
839 
840   tok::ObjCKeywordKind visibility = tok::objc_protected;
841   // While we still have something to read, read the instance variables.
842   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
843     // Each iteration of this loop reads one objc-instance-variable-decl.
844 
845     // Check for extraneous top-level semicolon.
846     if (Tok.is(tok::semi)) {
847       Diag(Tok, diag::ext_extra_struct_semi);
848       ConsumeToken();
849       continue;
850     }
851 
852     // Set the default visibility to private.
853     if (Tok.is(tok::at)) { // parse objc-visibility-spec
854       ConsumeToken(); // eat the @ sign
855       switch (Tok.getObjCKeywordID()) {
856       case tok::objc_private:
857       case tok::objc_public:
858       case tok::objc_protected:
859       case tok::objc_package:
860         visibility = Tok.getObjCKeywordID();
861         ConsumeToken();
862         continue;
863       default:
864         Diag(Tok, diag::err_objc_illegal_visibility_spec);
865         continue;
866       }
867     }
868 
869     // Parse all the comma separated declarators.
870     DeclSpec DS;
871     FieldDeclarators.clear();
872     ParseStructDeclaration(DS, FieldDeclarators);
873 
874     // Convert them all to fields.
875     for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
876       FieldDeclarator &FD = FieldDeclarators[i];
877       // Install the declarator into interfaceDecl.
878       DeclTy *Field = Actions.ActOnIvar(CurScope,
879                                          DS.getSourceRange().getBegin(),
880                                          FD.D, FD.BitfieldSize, visibility);
881       AllIvarDecls.push_back(Field);
882     }
883 
884     if (Tok.is(tok::semi)) {
885       ConsumeToken();
886     } else {
887       Diag(Tok, diag::err_expected_semi_decl_list);
888       // Skip to end of block or statement
889       SkipUntil(tok::r_brace, true, true);
890     }
891   }
892   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
893   // Call ActOnFields() even if we don't have any decls. This is useful
894   // for code rewriting tools that need to be aware of the empty list.
895   Actions.ActOnFields(CurScope, atLoc, interfaceDecl,
896                       &AllIvarDecls[0], AllIvarDecls.size(),
897                       LBraceLoc, RBraceLoc, 0);
898   return;
899 }
900 
901 ///   objc-protocol-declaration:
902 ///     objc-protocol-definition
903 ///     objc-protocol-forward-reference
904 ///
905 ///   objc-protocol-definition:
906 ///     @protocol identifier
907 ///       objc-protocol-refs[opt]
908 ///       objc-interface-decl-list
909 ///     @end
910 ///
911 ///   objc-protocol-forward-reference:
912 ///     @protocol identifier-list ';'
913 ///
914 ///   "@protocol identifier ;" should be resolved as "@protocol
915 ///   identifier-list ;": objc-interface-decl-list may not start with a
916 ///   semicolon in the first alternative if objc-protocol-refs are omitted.
917 Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
918                                                AttributeList *attrList) {
919   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
920          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
921   ConsumeToken(); // the "protocol" identifier
922 
923   if (Tok.isNot(tok::identifier)) {
924     Diag(Tok, diag::err_expected_ident); // missing protocol name.
925     return 0;
926   }
927   // Save the protocol name, then consume it.
928   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
929   SourceLocation nameLoc = ConsumeToken();
930 
931   if (Tok.is(tok::semi)) { // forward declaration of one protocol.
932     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
933     ConsumeToken();
934     return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1);
935   }
936 
937   if (Tok.is(tok::comma)) { // list of forward declarations.
938     llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
939     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
940 
941     // Parse the list of forward declarations.
942     while (1) {
943       ConsumeToken(); // the ','
944       if (Tok.isNot(tok::identifier)) {
945         Diag(Tok, diag::err_expected_ident);
946         SkipUntil(tok::semi);
947         return 0;
948       }
949       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
950                                                Tok.getLocation()));
951       ConsumeToken(); // the identifier
952 
953       if (Tok.isNot(tok::comma))
954         break;
955     }
956     // Consume the ';'.
957     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
958       return 0;
959 
960     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
961                                                    &ProtocolRefs[0],
962                                                    ProtocolRefs.size());
963   }
964 
965   // Last, and definitely not least, parse a protocol declaration.
966   SourceLocation EndProtoLoc;
967 
968   llvm::SmallVector<DeclTy *, 8> ProtocolRefs;
969   if (Tok.is(tok::less) &&
970       ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
971     return 0;
972 
973   DeclTy *ProtoType =
974     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
975                                         &ProtocolRefs[0], ProtocolRefs.size(),
976                                         EndProtoLoc, attrList);
977   ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
978   return ProtoType;
979 }
980 
981 ///   objc-implementation:
982 ///     objc-class-implementation-prologue
983 ///     objc-category-implementation-prologue
984 ///
985 ///   objc-class-implementation-prologue:
986 ///     @implementation identifier objc-superclass[opt]
987 ///       objc-class-instance-variables[opt]
988 ///
989 ///   objc-category-implementation-prologue:
990 ///     @implementation identifier ( identifier )
991 
992 Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
993   SourceLocation atLoc) {
994   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
995          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
996   ConsumeToken(); // the "implementation" identifier
997 
998   if (Tok.isNot(tok::identifier)) {
999     Diag(Tok, diag::err_expected_ident); // missing class or category name.
1000     return 0;
1001   }
1002   // We have a class or category name - consume it.
1003   IdentifierInfo *nameId = Tok.getIdentifierInfo();
1004   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
1005 
1006   if (Tok.is(tok::l_paren)) {
1007     // we have a category implementation.
1008     SourceLocation lparenLoc = ConsumeParen();
1009     SourceLocation categoryLoc, rparenLoc;
1010     IdentifierInfo *categoryId = 0;
1011 
1012     if (Tok.is(tok::identifier)) {
1013       categoryId = Tok.getIdentifierInfo();
1014       categoryLoc = ConsumeToken();
1015     } else {
1016       Diag(Tok, diag::err_expected_ident); // missing category name.
1017       return 0;
1018     }
1019     if (Tok.isNot(tok::r_paren)) {
1020       Diag(Tok, diag::err_expected_rparen);
1021       SkipUntil(tok::r_paren, false); // don't stop at ';'
1022       return 0;
1023     }
1024     rparenLoc = ConsumeParen();
1025     DeclTy *ImplCatType = Actions.ActOnStartCategoryImplementation(
1026                                     atLoc, nameId, nameLoc, categoryId,
1027                                     categoryLoc);
1028     ObjCImpDecl = ImplCatType;
1029     return 0;
1030   }
1031   // We have a class implementation
1032   SourceLocation superClassLoc;
1033   IdentifierInfo *superClassId = 0;
1034   if (Tok.is(tok::colon)) {
1035     // We have a super class
1036     ConsumeToken();
1037     if (Tok.isNot(tok::identifier)) {
1038       Diag(Tok, diag::err_expected_ident); // missing super class name.
1039       return 0;
1040     }
1041     superClassId = Tok.getIdentifierInfo();
1042     superClassLoc = ConsumeToken(); // Consume super class name
1043   }
1044   DeclTy *ImplClsType = Actions.ActOnStartClassImplementation(
1045                                   atLoc, nameId, nameLoc,
1046                                   superClassId, superClassLoc);
1047 
1048   if (Tok.is(tok::l_brace)) // we have ivars
1049     ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
1050   ObjCImpDecl = ImplClsType;
1051 
1052   return 0;
1053 }
1054 
1055 Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
1056   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
1057          "ParseObjCAtEndDeclaration(): Expected @end");
1058   ConsumeToken(); // the "end" identifier
1059   if (ObjCImpDecl)
1060     Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
1061   else
1062     Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
1063   return ObjCImpDecl;
1064 }
1065 
1066 ///   compatibility-alias-decl:
1067 ///     @compatibility_alias alias-name  class-name ';'
1068 ///
1069 Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
1070   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
1071          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
1072   ConsumeToken(); // consume compatibility_alias
1073   if (Tok.isNot(tok::identifier)) {
1074     Diag(Tok, diag::err_expected_ident);
1075     return 0;
1076   }
1077   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
1078   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
1079   if (Tok.isNot(tok::identifier)) {
1080     Diag(Tok, diag::err_expected_ident);
1081     return 0;
1082   }
1083   IdentifierInfo *classId = Tok.getIdentifierInfo();
1084   SourceLocation classLoc = ConsumeToken(); // consume class-name;
1085   if (Tok.isNot(tok::semi)) {
1086     Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
1087     return 0;
1088   }
1089   DeclTy *ClsType = Actions.ActOnCompatiblityAlias(atLoc,
1090                                                    aliasId, aliasLoc,
1091                                                    classId, classLoc);
1092   return ClsType;
1093 }
1094 
1095 ///   property-synthesis:
1096 ///     @synthesize property-ivar-list ';'
1097 ///
1098 ///   property-ivar-list:
1099 ///     property-ivar
1100 ///     property-ivar-list ',' property-ivar
1101 ///
1102 ///   property-ivar:
1103 ///     identifier
1104 ///     identifier '=' identifier
1105 ///
1106 Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1107   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1108          "ParseObjCPropertyDynamic(): Expected '@synthesize'");
1109   SourceLocation loc = ConsumeToken(); // consume synthesize
1110   if (Tok.isNot(tok::identifier)) {
1111     Diag(Tok, diag::err_expected_ident);
1112     return 0;
1113   }
1114   while (Tok.is(tok::identifier)) {
1115     IdentifierInfo *propertyIvar = 0;
1116     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1117     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1118     if (Tok.is(tok::equal)) {
1119       // property '=' ivar-name
1120       ConsumeToken(); // consume '='
1121       if (Tok.isNot(tok::identifier)) {
1122         Diag(Tok, diag::err_expected_ident);
1123         break;
1124       }
1125       propertyIvar = Tok.getIdentifierInfo();
1126       ConsumeToken(); // consume ivar-name
1127     }
1128     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
1129                                   propertyId, propertyIvar);
1130     if (Tok.isNot(tok::comma))
1131       break;
1132     ConsumeToken(); // consume ','
1133   }
1134   if (Tok.isNot(tok::semi))
1135     Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
1136   return 0;
1137 }
1138 
1139 ///   property-dynamic:
1140 ///     @dynamic  property-list
1141 ///
1142 ///   property-list:
1143 ///     identifier
1144 ///     property-list ',' identifier
1145 ///
1146 Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1147   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1148          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1149   SourceLocation loc = ConsumeToken(); // consume dynamic
1150   if (Tok.isNot(tok::identifier)) {
1151     Diag(Tok, diag::err_expected_ident);
1152     return 0;
1153   }
1154   while (Tok.is(tok::identifier)) {
1155     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1156     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1157     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
1158                                   propertyId, 0);
1159 
1160     if (Tok.isNot(tok::comma))
1161       break;
1162     ConsumeToken(); // consume ','
1163   }
1164   if (Tok.isNot(tok::semi))
1165     Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
1166   return 0;
1167 }
1168 
1169 ///  objc-throw-statement:
1170 ///    throw expression[opt];
1171 ///
1172 Parser::StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
1173   ExprResult Res;
1174   ConsumeToken(); // consume throw
1175   if (Tok.isNot(tok::semi)) {
1176     Res = ParseExpression();
1177     if (Res.isInvalid) {
1178       SkipUntil(tok::semi);
1179       return true;
1180     }
1181   }
1182   ConsumeToken(); // consume ';'
1183   return Actions.ActOnObjCAtThrowStmt(atLoc, Res.Val);
1184 }
1185 
1186 /// objc-synchronized-statement:
1187 ///   @synchronized '(' expression ')' compound-statement
1188 ///
1189 Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
1190   ConsumeToken(); // consume synchronized
1191   if (Tok.isNot(tok::l_paren)) {
1192     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
1193     return true;
1194   }
1195   ConsumeParen();  // '('
1196   ExprResult Res = ParseExpression();
1197   if (Res.isInvalid) {
1198     SkipUntil(tok::semi);
1199     return true;
1200   }
1201   if (Tok.isNot(tok::r_paren)) {
1202     Diag(Tok, diag::err_expected_lbrace);
1203     return true;
1204   }
1205   ConsumeParen();  // ')'
1206   if (Tok.isNot(tok::l_brace)) {
1207     Diag(Tok, diag::err_expected_lbrace);
1208     return true;
1209   }
1210   // Enter a scope to hold everything within the compound stmt.  Compound
1211   // statements can always hold declarations.
1212   EnterScope(Scope::DeclScope);
1213 
1214   StmtResult SynchBody = ParseCompoundStatementBody();
1215 
1216   ExitScope();
1217   if (SynchBody.isInvalid)
1218     SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
1219   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.Val, SynchBody.Val);
1220 }
1221 
1222 ///  objc-try-catch-statement:
1223 ///    @try compound-statement objc-catch-list[opt]
1224 ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
1225 ///
1226 ///  objc-catch-list:
1227 ///    @catch ( parameter-declaration ) compound-statement
1228 ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1229 ///  catch-parameter-declaration:
1230 ///     parameter-declaration
1231 ///     '...' [OBJC2]
1232 ///
1233 Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
1234   bool catch_or_finally_seen = false;
1235 
1236   ConsumeToken(); // consume try
1237   if (Tok.isNot(tok::l_brace)) {
1238     Diag(Tok, diag::err_expected_lbrace);
1239     return true;
1240   }
1241   StmtResult CatchStmts;
1242   StmtResult FinallyStmt;
1243   EnterScope(Scope::DeclScope);
1244   StmtResult TryBody = ParseCompoundStatementBody();
1245   ExitScope();
1246   if (TryBody.isInvalid)
1247     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
1248 
1249   while (Tok.is(tok::at)) {
1250     // At this point, we need to lookahead to determine if this @ is the start
1251     // of an @catch or @finally.  We don't want to consume the @ token if this
1252     // is an @try or @encode or something else.
1253     Token AfterAt = GetLookAheadToken(1);
1254     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
1255         !AfterAt.isObjCAtKeyword(tok::objc_finally))
1256       break;
1257 
1258     SourceLocation AtCatchFinallyLoc = ConsumeToken();
1259     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
1260       StmtTy *FirstPart = 0;
1261       ConsumeToken(); // consume catch
1262       if (Tok.is(tok::l_paren)) {
1263         ConsumeParen();
1264         EnterScope(Scope::DeclScope);
1265         if (Tok.isNot(tok::ellipsis)) {
1266           DeclSpec DS;
1267           ParseDeclarationSpecifiers(DS);
1268           // For some odd reason, the name of the exception variable is
1269           // optional. As a result, we need to use PrototypeContext.
1270           Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
1271           ParseDeclarator(DeclaratorInfo);
1272           if (DeclaratorInfo.getIdentifier()) {
1273             DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope,
1274                                                           DeclaratorInfo, 0);
1275             StmtResult stmtResult =
1276               Actions.ActOnDeclStmt(aBlockVarDecl,
1277                                     DS.getSourceRange().getBegin(),
1278                                     DeclaratorInfo.getSourceRange().getEnd());
1279             FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
1280           }
1281         } else
1282           ConsumeToken(); // consume '...'
1283         SourceLocation RParenLoc = ConsumeParen();
1284 
1285         StmtResult CatchBody(true);
1286         if (Tok.is(tok::l_brace))
1287           CatchBody = ParseCompoundStatementBody();
1288         else
1289           Diag(Tok, diag::err_expected_lbrace);
1290         if (CatchBody.isInvalid)
1291           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
1292         CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc,
1293           FirstPart, CatchBody.Val, CatchStmts.Val);
1294         ExitScope();
1295       } else {
1296         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
1297           << "@catch clause";
1298         return true;
1299       }
1300       catch_or_finally_seen = true;
1301     } else {
1302       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
1303       ConsumeToken(); // consume finally
1304       EnterScope(Scope::DeclScope);
1305 
1306 
1307       StmtResult FinallyBody(true);
1308       if (Tok.is(tok::l_brace))
1309         FinallyBody = ParseCompoundStatementBody();
1310       else
1311         Diag(Tok, diag::err_expected_lbrace);
1312       if (FinallyBody.isInvalid)
1313         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
1314       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
1315                                                    FinallyBody.Val);
1316       catch_or_finally_seen = true;
1317       ExitScope();
1318       break;
1319     }
1320   }
1321   if (!catch_or_finally_seen) {
1322     Diag(atLoc, diag::err_missing_catch_finally);
1323     return true;
1324   }
1325   return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.Val, CatchStmts.Val,
1326                                     FinallyStmt.Val);
1327 }
1328 
1329 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
1330 ///
1331 Parser::DeclTy *Parser::ParseObjCMethodDefinition() {
1332   DeclTy *MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
1333   // parse optional ';'
1334   if (Tok.is(tok::semi))
1335     ConsumeToken();
1336 
1337   // We should have an opening brace now.
1338   if (Tok.isNot(tok::l_brace)) {
1339     Diag(Tok, diag::err_expected_method_body);
1340 
1341     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
1342     SkipUntil(tok::l_brace, true, true);
1343 
1344     // If we didn't find the '{', bail out.
1345     if (Tok.isNot(tok::l_brace))
1346       return 0;
1347   }
1348   SourceLocation BraceLoc = Tok.getLocation();
1349 
1350   // Enter a scope for the method body.
1351   EnterScope(Scope::FnScope|Scope::DeclScope);
1352 
1353   // Tell the actions module that we have entered a method definition with the
1354   // specified Declarator for the method.
1355   Actions.ObjCActOnStartOfMethodDef(CurScope, MDecl);
1356 
1357   StmtResult FnBody = ParseCompoundStatementBody();
1358 
1359   // If the function body could not be parsed, make a bogus compoundstmt.
1360   if (FnBody.isInvalid)
1361     FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, 0, 0, false);
1362 
1363   // Leave the function body scope.
1364   ExitScope();
1365 
1366   // TODO: Pass argument information.
1367   Actions.ActOnFinishFunctionBody(MDecl, FnBody.Val);
1368   return MDecl;
1369 }
1370 
1371 Parser::StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
1372   if (Tok.isObjCAtKeyword(tok::objc_try)) {
1373     return ParseObjCTryStmt(AtLoc);
1374   } else if (Tok.isObjCAtKeyword(tok::objc_throw))
1375     return ParseObjCThrowStmt(AtLoc);
1376   else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
1377     return ParseObjCSynchronizedStmt(AtLoc);
1378   ExprResult Res = ParseExpressionWithLeadingAt(AtLoc);
1379   if (Res.isInvalid) {
1380     // If the expression is invalid, skip ahead to the next semicolon. Not
1381     // doing this opens us up to the possibility of infinite loops if
1382     // ParseExpression does not consume any tokens.
1383     SkipUntil(tok::semi);
1384     return true;
1385   }
1386   // Otherwise, eat the semicolon.
1387   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1388   return Actions.ActOnExprStmt(Res.Val);
1389 }
1390 
1391 Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
1392   switch (Tok.getKind()) {
1393   case tok::string_literal:    // primary-expression: string-literal
1394   case tok::wide_string_literal:
1395     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
1396   default:
1397     if (Tok.getIdentifierInfo() == 0)
1398       return Diag(AtLoc, diag::err_unexpected_at);
1399 
1400     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
1401     case tok::objc_encode:
1402       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
1403     case tok::objc_protocol:
1404       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
1405     case tok::objc_selector:
1406       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
1407     default:
1408         return Diag(AtLoc, diag::err_unexpected_at);
1409     }
1410   }
1411 }
1412 
1413 ///   objc-message-expr:
1414 ///     '[' objc-receiver objc-message-args ']'
1415 ///
1416 ///   objc-receiver:
1417 ///     expression
1418 ///     class-name
1419 ///     type-name
1420 Parser::ExprResult Parser::ParseObjCMessageExpression() {
1421   assert(Tok.is(tok::l_square) && "'[' expected");
1422   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
1423 
1424   // Parse receiver
1425   if (isTokObjCMessageIdentifierReceiver()) {
1426     IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
1427     SourceLocation NameLoc = ConsumeToken();
1428     return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName, 0);
1429   }
1430 
1431   ExprResult Res = ParseExpression();
1432   if (Res.isInvalid) {
1433     SkipUntil(tok::r_square);
1434     return Res;
1435   }
1436 
1437   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 0, Res.Val);
1438 }
1439 
1440 /// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
1441 /// the rest of a message expression.
1442 ///
1443 ///   objc-message-args:
1444 ///     objc-selector
1445 ///     objc-keywordarg-list
1446 ///
1447 ///   objc-keywordarg-list:
1448 ///     objc-keywordarg
1449 ///     objc-keywordarg-list objc-keywordarg
1450 ///
1451 ///   objc-keywordarg:
1452 ///     selector-name[opt] ':' objc-keywordexpr
1453 ///
1454 ///   objc-keywordexpr:
1455 ///     nonempty-expr-list
1456 ///
1457 ///   nonempty-expr-list:
1458 ///     assignment-expression
1459 ///     nonempty-expr-list , assignment-expression
1460 ///
1461 Parser::ExprResult
1462 Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
1463                                        SourceLocation NameLoc,
1464                                        IdentifierInfo *ReceiverName,
1465                                        ExprTy *ReceiverExpr) {
1466   // Parse objc-selector
1467   SourceLocation Loc;
1468   IdentifierInfo *selIdent = ParseObjCSelector(Loc);
1469 
1470   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1471   llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
1472 
1473   if (Tok.is(tok::colon)) {
1474     while (1) {
1475       // Each iteration parses a single keyword argument.
1476       KeyIdents.push_back(selIdent);
1477 
1478       if (Tok.isNot(tok::colon)) {
1479         Diag(Tok, diag::err_expected_colon);
1480         // We must manually skip to a ']', otherwise the expression skipper will
1481         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1482         // the enclosing expression.
1483         SkipUntil(tok::r_square);
1484         return true;
1485       }
1486 
1487       ConsumeToken(); // Eat the ':'.
1488       ///  Parse the expression after ':'
1489       ExprResult Res = ParseAssignmentExpression();
1490       if (Res.isInvalid) {
1491         // We must manually skip to a ']', otherwise the expression skipper will
1492         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1493         // the enclosing expression.
1494         SkipUntil(tok::r_square);
1495         return Res;
1496       }
1497 
1498       // We have a valid expression.
1499       KeyExprs.push_back(Res.Val);
1500 
1501       // Check for another keyword selector.
1502       selIdent = ParseObjCSelector(Loc);
1503       if (!selIdent && Tok.isNot(tok::colon))
1504         break;
1505       // We have a selector or a colon, continue parsing.
1506     }
1507     // Parse the, optional, argument list, comma separated.
1508     while (Tok.is(tok::comma)) {
1509       ConsumeToken(); // Eat the ','.
1510       ///  Parse the expression after ','
1511       ExprResult Res = ParseAssignmentExpression();
1512       if (Res.isInvalid) {
1513         // We must manually skip to a ']', otherwise the expression skipper will
1514         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1515         // the enclosing expression.
1516         SkipUntil(tok::r_square);
1517         return Res;
1518       }
1519 
1520       // We have a valid expression.
1521       KeyExprs.push_back(Res.Val);
1522     }
1523   } else if (!selIdent) {
1524     Diag(Tok, diag::err_expected_ident); // missing selector name.
1525 
1526     // We must manually skip to a ']', otherwise the expression skipper will
1527     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1528     // the enclosing expression.
1529     SkipUntil(tok::r_square);
1530     return true;
1531   }
1532 
1533   if (Tok.isNot(tok::r_square)) {
1534     Diag(Tok, diag::err_expected_rsquare);
1535     // We must manually skip to a ']', otherwise the expression skipper will
1536     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1537     // the enclosing expression.
1538     SkipUntil(tok::r_square);
1539     return true;
1540   }
1541 
1542   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
1543 
1544   unsigned nKeys = KeyIdents.size();
1545   if (nKeys == 0)
1546     KeyIdents.push_back(selIdent);
1547   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
1548 
1549   // We've just parsed a keyword message.
1550   if (ReceiverName)
1551     return Actions.ActOnClassMessage(CurScope,
1552                                      ReceiverName, Sel,
1553                                      LBracLoc, NameLoc, RBracLoc,
1554                                      &KeyExprs[0], KeyExprs.size());
1555   return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
1556                                       &KeyExprs[0], KeyExprs.size());
1557 }
1558 
1559 Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
1560   ExprResult Res = ParseStringLiteralExpression();
1561   if (Res.isInvalid) return Res;
1562 
1563   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
1564   // expressions.  At this point, we know that the only valid thing that starts
1565   // with '@' is an @"".
1566   llvm::SmallVector<SourceLocation, 4> AtLocs;
1567   llvm::SmallVector<ExprTy*, 4> AtStrings;
1568   AtLocs.push_back(AtLoc);
1569   AtStrings.push_back(Res.Val);
1570 
1571   while (Tok.is(tok::at)) {
1572     AtLocs.push_back(ConsumeToken()); // eat the @.
1573 
1574     ExprResult Res(true);  // Invalid unless there is a string literal.
1575     if (isTokenStringLiteral())
1576       Res = ParseStringLiteralExpression();
1577     else
1578       Diag(Tok, diag::err_objc_concat_string);
1579 
1580     if (Res.isInvalid) {
1581       while (!AtStrings.empty()) {
1582         Actions.DeleteExpr(AtStrings.back());
1583         AtStrings.pop_back();
1584       }
1585       return Res;
1586     }
1587 
1588     AtStrings.push_back(Res.Val);
1589   }
1590 
1591   return Actions.ParseObjCStringLiteral(&AtLocs[0], &AtStrings[0],
1592                                         AtStrings.size());
1593 }
1594 
1595 ///    objc-encode-expression:
1596 ///      @encode ( type-name )
1597 Parser::ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
1598   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
1599 
1600   SourceLocation EncLoc = ConsumeToken();
1601 
1602   if (Tok.isNot(tok::l_paren))
1603     return Diag(Tok, diag::err_expected_lparen_after) << "@encode";
1604 
1605   SourceLocation LParenLoc = ConsumeParen();
1606 
1607   TypeTy *Ty = ParseTypeName();
1608 
1609   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1610 
1611   return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty,
1612                                            RParenLoc);
1613 }
1614 
1615 ///     objc-protocol-expression
1616 ///       @protocol ( protocol-name )
1617 
1618 Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
1619   SourceLocation ProtoLoc = ConsumeToken();
1620 
1621   if (Tok.isNot(tok::l_paren))
1622     return Diag(Tok, diag::err_expected_lparen_after) << "@protocol";
1623 
1624   SourceLocation LParenLoc = ConsumeParen();
1625 
1626   if (Tok.isNot(tok::identifier))
1627     return Diag(Tok, diag::err_expected_ident);
1628 
1629   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
1630   ConsumeToken();
1631 
1632   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1633 
1634   return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
1635                                              LParenLoc, RParenLoc);
1636 }
1637 
1638 ///     objc-selector-expression
1639 ///       @selector '(' objc-keyword-selector ')'
1640 Parser::ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
1641   SourceLocation SelectorLoc = ConsumeToken();
1642 
1643   if (Tok.isNot(tok::l_paren))
1644     return Diag(Tok, diag::err_expected_lparen_after) << "@selector";
1645 
1646   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1647   SourceLocation LParenLoc = ConsumeParen();
1648   SourceLocation sLoc;
1649   IdentifierInfo *SelIdent = ParseObjCSelector(sLoc);
1650   if (!SelIdent && Tok.isNot(tok::colon))
1651     return Diag(Tok, diag::err_expected_ident); // missing selector name.
1652 
1653   KeyIdents.push_back(SelIdent);
1654   unsigned nColons = 0;
1655   if (Tok.isNot(tok::r_paren)) {
1656     while (1) {
1657       if (Tok.isNot(tok::colon))
1658         return Diag(Tok, diag::err_expected_colon);
1659 
1660       nColons++;
1661       ConsumeToken(); // Eat the ':'.
1662       if (Tok.is(tok::r_paren))
1663         break;
1664       // Check for another keyword selector.
1665       SourceLocation Loc;
1666       SelIdent = ParseObjCSelector(Loc);
1667       KeyIdents.push_back(SelIdent);
1668       if (!SelIdent && Tok.isNot(tok::colon))
1669         break;
1670     }
1671   }
1672   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1673   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
1674   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, LParenLoc,
1675                                              RParenLoc);
1676  }
1677