1 //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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
30 Parser::DeclPtrTy
Parser::ParseObjCAtDirectives() {
31 SourceLocation AtLoc
= ConsumeToken(); // the "@"
33 switch (Tok
.getObjCKeywordID()) {
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
);
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
);
51 Diag(AtLoc
, diag::err_unexpected_at
);
58 /// objc-class-declaration:
59 /// '@' 'class' identifier-list ';'
61 Parser::DeclPtrTy
Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc
) {
62 ConsumeToken(); // the identifier "class"
63 llvm::SmallVector
<IdentifierInfo
*, 8> ClassNames
;
66 if (Tok
.isNot(tok::identifier
)) {
67 Diag(Tok
, diag::err_expected_ident
);
71 ClassNames
.push_back(Tok
.getIdentifierInfo());
74 if (Tok
.isNot(tok::comma
))
81 if (ExpectAndConsume(tok::semi
, diag::err_expected_semi_after
, "@class"))
84 return Actions
.ActOnForwardClassDeclaration(atLoc
,
85 &ClassNames
[0], ClassNames
.size());
90 /// objc-class-interface-attributes[opt] objc-class-interface
91 /// objc-category-interface
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
100 /// objc-category-interface:
101 /// '@' 'interface' identifier '(' identifier[opt] ')'
102 /// objc-protocol-refs[opt]
103 /// objc-interface-decl-list
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.
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.
143 if (Tok
.isNot(tok::r_paren
)) {
144 Diag(Tok
, diag::err_expected_rparen
);
145 SkipUntil(tok::r_paren
, false); // don't stop at ';'
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
))
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
,
163 categoryId
, categoryLoc
,
168 ParseObjCInterfaceDeclList(CategoryType
, tok::objc_not_keyword
);
171 // Parse a class interface.
172 IdentifierInfo
*superClassId
= 0;
173 SourceLocation superClassLoc
;
175 if (Tok
.is(tok::colon
)) { // a super class is specified.
177 if (Tok
.isNot(tok::identifier
)) {
178 Diag(Tok
, diag::err_expected_ident
); // missing super class name.
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
))
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
);
204 /// objc-interface-decl-list:
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]
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
;
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
,
238 // Ignore excess semicolons.
239 if (Tok
.is(tok::semi
)) {
244 // If we got to the end of the file, exit the loop.
245 if (Tok
.is(tok::eof
))
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
))
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());
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
271 // Eat the identifier.
274 switch (DirectiveKind
) {
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
);
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
);
292 MethodImplKind
= DirectiveKind
;
295 case tok::objc_property
:
296 if (!getLang().ObjC2
)
297 Diag(AtLoc
, diag::err_objc_propertoes_require_objc2
);
300 // Parse property attribute list, if any.
301 if (Tok
.is(tok::l_paren
))
302 ParseObjCPropertyAttribute(OCDS
);
304 // Parse all the comma separated declarators.
306 llvm::SmallVector
<FieldDeclarator
, 8> FieldDeclarators
;
307 ParseStructDeclaration(DS
, FieldDeclarators
);
309 ExpectAndConsume(tok::semi
, diag::err_expected_semi_decl_list
, "",
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();
320 if (FD
.BitfieldSize
) {
321 Diag(AtLoc
, diag::err_objc_property_bitfield
)
322 << FD
.D
.getSourceRange();
326 // Install the property declarator into interfaceDecl.
327 IdentifierInfo
*SelName
=
328 OCDS
.getGetterName() ? OCDS
.getGetterName() : FD
.D
.getIdentifier();
331 PP
.getSelectorTable().getNullarySelector(SelName
);
332 IdentifierInfo
*SetterName
= OCDS
.getSetterName();
335 SetterSel
= PP
.getSelectorTable().getSelector(1, &SetterName
);
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
,
344 &isOverridingProperty
,
346 if (!isOverridingProperty
)
347 allProperties
.push_back(Property
);
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
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 ':'
384 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec
&DS
) {
385 assert(Tok
.getKind() == tok::l_paren
);
386 SourceLocation LHSLoc
= ConsumeParen(); // consume '('
389 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
391 // If this is not an identifier at all, bail out early.
393 MatchRHSPunctuation(tok::r_paren
, LHSLoc
);
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
, "",
417 if (Tok
.isNot(tok::identifier
)) {
418 Diag(Tok
, diag::err_expected_ident
);
419 SkipUntil(tok::r_paren
);
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
, "",
432 DS
.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter
);
433 DS
.setGetterName(Tok
.getIdentifierInfo());
434 ConsumeToken(); // consume method name
437 Diag(AttrName
, diag::err_objc_expected_property_attr
) << II
;
438 SkipUntil(tok::r_paren
);
442 if (Tok
.isNot(tok::comma
))
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 ';'.
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()) {
486 case tok::identifier
:
496 case tok::kw_const_cast
:
497 case tok::kw_continue
:
498 case tok::kw_default
:
502 case tok::kw_dynamic_cast
:
505 case tok::kw_explicit
:
517 case tok::kw_mutable
:
518 case tok::kw_namespace
:
520 case tok::kw_operator
:
521 case tok::kw_private
:
522 case tok::kw_protected
:
524 case tok::kw_register
:
525 case tok::kw_reinterpret_cast
:
526 case tok::kw_restrict
:
532 case tok::kw_static_cast
:
535 case tok::kw_template
:
540 case tok::kw_typedef
:
542 case tok::kw_typename
:
545 case tok::kw_unsigned
:
547 case tok::kw_virtual
:
549 case tok::kw_volatile
:
550 case tok::kw_wchar_t
:
553 case tok::kw__Complex
:
554 case tok::kw___alignof
:
555 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
556 SelectorLoc
= ConsumeToken();
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,
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
575 /// objc-type-qualifiers:
576 /// objc-type-qualifier
577 /// objc-type-qualifiers objc-type-qualifier
579 void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec
&DS
) {
581 if (Tok
.isNot(tok::identifier
))
584 const IdentifierInfo
*II
= Tok
.getIdentifierInfo();
585 for (unsigned i
= 0; i
!= objc_NumQuals
; ++i
) {
586 if (II
!= ObjCTypeQuals
[i
])
589 ObjCDeclSpec::ObjCDeclQualifier Qual
;
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
);
605 // If this wasn't a recognized qualifier, bail out.
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
);
624 if (isTypeSpecifierQualifier()) {
625 TypeResult TypeSpec
= ParseTypeName();
626 if (!TypeSpec
.isInvalid())
630 if (Tok
.is(tok::r_paren
))
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
);
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
);
644 /// objc-method-decl:
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
661 /// objc-parms objc-ellipsis[opt]
664 /// objc-parms , parameter-declaration
669 /// objc-keyword-attributes: [OBJC2]
670 /// __attribute__((unused))
672 Parser::DeclPtrTy
Parser::ParseObjCMethodDecl(SourceLocation mLoc
,
673 tok::TokenKind mType
,
675 tok::ObjCKeywordKind MethodImplKind
) {
676 // Parse the return type if present.
677 TypeTy
*ReturnType
= 0;
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
);
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
,
708 llvm::SmallVector
<IdentifierInfo
*, 12> KeyIdents
;
709 llvm::SmallVector
<Action::ObjCArgInfo
, 12> ArgInfos
;
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
);
719 ConsumeToken(); // Eat the ':'.
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.
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.
744 SelIdent
= ParseObjCSelectorPiece(Loc
);
745 if (!SelIdent
&& Tok
.isNot(tok::colon
))
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
)) {
755 if (Tok
.is(tok::ellipsis
)) {
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)
776 Selector Sel
= PP
.getSelectorTable().getSelector(KeyIdents
.size(),
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 '>'
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
;
797 if (Tok
.isNot(tok::identifier
)) {
798 Diag(Tok
, diag::err_expected_ident
);
799 SkipUntil(tok::greater
);
802 ProtocolIdents
.push_back(std::make_pair(Tok
.getIdentifierInfo(),
806 if (Tok
.isNot(tok::comma
))
812 if (Tok
.isNot(tok::greater
)) {
813 Diag(Tok
, diag::err_expected_greater
);
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(),
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 ';'
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:
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
);
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();
880 Diag(Tok
, diag::err_objc_illegal_visibility_spec
);
885 // Parse all the comma separated declarators.
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(),
897 FD
.D
, FD
.BitfieldSize
, visibility
);
898 AllIvarDecls
.push_back(Field
);
901 if (Tok
.is(tok::semi
)) {
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);
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
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.
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
);
951 return Actions
.ActOnForwardProtocolDeclaration(AtLoc
, &ProtoInfo
, 1,
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.
961 ConsumeToken(); // the ','
962 if (Tok
.isNot(tok::identifier
)) {
963 Diag(Tok
, diag::err_expected_ident
);
964 SkipUntil(tok::semi
);
967 ProtocolRefs
.push_back(IdentifierLocPair(Tok
.getIdentifierInfo(),
969 ConsumeToken(); // the identifier
971 if (Tok
.isNot(tok::comma
))
975 if (ExpectAndConsume(tok::semi
, diag::err_expected_semi_after
, "@protocol"))
978 return Actions
.ActOnForwardProtocolDeclaration(AtLoc
,
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
))
992 DeclPtrTy ProtoType
=
993 Actions
.ActOnStartProtocolInterface(AtLoc
, protocolName
, nameLoc
,
996 EndProtoLoc
, attrList
);
997 ParseObjCInterfaceDeclList(ProtoType
, tok::objc_protocol
);
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.
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();
1035 Diag(Tok
, diag::err_expected_ident
); // missing category name.
1038 if (Tok
.isNot(tok::r_paren
)) {
1039 Diag(Tok
, diag::err_expected_rparen
);
1040 SkipUntil(tok::r_paren
, false); // don't stop at ';'
1043 rparenLoc
= ConsumeParen();
1044 DeclPtrTy ImplCatType
= Actions
.ActOnStartCategoryImplementation(
1045 atLoc
, nameId
, nameLoc
, categoryId
,
1047 ObjCImpDecl
= ImplCatType
;
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
1056 if (Tok
.isNot(tok::identifier
)) {
1057 Diag(Tok
, diag::err_expected_ident
); // missing super class name.
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
;
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
1080 Actions
.ActOnAtEnd(atLoc
, ObjCImpDecl
);
1081 ObjCImpDecl
= DeclPtrTy();
1084 Diag(atLoc
, diag::warn_expected_implementation
); // missing @implementation
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
);
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
);
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";
1111 return Actions
.ActOnCompatiblityAlias(atLoc
, aliasId
, aliasLoc
,
1115 /// property-synthesis:
1116 /// @synthesize property-ivar-list ';'
1118 /// property-ivar-list:
1120 /// property-ivar-list ',' property-ivar
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
);
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
);
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
))
1153 ConsumeToken(); // consume ','
1155 if (Tok
.isNot(tok::semi
))
1156 Diag(Tok
, diag::err_expected_semi_after
) << "@synthesize";
1160 /// property-dynamic:
1161 /// @dynamic property-list
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
);
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
,
1181 if (Tok
.isNot(tok::comma
))
1183 ConsumeToken(); // consume ','
1185 if (Tok
.isNot(tok::semi
))
1186 Diag(Tok
, diag::err_expected_semi_after
) << "@dynamic";
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
);
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";
1217 ConsumeParen(); // '('
1218 OwningExprResult
Res(ParseExpression());
1219 if (Res
.isInvalid()) {
1220 SkipUntil(tok::semi
);
1223 if (Tok
.isNot(tok::r_paren
)) {
1224 Diag(Tok
, diag::err_expected_lbrace
);
1227 ConsumeParen(); // ')'
1228 if (Tok
.isNot(tok::l_brace
)) {
1229 Diag(Tok
, diag::err_expected_lbrace
);
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());
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
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
);
1263 OwningStmtResult
CatchStmts(Actions
);
1264 OwningStmtResult
FinallyStmt(Actions
);
1265 ParseScope
TryScope(this, Scope::DeclScope
);
1266 OwningStmtResult
TryBody(ParseCompoundStatementBody());
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
))
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
)) {
1286 ParseScope
CatchScope(this, Scope::DeclScope
|Scope::AtCatchScope
);
1287 if (Tok
.isNot(tok::ellipsis
)) {
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
);
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();
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
),
1320 Diag(AtCatchFinallyLoc
, diag::err_expected_lparen_after
)
1324 catch_or_finally_seen
= true;
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();
1334 Diag(Tok
, diag::err_expected_lbrace
);
1335 if (FinallyBody
.isInvalid())
1336 FinallyBody
= Actions
.ActOnNullStmt(Tok
.getLocation());
1337 FinallyStmt
= Actions
.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc
,
1339 catch_or_finally_seen
= true;
1343 if (!catch_or_finally_seen
) {
1344 Diag(atLoc
, diag::err_missing_catch_finally
);
1347 return Actions
.ActOnObjCAtTryStmt(atLoc
, move(TryBody
), move(CatchStmts
),
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
))
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
))
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.
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
);
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
));
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
));
1437 return ExprError(Diag(AtLoc
, diag::err_unexpected_at
));
1442 /// objc-message-expr:
1443 /// '[' objc-receiver objc-message-args ']'
1449 Parser::OwningExprResult
Parser::ParseObjCMessageExpression() {
1450 assert(Tok
.is(tok::l_square
) && "'[' expected");
1451 SourceLocation LBracLoc
= ConsumeBracket(); // consume '['
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
,
1463 OwningExprResult
Res(ParseExpression());
1464 if (Res
.isInvalid()) {
1465 SkipUntil(tok::r_square
);
1469 return ParseObjCMessageExpressionBody(LBracLoc
, SourceLocation(),
1473 /// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
1474 /// the rest of a message expression.
1476 /// objc-message-args:
1478 /// objc-keywordarg-list
1480 /// objc-keywordarg-list:
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
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
)) {
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
);
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
);
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
))
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
);
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
);
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
);
1577 SourceLocation RBracLoc
= ConsumeBracket(); // consume ']'
1579 unsigned nKeys
= KeyIdents
.size();
1581 KeyIdents
.push_back(selIdent
);
1582 Selector Sel
= PP
.getSelectorTable().getSelector(nKeys
, &KeyIdents
[0]);
1584 // We've just parsed a keyword message.
1586 return Owned(Actions
.ActOnClassMessage(CurScope
, ReceiverName
, Sel
,
1587 LBracLoc
, NameLoc
, SelectorLoc
,
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())
1618 AtStrings
.push_back(Lit
.release());
1621 return Owned(Actions
.ParseObjCStringLiteral(&AtLocs
[0], AtStrings
.take(),
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
);
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();
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
)) {
1692 if (Tok
.isNot(tok::colon
))
1693 return ExprError(Diag(Tok
, diag::err_expected_colon
));
1696 ConsumeToken(); // Eat the ':'.
1697 if (Tok
.is(tok::r_paren
))
1699 // Check for another keyword selector.
1701 SelIdent
= ParseObjCSelectorPiece(Loc
);
1702 KeyIdents
.push_back(SelIdent
);
1703 if (!SelIdent
&& Tok
.isNot(tok::colon
))
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
));