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