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