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