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