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