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