xref: /llvm-project/clang/lib/Parse/ParseObjc.cpp (revision 5b4671c32835cfe7eee13e28fe8b13d1b53c9db6)
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.is(tok::code_completion)) {
998     Actions.CodeCompleteObjCProtocolDecl(CurScope);
999     ConsumeToken();
1000   }
1001 
1002   if (Tok.isNot(tok::identifier)) {
1003     Diag(Tok, diag::err_expected_ident); // missing protocol name.
1004     return DeclPtrTy();
1005   }
1006   // Save the protocol name, then consume it.
1007   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
1008   SourceLocation nameLoc = ConsumeToken();
1009 
1010   if (Tok.is(tok::semi)) { // forward declaration of one protocol.
1011     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
1012     ConsumeToken();
1013     return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
1014                                                    attrList);
1015   }
1016 
1017   if (Tok.is(tok::comma)) { // list of forward declarations.
1018     llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
1019     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
1020 
1021     // Parse the list of forward declarations.
1022     while (1) {
1023       ConsumeToken(); // the ','
1024       if (Tok.isNot(tok::identifier)) {
1025         Diag(Tok, diag::err_expected_ident);
1026         SkipUntil(tok::semi);
1027         return DeclPtrTy();
1028       }
1029       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
1030                                                Tok.getLocation()));
1031       ConsumeToken(); // the identifier
1032 
1033       if (Tok.isNot(tok::comma))
1034         break;
1035     }
1036     // Consume the ';'.
1037     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
1038       return DeclPtrTy();
1039 
1040     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
1041                                                    &ProtocolRefs[0],
1042                                                    ProtocolRefs.size(),
1043                                                    attrList);
1044   }
1045 
1046   // Last, and definitely not least, parse a protocol declaration.
1047   SourceLocation LAngleLoc, EndProtoLoc;
1048 
1049   llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
1050   llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
1051   if (Tok.is(tok::less) &&
1052       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
1053                                   LAngleLoc, EndProtoLoc))
1054     return DeclPtrTy();
1055 
1056   DeclPtrTy ProtoType =
1057     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
1058                                         ProtocolRefs.data(),
1059                                         ProtocolRefs.size(),
1060                                         EndProtoLoc, attrList);
1061   ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
1062   return ProtoType;
1063 }
1064 
1065 ///   objc-implementation:
1066 ///     objc-class-implementation-prologue
1067 ///     objc-category-implementation-prologue
1068 ///
1069 ///   objc-class-implementation-prologue:
1070 ///     @implementation identifier objc-superclass[opt]
1071 ///       objc-class-instance-variables[opt]
1072 ///
1073 ///   objc-category-implementation-prologue:
1074 ///     @implementation identifier ( identifier )
1075 Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
1076   SourceLocation atLoc) {
1077   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
1078          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
1079   ConsumeToken(); // the "implementation" identifier
1080 
1081   if (Tok.isNot(tok::identifier)) {
1082     Diag(Tok, diag::err_expected_ident); // missing class or category name.
1083     return DeclPtrTy();
1084   }
1085   // We have a class or category name - consume it.
1086   IdentifierInfo *nameId = Tok.getIdentifierInfo();
1087   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
1088 
1089   if (Tok.is(tok::l_paren)) {
1090     // we have a category implementation.
1091     SourceLocation lparenLoc = ConsumeParen();
1092     SourceLocation categoryLoc, rparenLoc;
1093     IdentifierInfo *categoryId = 0;
1094 
1095     if (Tok.is(tok::identifier)) {
1096       categoryId = Tok.getIdentifierInfo();
1097       categoryLoc = ConsumeToken();
1098     } else {
1099       Diag(Tok, diag::err_expected_ident); // missing category name.
1100       return DeclPtrTy();
1101     }
1102     if (Tok.isNot(tok::r_paren)) {
1103       Diag(Tok, diag::err_expected_rparen);
1104       SkipUntil(tok::r_paren, false); // don't stop at ';'
1105       return DeclPtrTy();
1106     }
1107     rparenLoc = ConsumeParen();
1108     DeclPtrTy ImplCatType = Actions.ActOnStartCategoryImplementation(
1109                                     atLoc, nameId, nameLoc, categoryId,
1110                                     categoryLoc);
1111     ObjCImpDecl = ImplCatType;
1112     PendingObjCImpDecl.push_back(ObjCImpDecl);
1113     return DeclPtrTy();
1114   }
1115   // We have a class implementation
1116   SourceLocation superClassLoc;
1117   IdentifierInfo *superClassId = 0;
1118   if (Tok.is(tok::colon)) {
1119     // We have a super class
1120     ConsumeToken();
1121     if (Tok.isNot(tok::identifier)) {
1122       Diag(Tok, diag::err_expected_ident); // missing super class name.
1123       return DeclPtrTy();
1124     }
1125     superClassId = Tok.getIdentifierInfo();
1126     superClassLoc = ConsumeToken(); // Consume super class name
1127   }
1128   DeclPtrTy ImplClsType = Actions.ActOnStartClassImplementation(
1129                                   atLoc, nameId, nameLoc,
1130                                   superClassId, superClassLoc);
1131 
1132   if (Tok.is(tok::l_brace)) // we have ivars
1133     ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
1134   ObjCImpDecl = ImplClsType;
1135   PendingObjCImpDecl.push_back(ObjCImpDecl);
1136 
1137   return DeclPtrTy();
1138 }
1139 
1140 Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
1141   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
1142          "ParseObjCAtEndDeclaration(): Expected @end");
1143   DeclPtrTy Result = ObjCImpDecl;
1144   ConsumeToken(); // the "end" identifier
1145   if (ObjCImpDecl) {
1146     Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
1147     ObjCImpDecl = DeclPtrTy();
1148     PendingObjCImpDecl.pop_back();
1149   }
1150   else
1151     Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
1152   return Result;
1153 }
1154 
1155 Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
1156   if (PendingObjCImpDecl.empty())
1157     return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
1158   DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
1159   Actions.ActOnAtEnd(SourceLocation(), ImpDecl);
1160   return Actions.ConvertDeclToDeclGroup(ImpDecl);
1161 }
1162 
1163 ///   compatibility-alias-decl:
1164 ///     @compatibility_alias alias-name  class-name ';'
1165 ///
1166 Parser::DeclPtrTy Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
1167   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
1168          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
1169   ConsumeToken(); // consume compatibility_alias
1170   if (Tok.isNot(tok::identifier)) {
1171     Diag(Tok, diag::err_expected_ident);
1172     return DeclPtrTy();
1173   }
1174   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
1175   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
1176   if (Tok.isNot(tok::identifier)) {
1177     Diag(Tok, diag::err_expected_ident);
1178     return DeclPtrTy();
1179   }
1180   IdentifierInfo *classId = Tok.getIdentifierInfo();
1181   SourceLocation classLoc = ConsumeToken(); // consume class-name;
1182   if (Tok.isNot(tok::semi)) {
1183     Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
1184     return DeclPtrTy();
1185   }
1186   return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc,
1187                                         classId, classLoc);
1188 }
1189 
1190 ///   property-synthesis:
1191 ///     @synthesize property-ivar-list ';'
1192 ///
1193 ///   property-ivar-list:
1194 ///     property-ivar
1195 ///     property-ivar-list ',' property-ivar
1196 ///
1197 ///   property-ivar:
1198 ///     identifier
1199 ///     identifier '=' identifier
1200 ///
1201 Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1202   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1203          "ParseObjCPropertyDynamic(): Expected '@synthesize'");
1204   SourceLocation loc = ConsumeToken(); // consume synthesize
1205   if (Tok.isNot(tok::identifier)) {
1206     Diag(Tok, diag::err_expected_ident);
1207     return DeclPtrTy();
1208   }
1209 
1210   while (Tok.is(tok::identifier)) {
1211     IdentifierInfo *propertyIvar = 0;
1212     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1213     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1214     if (Tok.is(tok::equal)) {
1215       // property '=' ivar-name
1216       ConsumeToken(); // consume '='
1217       if (Tok.isNot(tok::identifier)) {
1218         Diag(Tok, diag::err_expected_ident);
1219         break;
1220       }
1221       propertyIvar = Tok.getIdentifierInfo();
1222       ConsumeToken(); // consume ivar-name
1223     }
1224     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
1225                                   propertyId, propertyIvar);
1226     if (Tok.isNot(tok::comma))
1227       break;
1228     ConsumeToken(); // consume ','
1229   }
1230   if (Tok.isNot(tok::semi))
1231     Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
1232   else
1233     ConsumeToken(); // consume ';'
1234   return DeclPtrTy();
1235 }
1236 
1237 ///   property-dynamic:
1238 ///     @dynamic  property-list
1239 ///
1240 ///   property-list:
1241 ///     identifier
1242 ///     property-list ',' identifier
1243 ///
1244 Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1245   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1246          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1247   SourceLocation loc = ConsumeToken(); // consume dynamic
1248   if (Tok.isNot(tok::identifier)) {
1249     Diag(Tok, diag::err_expected_ident);
1250     return DeclPtrTy();
1251   }
1252   while (Tok.is(tok::identifier)) {
1253     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1254     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1255     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
1256                                   propertyId, 0);
1257 
1258     if (Tok.isNot(tok::comma))
1259       break;
1260     ConsumeToken(); // consume ','
1261   }
1262   if (Tok.isNot(tok::semi))
1263     Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
1264   return DeclPtrTy();
1265 }
1266 
1267 ///  objc-throw-statement:
1268 ///    throw expression[opt];
1269 ///
1270 Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
1271   OwningExprResult Res(Actions);
1272   ConsumeToken(); // consume throw
1273   if (Tok.isNot(tok::semi)) {
1274     Res = ParseExpression();
1275     if (Res.isInvalid()) {
1276       SkipUntil(tok::semi);
1277       return StmtError();
1278     }
1279   }
1280   ConsumeToken(); // consume ';'
1281   return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope);
1282 }
1283 
1284 /// objc-synchronized-statement:
1285 ///   @synchronized '(' expression ')' compound-statement
1286 ///
1287 Parser::OwningStmtResult
1288 Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
1289   ConsumeToken(); // consume synchronized
1290   if (Tok.isNot(tok::l_paren)) {
1291     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
1292     return StmtError();
1293   }
1294   ConsumeParen();  // '('
1295   OwningExprResult Res(ParseExpression());
1296   if (Res.isInvalid()) {
1297     SkipUntil(tok::semi);
1298     return StmtError();
1299   }
1300   if (Tok.isNot(tok::r_paren)) {
1301     Diag(Tok, diag::err_expected_lbrace);
1302     return StmtError();
1303   }
1304   ConsumeParen();  // ')'
1305   if (Tok.isNot(tok::l_brace)) {
1306     Diag(Tok, diag::err_expected_lbrace);
1307     return StmtError();
1308   }
1309   // Enter a scope to hold everything within the compound stmt.  Compound
1310   // statements can always hold declarations.
1311   ParseScope BodyScope(this, Scope::DeclScope);
1312 
1313   OwningStmtResult SynchBody(ParseCompoundStatementBody());
1314 
1315   BodyScope.Exit();
1316   if (SynchBody.isInvalid())
1317     SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
1318   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody));
1319 }
1320 
1321 ///  objc-try-catch-statement:
1322 ///    @try compound-statement objc-catch-list[opt]
1323 ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
1324 ///
1325 ///  objc-catch-list:
1326 ///    @catch ( parameter-declaration ) compound-statement
1327 ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1328 ///  catch-parameter-declaration:
1329 ///     parameter-declaration
1330 ///     '...' [OBJC2]
1331 ///
1332 Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
1333   bool catch_or_finally_seen = false;
1334 
1335   ConsumeToken(); // consume try
1336   if (Tok.isNot(tok::l_brace)) {
1337     Diag(Tok, diag::err_expected_lbrace);
1338     return StmtError();
1339   }
1340   OwningStmtResult CatchStmts(Actions);
1341   OwningStmtResult FinallyStmt(Actions);
1342   ParseScope TryScope(this, Scope::DeclScope);
1343   OwningStmtResult TryBody(ParseCompoundStatementBody());
1344   TryScope.Exit();
1345   if (TryBody.isInvalid())
1346     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
1347 
1348   while (Tok.is(tok::at)) {
1349     // At this point, we need to lookahead to determine if this @ is the start
1350     // of an @catch or @finally.  We don't want to consume the @ token if this
1351     // is an @try or @encode or something else.
1352     Token AfterAt = GetLookAheadToken(1);
1353     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
1354         !AfterAt.isObjCAtKeyword(tok::objc_finally))
1355       break;
1356 
1357     SourceLocation AtCatchFinallyLoc = ConsumeToken();
1358     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
1359       DeclPtrTy FirstPart;
1360       ConsumeToken(); // consume catch
1361       if (Tok.is(tok::l_paren)) {
1362         ConsumeParen();
1363         ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
1364         if (Tok.isNot(tok::ellipsis)) {
1365           DeclSpec DS;
1366           ParseDeclarationSpecifiers(DS);
1367           // For some odd reason, the name of the exception variable is
1368           // optional. As a result, we need to use "PrototypeContext", because
1369           // we must accept either 'declarator' or 'abstract-declarator' here.
1370           Declarator ParmDecl(DS, Declarator::PrototypeContext);
1371           ParseDeclarator(ParmDecl);
1372 
1373           // Inform the actions module about the parameter declarator, so it
1374           // gets added to the current scope.
1375           FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
1376         } else
1377           ConsumeToken(); // consume '...'
1378 
1379         SourceLocation RParenLoc;
1380 
1381         if (Tok.is(tok::r_paren))
1382           RParenLoc = ConsumeParen();
1383         else // Skip over garbage, until we get to ')'.  Eat the ')'.
1384           SkipUntil(tok::r_paren, true, false);
1385 
1386         OwningStmtResult CatchBody(Actions, true);
1387         if (Tok.is(tok::l_brace))
1388           CatchBody = ParseCompoundStatementBody();
1389         else
1390           Diag(Tok, diag::err_expected_lbrace);
1391         if (CatchBody.isInvalid())
1392           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
1393         CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
1394                         RParenLoc, FirstPart, move(CatchBody),
1395                         move(CatchStmts));
1396       } else {
1397         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
1398           << "@catch clause";
1399         return StmtError();
1400       }
1401       catch_or_finally_seen = true;
1402     } else {
1403       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
1404       ConsumeToken(); // consume finally
1405       ParseScope FinallyScope(this, Scope::DeclScope);
1406 
1407       OwningStmtResult FinallyBody(Actions, true);
1408       if (Tok.is(tok::l_brace))
1409         FinallyBody = ParseCompoundStatementBody();
1410       else
1411         Diag(Tok, diag::err_expected_lbrace);
1412       if (FinallyBody.isInvalid())
1413         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
1414       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
1415                                                    move(FinallyBody));
1416       catch_or_finally_seen = true;
1417       break;
1418     }
1419   }
1420   if (!catch_or_finally_seen) {
1421     Diag(atLoc, diag::err_missing_catch_finally);
1422     return StmtError();
1423   }
1424   return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody), move(CatchStmts),
1425                                     move(FinallyStmt));
1426 }
1427 
1428 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
1429 ///
1430 Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
1431   DeclPtrTy MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
1432 
1433   PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
1434                                         PP.getSourceManager(),
1435                                         "parsing Objective-C method");
1436 
1437   // parse optional ';'
1438   if (Tok.is(tok::semi)) {
1439     if (ObjCImpDecl) {
1440       Diag(Tok, diag::warn_semicolon_before_method_body)
1441         << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
1442     }
1443     ConsumeToken();
1444   }
1445 
1446   // We should have an opening brace now.
1447   if (Tok.isNot(tok::l_brace)) {
1448     Diag(Tok, diag::err_expected_method_body);
1449 
1450     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
1451     SkipUntil(tok::l_brace, true, true);
1452 
1453     // If we didn't find the '{', bail out.
1454     if (Tok.isNot(tok::l_brace))
1455       return DeclPtrTy();
1456   }
1457   SourceLocation BraceLoc = Tok.getLocation();
1458 
1459   // Enter a scope for the method body.
1460   ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
1461 
1462   // Tell the actions module that we have entered a method definition with the
1463   // specified Declarator for the method.
1464   Actions.ActOnStartOfObjCMethodDef(CurScope, MDecl);
1465 
1466   OwningStmtResult FnBody(ParseCompoundStatementBody());
1467 
1468   // If the function body could not be parsed, make a bogus compoundstmt.
1469   if (FnBody.isInvalid())
1470     FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
1471                                        MultiStmtArg(Actions), false);
1472 
1473   // TODO: Pass argument information.
1474   Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
1475 
1476   // Leave the function body scope.
1477   BodyScope.Exit();
1478 
1479   return MDecl;
1480 }
1481 
1482 Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
1483   if (Tok.isObjCAtKeyword(tok::objc_try)) {
1484     return ParseObjCTryStmt(AtLoc);
1485   } else if (Tok.isObjCAtKeyword(tok::objc_throw))
1486     return ParseObjCThrowStmt(AtLoc);
1487   else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
1488     return ParseObjCSynchronizedStmt(AtLoc);
1489   OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
1490   if (Res.isInvalid()) {
1491     // If the expression is invalid, skip ahead to the next semicolon. Not
1492     // doing this opens us up to the possibility of infinite loops if
1493     // ParseExpression does not consume any tokens.
1494     SkipUntil(tok::semi);
1495     return StmtError();
1496   }
1497   // Otherwise, eat the semicolon.
1498   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1499   return Actions.ActOnExprStmt(Actions.FullExpr(Res));
1500 }
1501 
1502 Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
1503   switch (Tok.getKind()) {
1504   case tok::string_literal:    // primary-expression: string-literal
1505   case tok::wide_string_literal:
1506     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
1507   default:
1508     if (Tok.getIdentifierInfo() == 0)
1509       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
1510 
1511     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
1512     case tok::objc_encode:
1513       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
1514     case tok::objc_protocol:
1515       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
1516     case tok::objc_selector:
1517       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
1518     default:
1519       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
1520     }
1521   }
1522 }
1523 
1524 ///   objc-message-expr:
1525 ///     '[' objc-receiver objc-message-args ']'
1526 ///
1527 ///   objc-receiver:
1528 ///     expression
1529 ///     class-name
1530 ///     type-name
1531 Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
1532   assert(Tok.is(tok::l_square) && "'[' expected");
1533   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
1534 
1535   // Parse receiver
1536   if (isTokObjCMessageIdentifierReceiver()) {
1537     IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
1538     if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
1539       SourceLocation NameLoc = ConsumeToken();
1540       return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
1541                                             ExprArg(Actions));
1542     }
1543   }
1544 
1545   OwningExprResult Res(ParseExpression());
1546   if (Res.isInvalid()) {
1547     SkipUntil(tok::r_square);
1548     return move(Res);
1549   }
1550 
1551   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
1552                                         0, move(Res));
1553 }
1554 
1555 /// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
1556 /// the rest of a message expression.
1557 ///
1558 ///   objc-message-args:
1559 ///     objc-selector
1560 ///     objc-keywordarg-list
1561 ///
1562 ///   objc-keywordarg-list:
1563 ///     objc-keywordarg
1564 ///     objc-keywordarg-list objc-keywordarg
1565 ///
1566 ///   objc-keywordarg:
1567 ///     selector-name[opt] ':' objc-keywordexpr
1568 ///
1569 ///   objc-keywordexpr:
1570 ///     nonempty-expr-list
1571 ///
1572 ///   nonempty-expr-list:
1573 ///     assignment-expression
1574 ///     nonempty-expr-list , assignment-expression
1575 ///
1576 Parser::OwningExprResult
1577 Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
1578                                        SourceLocation NameLoc,
1579                                        IdentifierInfo *ReceiverName,
1580                                        ExprArg ReceiverExpr) {
1581   if (Tok.is(tok::code_completion)) {
1582     if (ReceiverName)
1583       Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc);
1584     else
1585       Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get());
1586     ConsumeToken();
1587   }
1588   // Parse objc-selector
1589   SourceLocation Loc;
1590   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
1591 
1592   SourceLocation SelectorLoc = Loc;
1593 
1594   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1595   ExprVector KeyExprs(Actions);
1596 
1597   if (Tok.is(tok::colon)) {
1598     while (1) {
1599       // Each iteration parses a single keyword argument.
1600       KeyIdents.push_back(selIdent);
1601 
1602       if (Tok.isNot(tok::colon)) {
1603         Diag(Tok, diag::err_expected_colon);
1604         // We must manually skip to a ']', otherwise the expression skipper will
1605         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1606         // the enclosing expression.
1607         SkipUntil(tok::r_square);
1608         return ExprError();
1609       }
1610 
1611       ConsumeToken(); // Eat the ':'.
1612       ///  Parse the expression after ':'
1613       OwningExprResult Res(ParseAssignmentExpression());
1614       if (Res.isInvalid()) {
1615         // We must manually skip to a ']', otherwise the expression skipper will
1616         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1617         // the enclosing expression.
1618         SkipUntil(tok::r_square);
1619         return move(Res);
1620       }
1621 
1622       // We have a valid expression.
1623       KeyExprs.push_back(Res.release());
1624 
1625       // Check for another keyword selector.
1626       selIdent = ParseObjCSelectorPiece(Loc);
1627       if (!selIdent && Tok.isNot(tok::colon))
1628         break;
1629       // We have a selector or a colon, continue parsing.
1630     }
1631     // Parse the, optional, argument list, comma separated.
1632     while (Tok.is(tok::comma)) {
1633       ConsumeToken(); // Eat the ','.
1634       ///  Parse the expression after ','
1635       OwningExprResult Res(ParseAssignmentExpression());
1636       if (Res.isInvalid()) {
1637         // We must manually skip to a ']', otherwise the expression skipper will
1638         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1639         // the enclosing expression.
1640         SkipUntil(tok::r_square);
1641         return move(Res);
1642       }
1643 
1644       // We have a valid expression.
1645       KeyExprs.push_back(Res.release());
1646     }
1647   } else if (!selIdent) {
1648     Diag(Tok, diag::err_expected_ident); // missing selector name.
1649 
1650     // We must manually skip to a ']', otherwise the expression skipper will
1651     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1652     // the enclosing expression.
1653     SkipUntil(tok::r_square);
1654     return ExprError();
1655   }
1656 
1657   if (Tok.isNot(tok::r_square)) {
1658     Diag(Tok, diag::err_expected_rsquare);
1659     // We must manually skip to a ']', otherwise the expression skipper will
1660     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1661     // the enclosing expression.
1662     SkipUntil(tok::r_square);
1663     return ExprError();
1664   }
1665 
1666   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
1667 
1668   unsigned nKeys = KeyIdents.size();
1669   if (nKeys == 0)
1670     KeyIdents.push_back(selIdent);
1671   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
1672 
1673   // We've just parsed a keyword message.
1674   if (ReceiverName)
1675     return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
1676                                            LBracLoc, NameLoc, SelectorLoc,
1677                                            RBracLoc,
1678                                            KeyExprs.take(), KeyExprs.size()));
1679   return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
1680                                             LBracLoc, SelectorLoc, RBracLoc,
1681                                             KeyExprs.take(), KeyExprs.size()));
1682 }
1683 
1684 Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
1685   OwningExprResult Res(ParseStringLiteralExpression());
1686   if (Res.isInvalid()) return move(Res);
1687 
1688   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
1689   // expressions.  At this point, we know that the only valid thing that starts
1690   // with '@' is an @"".
1691   llvm::SmallVector<SourceLocation, 4> AtLocs;
1692   ExprVector AtStrings(Actions);
1693   AtLocs.push_back(AtLoc);
1694   AtStrings.push_back(Res.release());
1695 
1696   while (Tok.is(tok::at)) {
1697     AtLocs.push_back(ConsumeToken()); // eat the @.
1698 
1699     // Invalid unless there is a string literal.
1700     if (!isTokenStringLiteral())
1701       return ExprError(Diag(Tok, diag::err_objc_concat_string));
1702 
1703     OwningExprResult Lit(ParseStringLiteralExpression());
1704     if (Lit.isInvalid())
1705       return move(Lit);
1706 
1707     AtStrings.push_back(Lit.release());
1708   }
1709 
1710   return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
1711                                               AtStrings.size()));
1712 }
1713 
1714 ///    objc-encode-expression:
1715 ///      @encode ( type-name )
1716 Parser::OwningExprResult
1717 Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
1718   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
1719 
1720   SourceLocation EncLoc = ConsumeToken();
1721 
1722   if (Tok.isNot(tok::l_paren))
1723     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
1724 
1725   SourceLocation LParenLoc = ConsumeParen();
1726 
1727   TypeResult Ty = ParseTypeName();
1728 
1729   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1730 
1731   if (Ty.isInvalid())
1732     return ExprError();
1733 
1734   return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
1735                                                  Ty.get(), RParenLoc));
1736 }
1737 
1738 ///     objc-protocol-expression
1739 ///       @protocol ( protocol-name )
1740 Parser::OwningExprResult
1741 Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
1742   SourceLocation ProtoLoc = ConsumeToken();
1743 
1744   if (Tok.isNot(tok::l_paren))
1745     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
1746 
1747   SourceLocation LParenLoc = ConsumeParen();
1748 
1749   if (Tok.isNot(tok::identifier))
1750     return ExprError(Diag(Tok, diag::err_expected_ident));
1751 
1752   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
1753   ConsumeToken();
1754 
1755   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1756 
1757   return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
1758                                                    LParenLoc, RParenLoc));
1759 }
1760 
1761 ///     objc-selector-expression
1762 ///       @selector '(' objc-keyword-selector ')'
1763 Parser::OwningExprResult
1764 Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
1765   SourceLocation SelectorLoc = ConsumeToken();
1766 
1767   if (Tok.isNot(tok::l_paren))
1768     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
1769 
1770   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1771   SourceLocation LParenLoc = ConsumeParen();
1772   SourceLocation sLoc;
1773   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
1774   if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name.
1775     return ExprError(Diag(Tok, diag::err_expected_ident));
1776 
1777   KeyIdents.push_back(SelIdent);
1778   unsigned nColons = 0;
1779   if (Tok.isNot(tok::r_paren)) {
1780     while (1) {
1781       if (Tok.isNot(tok::colon))
1782         return ExprError(Diag(Tok, diag::err_expected_colon));
1783 
1784       nColons++;
1785       ConsumeToken(); // Eat the ':'.
1786       if (Tok.is(tok::r_paren))
1787         break;
1788       // Check for another keyword selector.
1789       SourceLocation Loc;
1790       SelIdent = ParseObjCSelectorPiece(Loc);
1791       KeyIdents.push_back(SelIdent);
1792       if (!SelIdent && Tok.isNot(tok::colon))
1793         break;
1794     }
1795   }
1796   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1797   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
1798   return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
1799                                                    LParenLoc, RParenLoc));
1800  }
1801