1*f4a2713aSLionel Sambuc //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This file implements the Objective-C portions of the Parser interface. 11*f4a2713aSLionel Sambuc // 12*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc #include "clang/Parse/Parser.h" 15*f4a2713aSLionel Sambuc #include "RAIIObjectsForParser.h" 16*f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h" 17*f4a2713aSLionel Sambuc #include "clang/Parse/ParseDiagnostic.h" 18*f4a2713aSLionel Sambuc #include "clang/Sema/DeclSpec.h" 19*f4a2713aSLionel Sambuc #include "clang/Sema/PrettyDeclStackTrace.h" 20*f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h" 21*f4a2713aSLionel Sambuc #include "llvm/ADT/SmallVector.h" 22*f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h" 23*f4a2713aSLionel Sambuc using namespace clang; 24*f4a2713aSLionel Sambuc 25*f4a2713aSLionel Sambuc /// Skips attributes after an Objective-C @ directive. Emits a diagnostic. 26*f4a2713aSLionel Sambuc void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { 27*f4a2713aSLionel Sambuc ParsedAttributes attrs(AttrFactory); 28*f4a2713aSLionel Sambuc if (Tok.is(tok::kw___attribute)) { 29*f4a2713aSLionel Sambuc if (Kind == tok::objc_interface || Kind == tok::objc_protocol) 30*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_postfix_attribute_hint) 31*f4a2713aSLionel Sambuc << (Kind == tok::objc_protocol); 32*f4a2713aSLionel Sambuc else 33*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_postfix_attribute); 34*f4a2713aSLionel Sambuc ParseGNUAttributes(attrs); 35*f4a2713aSLionel Sambuc } 36*f4a2713aSLionel Sambuc } 37*f4a2713aSLionel Sambuc 38*f4a2713aSLionel Sambuc /// ParseObjCAtDirectives - Handle parts of the external-declaration production: 39*f4a2713aSLionel Sambuc /// external-declaration: [C99 6.9] 40*f4a2713aSLionel Sambuc /// [OBJC] objc-class-definition 41*f4a2713aSLionel Sambuc /// [OBJC] objc-class-declaration 42*f4a2713aSLionel Sambuc /// [OBJC] objc-alias-declaration 43*f4a2713aSLionel Sambuc /// [OBJC] objc-protocol-definition 44*f4a2713aSLionel Sambuc /// [OBJC] objc-method-definition 45*f4a2713aSLionel Sambuc /// [OBJC] '@' 'end' 46*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { 47*f4a2713aSLionel Sambuc SourceLocation AtLoc = ConsumeToken(); // the "@" 48*f4a2713aSLionel Sambuc 49*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 50*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtDirective(getCurScope()); 51*f4a2713aSLionel Sambuc cutOffParsing(); 52*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 53*f4a2713aSLionel Sambuc } 54*f4a2713aSLionel Sambuc 55*f4a2713aSLionel Sambuc Decl *SingleDecl = 0; 56*f4a2713aSLionel Sambuc switch (Tok.getObjCKeywordID()) { 57*f4a2713aSLionel Sambuc case tok::objc_class: 58*f4a2713aSLionel Sambuc return ParseObjCAtClassDeclaration(AtLoc); 59*f4a2713aSLionel Sambuc case tok::objc_interface: { 60*f4a2713aSLionel Sambuc ParsedAttributes attrs(AttrFactory); 61*f4a2713aSLionel Sambuc SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs); 62*f4a2713aSLionel Sambuc break; 63*f4a2713aSLionel Sambuc } 64*f4a2713aSLionel Sambuc case tok::objc_protocol: { 65*f4a2713aSLionel Sambuc ParsedAttributes attrs(AttrFactory); 66*f4a2713aSLionel Sambuc return ParseObjCAtProtocolDeclaration(AtLoc, attrs); 67*f4a2713aSLionel Sambuc } 68*f4a2713aSLionel Sambuc case tok::objc_implementation: 69*f4a2713aSLionel Sambuc return ParseObjCAtImplementationDeclaration(AtLoc); 70*f4a2713aSLionel Sambuc case tok::objc_end: 71*f4a2713aSLionel Sambuc return ParseObjCAtEndDeclaration(AtLoc); 72*f4a2713aSLionel Sambuc case tok::objc_compatibility_alias: 73*f4a2713aSLionel Sambuc SingleDecl = ParseObjCAtAliasDeclaration(AtLoc); 74*f4a2713aSLionel Sambuc break; 75*f4a2713aSLionel Sambuc case tok::objc_synthesize: 76*f4a2713aSLionel Sambuc SingleDecl = ParseObjCPropertySynthesize(AtLoc); 77*f4a2713aSLionel Sambuc break; 78*f4a2713aSLionel Sambuc case tok::objc_dynamic: 79*f4a2713aSLionel Sambuc SingleDecl = ParseObjCPropertyDynamic(AtLoc); 80*f4a2713aSLionel Sambuc break; 81*f4a2713aSLionel Sambuc case tok::objc_import: 82*f4a2713aSLionel Sambuc if (getLangOpts().Modules) 83*f4a2713aSLionel Sambuc return ParseModuleImport(AtLoc); 84*f4a2713aSLionel Sambuc 85*f4a2713aSLionel Sambuc // Fall through 86*f4a2713aSLionel Sambuc 87*f4a2713aSLionel Sambuc default: 88*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_unexpected_at); 89*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 90*f4a2713aSLionel Sambuc SingleDecl = 0; 91*f4a2713aSLionel Sambuc break; 92*f4a2713aSLionel Sambuc } 93*f4a2713aSLionel Sambuc return Actions.ConvertDeclToDeclGroup(SingleDecl); 94*f4a2713aSLionel Sambuc } 95*f4a2713aSLionel Sambuc 96*f4a2713aSLionel Sambuc /// 97*f4a2713aSLionel Sambuc /// objc-class-declaration: 98*f4a2713aSLionel Sambuc /// '@' 'class' identifier-list ';' 99*f4a2713aSLionel Sambuc /// 100*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy 101*f4a2713aSLionel Sambuc Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { 102*f4a2713aSLionel Sambuc ConsumeToken(); // the identifier "class" 103*f4a2713aSLionel Sambuc SmallVector<IdentifierInfo *, 8> ClassNames; 104*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 8> ClassLocs; 105*f4a2713aSLionel Sambuc 106*f4a2713aSLionel Sambuc 107*f4a2713aSLionel Sambuc while (1) { 108*f4a2713aSLionel Sambuc MaybeSkipAttributes(tok::objc_class); 109*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 110*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 111*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 112*f4a2713aSLionel Sambuc return Actions.ConvertDeclToDeclGroup(0); 113*f4a2713aSLionel Sambuc } 114*f4a2713aSLionel Sambuc ClassNames.push_back(Tok.getIdentifierInfo()); 115*f4a2713aSLionel Sambuc ClassLocs.push_back(Tok.getLocation()); 116*f4a2713aSLionel Sambuc ConsumeToken(); 117*f4a2713aSLionel Sambuc 118*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 119*f4a2713aSLionel Sambuc break; 120*f4a2713aSLionel Sambuc 121*f4a2713aSLionel Sambuc ConsumeToken(); 122*f4a2713aSLionel Sambuc } 123*f4a2713aSLionel Sambuc 124*f4a2713aSLionel Sambuc // Consume the ';'. 125*f4a2713aSLionel Sambuc if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) 126*f4a2713aSLionel Sambuc return Actions.ConvertDeclToDeclGroup(0); 127*f4a2713aSLionel Sambuc 128*f4a2713aSLionel Sambuc return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), 129*f4a2713aSLionel Sambuc ClassLocs.data(), 130*f4a2713aSLionel Sambuc ClassNames.size()); 131*f4a2713aSLionel Sambuc } 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) 134*f4a2713aSLionel Sambuc { 135*f4a2713aSLionel Sambuc Sema::ObjCContainerKind ock = Actions.getObjCContainerKind(); 136*f4a2713aSLionel Sambuc if (ock == Sema::OCK_None) 137*f4a2713aSLionel Sambuc return; 138*f4a2713aSLionel Sambuc 139*f4a2713aSLionel Sambuc Decl *Decl = Actions.getObjCDeclContext(); 140*f4a2713aSLionel Sambuc if (CurParsedObjCImpl) { 141*f4a2713aSLionel Sambuc CurParsedObjCImpl->finish(AtLoc); 142*f4a2713aSLionel Sambuc } else { 143*f4a2713aSLionel Sambuc Actions.ActOnAtEnd(getCurScope(), AtLoc); 144*f4a2713aSLionel Sambuc } 145*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_objc_missing_end) 146*f4a2713aSLionel Sambuc << FixItHint::CreateInsertion(AtLoc, "@end\n"); 147*f4a2713aSLionel Sambuc if (Decl) 148*f4a2713aSLionel Sambuc Diag(Decl->getLocStart(), diag::note_objc_container_start) 149*f4a2713aSLionel Sambuc << (int) ock; 150*f4a2713aSLionel Sambuc } 151*f4a2713aSLionel Sambuc 152*f4a2713aSLionel Sambuc /// 153*f4a2713aSLionel Sambuc /// objc-interface: 154*f4a2713aSLionel Sambuc /// objc-class-interface-attributes[opt] objc-class-interface 155*f4a2713aSLionel Sambuc /// objc-category-interface 156*f4a2713aSLionel Sambuc /// 157*f4a2713aSLionel Sambuc /// objc-class-interface: 158*f4a2713aSLionel Sambuc /// '@' 'interface' identifier objc-superclass[opt] 159*f4a2713aSLionel Sambuc /// objc-protocol-refs[opt] 160*f4a2713aSLionel Sambuc /// objc-class-instance-variables[opt] 161*f4a2713aSLionel Sambuc /// objc-interface-decl-list 162*f4a2713aSLionel Sambuc /// @end 163*f4a2713aSLionel Sambuc /// 164*f4a2713aSLionel Sambuc /// objc-category-interface: 165*f4a2713aSLionel Sambuc /// '@' 'interface' identifier '(' identifier[opt] ')' 166*f4a2713aSLionel Sambuc /// objc-protocol-refs[opt] 167*f4a2713aSLionel Sambuc /// objc-interface-decl-list 168*f4a2713aSLionel Sambuc /// @end 169*f4a2713aSLionel Sambuc /// 170*f4a2713aSLionel Sambuc /// objc-superclass: 171*f4a2713aSLionel Sambuc /// ':' identifier 172*f4a2713aSLionel Sambuc /// 173*f4a2713aSLionel Sambuc /// objc-class-interface-attributes: 174*f4a2713aSLionel Sambuc /// __attribute__((visibility("default"))) 175*f4a2713aSLionel Sambuc /// __attribute__((visibility("hidden"))) 176*f4a2713aSLionel Sambuc /// __attribute__((deprecated)) 177*f4a2713aSLionel Sambuc /// __attribute__((unavailable)) 178*f4a2713aSLionel Sambuc /// __attribute__((objc_exception)) - used by NSException on 64-bit 179*f4a2713aSLionel Sambuc /// __attribute__((objc_root_class)) 180*f4a2713aSLionel Sambuc /// 181*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, 182*f4a2713aSLionel Sambuc ParsedAttributes &attrs) { 183*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_interface) && 184*f4a2713aSLionel Sambuc "ParseObjCAtInterfaceDeclaration(): Expected @interface"); 185*f4a2713aSLionel Sambuc CheckNestedObjCContexts(AtLoc); 186*f4a2713aSLionel Sambuc ConsumeToken(); // the "interface" identifier 187*f4a2713aSLionel Sambuc 188*f4a2713aSLionel Sambuc // Code completion after '@interface'. 189*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 190*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); 191*f4a2713aSLionel Sambuc cutOffParsing(); 192*f4a2713aSLionel Sambuc return 0; 193*f4a2713aSLionel Sambuc } 194*f4a2713aSLionel Sambuc 195*f4a2713aSLionel Sambuc MaybeSkipAttributes(tok::objc_interface); 196*f4a2713aSLionel Sambuc 197*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 198*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing class or category name. 199*f4a2713aSLionel Sambuc return 0; 200*f4a2713aSLionel Sambuc } 201*f4a2713aSLionel Sambuc 202*f4a2713aSLionel Sambuc // We have a class or category name - consume it. 203*f4a2713aSLionel Sambuc IdentifierInfo *nameId = Tok.getIdentifierInfo(); 204*f4a2713aSLionel Sambuc SourceLocation nameLoc = ConsumeToken(); 205*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren) && 206*f4a2713aSLionel Sambuc !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. 207*f4a2713aSLionel Sambuc 208*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 209*f4a2713aSLionel Sambuc T.consumeOpen(); 210*f4a2713aSLionel Sambuc 211*f4a2713aSLionel Sambuc SourceLocation categoryLoc; 212*f4a2713aSLionel Sambuc IdentifierInfo *categoryId = 0; 213*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 214*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); 215*f4a2713aSLionel Sambuc cutOffParsing(); 216*f4a2713aSLionel Sambuc return 0; 217*f4a2713aSLionel Sambuc } 218*f4a2713aSLionel Sambuc 219*f4a2713aSLionel Sambuc // For ObjC2, the category name is optional (not an error). 220*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier)) { 221*f4a2713aSLionel Sambuc categoryId = Tok.getIdentifierInfo(); 222*f4a2713aSLionel Sambuc categoryLoc = ConsumeToken(); 223*f4a2713aSLionel Sambuc } 224*f4a2713aSLionel Sambuc else if (!getLangOpts().ObjC2) { 225*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing category name. 226*f4a2713aSLionel Sambuc return 0; 227*f4a2713aSLionel Sambuc } 228*f4a2713aSLionel Sambuc 229*f4a2713aSLionel Sambuc T.consumeClose(); 230*f4a2713aSLionel Sambuc if (T.getCloseLocation().isInvalid()) 231*f4a2713aSLionel Sambuc return 0; 232*f4a2713aSLionel Sambuc 233*f4a2713aSLionel Sambuc if (!attrs.empty()) { // categories don't support attributes. 234*f4a2713aSLionel Sambuc Diag(nameLoc, diag::err_objc_no_attributes_on_category); 235*f4a2713aSLionel Sambuc attrs.clear(); 236*f4a2713aSLionel Sambuc } 237*f4a2713aSLionel Sambuc 238*f4a2713aSLionel Sambuc // Next, we need to check for any protocol references. 239*f4a2713aSLionel Sambuc SourceLocation LAngleLoc, EndProtoLoc; 240*f4a2713aSLionel Sambuc SmallVector<Decl *, 8> ProtocolRefs; 241*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 8> ProtocolLocs; 242*f4a2713aSLionel Sambuc if (Tok.is(tok::less) && 243*f4a2713aSLionel Sambuc ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, 244*f4a2713aSLionel Sambuc LAngleLoc, EndProtoLoc)) 245*f4a2713aSLionel Sambuc return 0; 246*f4a2713aSLionel Sambuc 247*f4a2713aSLionel Sambuc Decl *CategoryType = 248*f4a2713aSLionel Sambuc Actions.ActOnStartCategoryInterface(AtLoc, 249*f4a2713aSLionel Sambuc nameId, nameLoc, 250*f4a2713aSLionel Sambuc categoryId, categoryLoc, 251*f4a2713aSLionel Sambuc ProtocolRefs.data(), 252*f4a2713aSLionel Sambuc ProtocolRefs.size(), 253*f4a2713aSLionel Sambuc ProtocolLocs.data(), 254*f4a2713aSLionel Sambuc EndProtoLoc); 255*f4a2713aSLionel Sambuc 256*f4a2713aSLionel Sambuc if (Tok.is(tok::l_brace)) 257*f4a2713aSLionel Sambuc ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); 258*f4a2713aSLionel Sambuc 259*f4a2713aSLionel Sambuc ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); 260*f4a2713aSLionel Sambuc return CategoryType; 261*f4a2713aSLionel Sambuc } 262*f4a2713aSLionel Sambuc // Parse a class interface. 263*f4a2713aSLionel Sambuc IdentifierInfo *superClassId = 0; 264*f4a2713aSLionel Sambuc SourceLocation superClassLoc; 265*f4a2713aSLionel Sambuc 266*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { // a super class is specified. 267*f4a2713aSLionel Sambuc ConsumeToken(); 268*f4a2713aSLionel Sambuc 269*f4a2713aSLionel Sambuc // Code completion of superclass names. 270*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 271*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); 272*f4a2713aSLionel Sambuc cutOffParsing(); 273*f4a2713aSLionel Sambuc return 0; 274*f4a2713aSLionel Sambuc } 275*f4a2713aSLionel Sambuc 276*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 277*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing super class name. 278*f4a2713aSLionel Sambuc return 0; 279*f4a2713aSLionel Sambuc } 280*f4a2713aSLionel Sambuc superClassId = Tok.getIdentifierInfo(); 281*f4a2713aSLionel Sambuc superClassLoc = ConsumeToken(); 282*f4a2713aSLionel Sambuc } 283*f4a2713aSLionel Sambuc // Next, we need to check for any protocol references. 284*f4a2713aSLionel Sambuc SmallVector<Decl *, 8> ProtocolRefs; 285*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 8> ProtocolLocs; 286*f4a2713aSLionel Sambuc SourceLocation LAngleLoc, EndProtoLoc; 287*f4a2713aSLionel Sambuc if (Tok.is(tok::less) && 288*f4a2713aSLionel Sambuc ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, 289*f4a2713aSLionel Sambuc LAngleLoc, EndProtoLoc)) 290*f4a2713aSLionel Sambuc return 0; 291*f4a2713aSLionel Sambuc 292*f4a2713aSLionel Sambuc if (Tok.isNot(tok::less)) 293*f4a2713aSLionel Sambuc Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc); 294*f4a2713aSLionel Sambuc 295*f4a2713aSLionel Sambuc Decl *ClsType = 296*f4a2713aSLionel Sambuc Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc, 297*f4a2713aSLionel Sambuc superClassId, superClassLoc, 298*f4a2713aSLionel Sambuc ProtocolRefs.data(), ProtocolRefs.size(), 299*f4a2713aSLionel Sambuc ProtocolLocs.data(), 300*f4a2713aSLionel Sambuc EndProtoLoc, attrs.getList()); 301*f4a2713aSLionel Sambuc 302*f4a2713aSLionel Sambuc if (Tok.is(tok::l_brace)) 303*f4a2713aSLionel Sambuc ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); 304*f4a2713aSLionel Sambuc 305*f4a2713aSLionel Sambuc ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); 306*f4a2713aSLionel Sambuc return ClsType; 307*f4a2713aSLionel Sambuc } 308*f4a2713aSLionel Sambuc 309*f4a2713aSLionel Sambuc /// The Objective-C property callback. This should be defined where 310*f4a2713aSLionel Sambuc /// it's used, but instead it's been lifted to here to support VS2005. 311*f4a2713aSLionel Sambuc struct Parser::ObjCPropertyCallback : FieldCallback { 312*f4a2713aSLionel Sambuc private: 313*f4a2713aSLionel Sambuc virtual void anchor(); 314*f4a2713aSLionel Sambuc public: 315*f4a2713aSLionel Sambuc Parser &P; 316*f4a2713aSLionel Sambuc SmallVectorImpl<Decl *> &Props; 317*f4a2713aSLionel Sambuc ObjCDeclSpec &OCDS; 318*f4a2713aSLionel Sambuc SourceLocation AtLoc; 319*f4a2713aSLionel Sambuc SourceLocation LParenLoc; 320*f4a2713aSLionel Sambuc tok::ObjCKeywordKind MethodImplKind; 321*f4a2713aSLionel Sambuc 322*f4a2713aSLionel Sambuc ObjCPropertyCallback(Parser &P, 323*f4a2713aSLionel Sambuc SmallVectorImpl<Decl *> &Props, 324*f4a2713aSLionel Sambuc ObjCDeclSpec &OCDS, SourceLocation AtLoc, 325*f4a2713aSLionel Sambuc SourceLocation LParenLoc, 326*f4a2713aSLionel Sambuc tok::ObjCKeywordKind MethodImplKind) : 327*f4a2713aSLionel Sambuc P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc), LParenLoc(LParenLoc), 328*f4a2713aSLionel Sambuc MethodImplKind(MethodImplKind) { 329*f4a2713aSLionel Sambuc } 330*f4a2713aSLionel Sambuc 331*f4a2713aSLionel Sambuc void invoke(ParsingFieldDeclarator &FD) { 332*f4a2713aSLionel Sambuc if (FD.D.getIdentifier() == 0) { 333*f4a2713aSLionel Sambuc P.Diag(AtLoc, diag::err_objc_property_requires_field_name) 334*f4a2713aSLionel Sambuc << FD.D.getSourceRange(); 335*f4a2713aSLionel Sambuc return; 336*f4a2713aSLionel Sambuc } 337*f4a2713aSLionel Sambuc if (FD.BitfieldSize) { 338*f4a2713aSLionel Sambuc P.Diag(AtLoc, diag::err_objc_property_bitfield) 339*f4a2713aSLionel Sambuc << FD.D.getSourceRange(); 340*f4a2713aSLionel Sambuc return; 341*f4a2713aSLionel Sambuc } 342*f4a2713aSLionel Sambuc 343*f4a2713aSLionel Sambuc // Install the property declarator into interfaceDecl. 344*f4a2713aSLionel Sambuc IdentifierInfo *SelName = 345*f4a2713aSLionel Sambuc OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); 346*f4a2713aSLionel Sambuc 347*f4a2713aSLionel Sambuc Selector GetterSel = 348*f4a2713aSLionel Sambuc P.PP.getSelectorTable().getNullarySelector(SelName); 349*f4a2713aSLionel Sambuc IdentifierInfo *SetterName = OCDS.getSetterName(); 350*f4a2713aSLionel Sambuc Selector SetterSel; 351*f4a2713aSLionel Sambuc if (SetterName) 352*f4a2713aSLionel Sambuc SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName); 353*f4a2713aSLionel Sambuc else 354*f4a2713aSLionel Sambuc SetterSel = 355*f4a2713aSLionel Sambuc SelectorTable::constructSetterSelector(P.PP.getIdentifierTable(), 356*f4a2713aSLionel Sambuc P.PP.getSelectorTable(), 357*f4a2713aSLionel Sambuc FD.D.getIdentifier()); 358*f4a2713aSLionel Sambuc bool isOverridingProperty = false; 359*f4a2713aSLionel Sambuc Decl *Property = 360*f4a2713aSLionel Sambuc P.Actions.ActOnProperty(P.getCurScope(), AtLoc, LParenLoc, 361*f4a2713aSLionel Sambuc FD, OCDS, 362*f4a2713aSLionel Sambuc GetterSel, SetterSel, 363*f4a2713aSLionel Sambuc &isOverridingProperty, 364*f4a2713aSLionel Sambuc MethodImplKind); 365*f4a2713aSLionel Sambuc if (!isOverridingProperty) 366*f4a2713aSLionel Sambuc Props.push_back(Property); 367*f4a2713aSLionel Sambuc 368*f4a2713aSLionel Sambuc FD.complete(Property); 369*f4a2713aSLionel Sambuc } 370*f4a2713aSLionel Sambuc }; 371*f4a2713aSLionel Sambuc 372*f4a2713aSLionel Sambuc void Parser::ObjCPropertyCallback::anchor() { 373*f4a2713aSLionel Sambuc } 374*f4a2713aSLionel Sambuc 375*f4a2713aSLionel Sambuc /// objc-interface-decl-list: 376*f4a2713aSLionel Sambuc /// empty 377*f4a2713aSLionel Sambuc /// objc-interface-decl-list objc-property-decl [OBJC2] 378*f4a2713aSLionel Sambuc /// objc-interface-decl-list objc-method-requirement [OBJC2] 379*f4a2713aSLionel Sambuc /// objc-interface-decl-list objc-method-proto ';' 380*f4a2713aSLionel Sambuc /// objc-interface-decl-list declaration 381*f4a2713aSLionel Sambuc /// objc-interface-decl-list ';' 382*f4a2713aSLionel Sambuc /// 383*f4a2713aSLionel Sambuc /// objc-method-requirement: [OBJC2] 384*f4a2713aSLionel Sambuc /// @required 385*f4a2713aSLionel Sambuc /// @optional 386*f4a2713aSLionel Sambuc /// 387*f4a2713aSLionel Sambuc void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, 388*f4a2713aSLionel Sambuc Decl *CDecl) { 389*f4a2713aSLionel Sambuc SmallVector<Decl *, 32> allMethods; 390*f4a2713aSLionel Sambuc SmallVector<Decl *, 16> allProperties; 391*f4a2713aSLionel Sambuc SmallVector<DeclGroupPtrTy, 8> allTUVariables; 392*f4a2713aSLionel Sambuc tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; 393*f4a2713aSLionel Sambuc 394*f4a2713aSLionel Sambuc SourceRange AtEnd; 395*f4a2713aSLionel Sambuc 396*f4a2713aSLionel Sambuc while (1) { 397*f4a2713aSLionel Sambuc // If this is a method prototype, parse it. 398*f4a2713aSLionel Sambuc if (Tok.is(tok::minus) || Tok.is(tok::plus)) { 399*f4a2713aSLionel Sambuc if (Decl *methodPrototype = 400*f4a2713aSLionel Sambuc ParseObjCMethodPrototype(MethodImplKind, false)) 401*f4a2713aSLionel Sambuc allMethods.push_back(methodPrototype); 402*f4a2713aSLionel Sambuc // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for 403*f4a2713aSLionel Sambuc // method definitions. 404*f4a2713aSLionel Sambuc if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) { 405*f4a2713aSLionel Sambuc // We didn't find a semi and we error'ed out. Skip until a ';' or '@'. 406*f4a2713aSLionel Sambuc SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); 407*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) 408*f4a2713aSLionel Sambuc ConsumeToken(); 409*f4a2713aSLionel Sambuc } 410*f4a2713aSLionel Sambuc continue; 411*f4a2713aSLionel Sambuc } 412*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) { 413*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_minus_or_plus); 414*f4a2713aSLionel Sambuc ParseObjCMethodDecl(Tok.getLocation(), 415*f4a2713aSLionel Sambuc tok::minus, 416*f4a2713aSLionel Sambuc MethodImplKind, false); 417*f4a2713aSLionel Sambuc continue; 418*f4a2713aSLionel Sambuc } 419*f4a2713aSLionel Sambuc // Ignore excess semicolons. 420*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) { 421*f4a2713aSLionel Sambuc ConsumeToken(); 422*f4a2713aSLionel Sambuc continue; 423*f4a2713aSLionel Sambuc } 424*f4a2713aSLionel Sambuc 425*f4a2713aSLionel Sambuc // If we got to the end of the file, exit the loop. 426*f4a2713aSLionel Sambuc if (Tok.is(tok::eof)) 427*f4a2713aSLionel Sambuc break; 428*f4a2713aSLionel Sambuc 429*f4a2713aSLionel Sambuc // Code completion within an Objective-C interface. 430*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 431*f4a2713aSLionel Sambuc Actions.CodeCompleteOrdinaryName(getCurScope(), 432*f4a2713aSLionel Sambuc CurParsedObjCImpl? Sema::PCC_ObjCImplementation 433*f4a2713aSLionel Sambuc : Sema::PCC_ObjCInterface); 434*f4a2713aSLionel Sambuc return cutOffParsing(); 435*f4a2713aSLionel Sambuc } 436*f4a2713aSLionel Sambuc 437*f4a2713aSLionel Sambuc // If we don't have an @ directive, parse it as a function definition. 438*f4a2713aSLionel Sambuc if (Tok.isNot(tok::at)) { 439*f4a2713aSLionel Sambuc // The code below does not consume '}'s because it is afraid of eating the 440*f4a2713aSLionel Sambuc // end of a namespace. Because of the way this code is structured, an 441*f4a2713aSLionel Sambuc // erroneous r_brace would cause an infinite loop if not handled here. 442*f4a2713aSLionel Sambuc if (Tok.is(tok::r_brace)) 443*f4a2713aSLionel Sambuc break; 444*f4a2713aSLionel Sambuc ParsedAttributesWithRange attrs(AttrFactory); 445*f4a2713aSLionel Sambuc allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); 446*f4a2713aSLionel Sambuc continue; 447*f4a2713aSLionel Sambuc } 448*f4a2713aSLionel Sambuc 449*f4a2713aSLionel Sambuc // Otherwise, we have an @ directive, eat the @. 450*f4a2713aSLionel Sambuc SourceLocation AtLoc = ConsumeToken(); // the "@" 451*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 452*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtDirective(getCurScope()); 453*f4a2713aSLionel Sambuc return cutOffParsing(); 454*f4a2713aSLionel Sambuc } 455*f4a2713aSLionel Sambuc 456*f4a2713aSLionel Sambuc tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); 457*f4a2713aSLionel Sambuc 458*f4a2713aSLionel Sambuc if (DirectiveKind == tok::objc_end) { // @end -> terminate list 459*f4a2713aSLionel Sambuc AtEnd.setBegin(AtLoc); 460*f4a2713aSLionel Sambuc AtEnd.setEnd(Tok.getLocation()); 461*f4a2713aSLionel Sambuc break; 462*f4a2713aSLionel Sambuc } else if (DirectiveKind == tok::objc_not_keyword) { 463*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_unknown_at); 464*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 465*f4a2713aSLionel Sambuc continue; 466*f4a2713aSLionel Sambuc } 467*f4a2713aSLionel Sambuc 468*f4a2713aSLionel Sambuc // Eat the identifier. 469*f4a2713aSLionel Sambuc ConsumeToken(); 470*f4a2713aSLionel Sambuc 471*f4a2713aSLionel Sambuc switch (DirectiveKind) { 472*f4a2713aSLionel Sambuc default: 473*f4a2713aSLionel Sambuc // FIXME: If someone forgets an @end on a protocol, this loop will 474*f4a2713aSLionel Sambuc // continue to eat up tons of stuff and spew lots of nonsense errors. It 475*f4a2713aSLionel Sambuc // would probably be better to bail out if we saw an @class or @interface 476*f4a2713aSLionel Sambuc // or something like that. 477*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_objc_illegal_interface_qual); 478*f4a2713aSLionel Sambuc // Skip until we see an '@' or '}' or ';'. 479*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace, tok::at, StopAtSemi); 480*f4a2713aSLionel Sambuc break; 481*f4a2713aSLionel Sambuc 482*f4a2713aSLionel Sambuc case tok::objc_implementation: 483*f4a2713aSLionel Sambuc case tok::objc_interface: 484*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_objc_missing_end) 485*f4a2713aSLionel Sambuc << FixItHint::CreateInsertion(AtLoc, "@end\n"); 486*f4a2713aSLionel Sambuc Diag(CDecl->getLocStart(), diag::note_objc_container_start) 487*f4a2713aSLionel Sambuc << (int) Actions.getObjCContainerKind(); 488*f4a2713aSLionel Sambuc ConsumeToken(); 489*f4a2713aSLionel Sambuc break; 490*f4a2713aSLionel Sambuc 491*f4a2713aSLionel Sambuc case tok::objc_required: 492*f4a2713aSLionel Sambuc case tok::objc_optional: 493*f4a2713aSLionel Sambuc // This is only valid on protocols. 494*f4a2713aSLionel Sambuc // FIXME: Should this check for ObjC2 being enabled? 495*f4a2713aSLionel Sambuc if (contextKey != tok::objc_protocol) 496*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_objc_directive_only_in_protocol); 497*f4a2713aSLionel Sambuc else 498*f4a2713aSLionel Sambuc MethodImplKind = DirectiveKind; 499*f4a2713aSLionel Sambuc break; 500*f4a2713aSLionel Sambuc 501*f4a2713aSLionel Sambuc case tok::objc_property: 502*f4a2713aSLionel Sambuc if (!getLangOpts().ObjC2) 503*f4a2713aSLionel Sambuc Diag(AtLoc, diag::err_objc_properties_require_objc2); 504*f4a2713aSLionel Sambuc 505*f4a2713aSLionel Sambuc ObjCDeclSpec OCDS; 506*f4a2713aSLionel Sambuc SourceLocation LParenLoc; 507*f4a2713aSLionel Sambuc // Parse property attribute list, if any. 508*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) { 509*f4a2713aSLionel Sambuc LParenLoc = Tok.getLocation(); 510*f4a2713aSLionel Sambuc ParseObjCPropertyAttribute(OCDS); 511*f4a2713aSLionel Sambuc } 512*f4a2713aSLionel Sambuc 513*f4a2713aSLionel Sambuc ObjCPropertyCallback Callback(*this, allProperties, 514*f4a2713aSLionel Sambuc OCDS, AtLoc, LParenLoc, MethodImplKind); 515*f4a2713aSLionel Sambuc 516*f4a2713aSLionel Sambuc // Parse all the comma separated declarators. 517*f4a2713aSLionel Sambuc ParsingDeclSpec DS(*this); 518*f4a2713aSLionel Sambuc ParseStructDeclaration(DS, Callback); 519*f4a2713aSLionel Sambuc 520*f4a2713aSLionel Sambuc ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); 521*f4a2713aSLionel Sambuc break; 522*f4a2713aSLionel Sambuc } 523*f4a2713aSLionel Sambuc } 524*f4a2713aSLionel Sambuc 525*f4a2713aSLionel Sambuc // We break out of the big loop in two cases: when we see @end or when we see 526*f4a2713aSLionel Sambuc // EOF. In the former case, eat the @end. In the later case, emit an error. 527*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 528*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtDirective(getCurScope()); 529*f4a2713aSLionel Sambuc return cutOffParsing(); 530*f4a2713aSLionel Sambuc } else if (Tok.isObjCAtKeyword(tok::objc_end)) { 531*f4a2713aSLionel Sambuc ConsumeToken(); // the "end" identifier 532*f4a2713aSLionel Sambuc } else { 533*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_missing_end) 534*f4a2713aSLionel Sambuc << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n"); 535*f4a2713aSLionel Sambuc Diag(CDecl->getLocStart(), diag::note_objc_container_start) 536*f4a2713aSLionel Sambuc << (int) Actions.getObjCContainerKind(); 537*f4a2713aSLionel Sambuc AtEnd.setBegin(Tok.getLocation()); 538*f4a2713aSLionel Sambuc AtEnd.setEnd(Tok.getLocation()); 539*f4a2713aSLionel Sambuc } 540*f4a2713aSLionel Sambuc 541*f4a2713aSLionel Sambuc // Insert collected methods declarations into the @interface object. 542*f4a2713aSLionel Sambuc // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. 543*f4a2713aSLionel Sambuc Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); 544*f4a2713aSLionel Sambuc } 545*f4a2713aSLionel Sambuc 546*f4a2713aSLionel Sambuc /// Parse property attribute declarations. 547*f4a2713aSLionel Sambuc /// 548*f4a2713aSLionel Sambuc /// property-attr-decl: '(' property-attrlist ')' 549*f4a2713aSLionel Sambuc /// property-attrlist: 550*f4a2713aSLionel Sambuc /// property-attribute 551*f4a2713aSLionel Sambuc /// property-attrlist ',' property-attribute 552*f4a2713aSLionel Sambuc /// property-attribute: 553*f4a2713aSLionel Sambuc /// getter '=' identifier 554*f4a2713aSLionel Sambuc /// setter '=' identifier ':' 555*f4a2713aSLionel Sambuc /// readonly 556*f4a2713aSLionel Sambuc /// readwrite 557*f4a2713aSLionel Sambuc /// assign 558*f4a2713aSLionel Sambuc /// retain 559*f4a2713aSLionel Sambuc /// copy 560*f4a2713aSLionel Sambuc /// nonatomic 561*f4a2713aSLionel Sambuc /// atomic 562*f4a2713aSLionel Sambuc /// strong 563*f4a2713aSLionel Sambuc /// weak 564*f4a2713aSLionel Sambuc /// unsafe_unretained 565*f4a2713aSLionel Sambuc /// 566*f4a2713aSLionel Sambuc void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { 567*f4a2713aSLionel Sambuc assert(Tok.getKind() == tok::l_paren); 568*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 569*f4a2713aSLionel Sambuc T.consumeOpen(); 570*f4a2713aSLionel Sambuc 571*f4a2713aSLionel Sambuc while (1) { 572*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 573*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS); 574*f4a2713aSLionel Sambuc return cutOffParsing(); 575*f4a2713aSLionel Sambuc } 576*f4a2713aSLionel Sambuc const IdentifierInfo *II = Tok.getIdentifierInfo(); 577*f4a2713aSLionel Sambuc 578*f4a2713aSLionel Sambuc // If this is not an identifier at all, bail out early. 579*f4a2713aSLionel Sambuc if (II == 0) { 580*f4a2713aSLionel Sambuc T.consumeClose(); 581*f4a2713aSLionel Sambuc return; 582*f4a2713aSLionel Sambuc } 583*f4a2713aSLionel Sambuc 584*f4a2713aSLionel Sambuc SourceLocation AttrName = ConsumeToken(); // consume last attribute name 585*f4a2713aSLionel Sambuc 586*f4a2713aSLionel Sambuc if (II->isStr("readonly")) 587*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly); 588*f4a2713aSLionel Sambuc else if (II->isStr("assign")) 589*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign); 590*f4a2713aSLionel Sambuc else if (II->isStr("unsafe_unretained")) 591*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained); 592*f4a2713aSLionel Sambuc else if (II->isStr("readwrite")) 593*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite); 594*f4a2713aSLionel Sambuc else if (II->isStr("retain")) 595*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain); 596*f4a2713aSLionel Sambuc else if (II->isStr("strong")) 597*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong); 598*f4a2713aSLionel Sambuc else if (II->isStr("copy")) 599*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy); 600*f4a2713aSLionel Sambuc else if (II->isStr("nonatomic")) 601*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic); 602*f4a2713aSLionel Sambuc else if (II->isStr("atomic")) 603*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic); 604*f4a2713aSLionel Sambuc else if (II->isStr("weak")) 605*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak); 606*f4a2713aSLionel Sambuc else if (II->isStr("getter") || II->isStr("setter")) { 607*f4a2713aSLionel Sambuc bool IsSetter = II->getNameStart()[0] == 's'; 608*f4a2713aSLionel Sambuc 609*f4a2713aSLionel Sambuc // getter/setter require extra treatment. 610*f4a2713aSLionel Sambuc unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter : 611*f4a2713aSLionel Sambuc diag::err_objc_expected_equal_for_getter; 612*f4a2713aSLionel Sambuc 613*f4a2713aSLionel Sambuc if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren)) 614*f4a2713aSLionel Sambuc return; 615*f4a2713aSLionel Sambuc 616*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 617*f4a2713aSLionel Sambuc if (IsSetter) 618*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertySetter(getCurScope()); 619*f4a2713aSLionel Sambuc else 620*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertyGetter(getCurScope()); 621*f4a2713aSLionel Sambuc return cutOffParsing(); 622*f4a2713aSLionel Sambuc } 623*f4a2713aSLionel Sambuc 624*f4a2713aSLionel Sambuc 625*f4a2713aSLionel Sambuc SourceLocation SelLoc; 626*f4a2713aSLionel Sambuc IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc); 627*f4a2713aSLionel Sambuc 628*f4a2713aSLionel Sambuc if (!SelIdent) { 629*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_expected_selector_for_getter_setter) 630*f4a2713aSLionel Sambuc << IsSetter; 631*f4a2713aSLionel Sambuc SkipUntil(tok::r_paren, StopAtSemi); 632*f4a2713aSLionel Sambuc return; 633*f4a2713aSLionel Sambuc } 634*f4a2713aSLionel Sambuc 635*f4a2713aSLionel Sambuc if (IsSetter) { 636*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); 637*f4a2713aSLionel Sambuc DS.setSetterName(SelIdent); 638*f4a2713aSLionel Sambuc 639*f4a2713aSLionel Sambuc if (ExpectAndConsume(tok::colon, 640*f4a2713aSLionel Sambuc diag::err_expected_colon_after_setter_name, "", 641*f4a2713aSLionel Sambuc tok::r_paren)) 642*f4a2713aSLionel Sambuc return; 643*f4a2713aSLionel Sambuc } else { 644*f4a2713aSLionel Sambuc DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); 645*f4a2713aSLionel Sambuc DS.setGetterName(SelIdent); 646*f4a2713aSLionel Sambuc } 647*f4a2713aSLionel Sambuc } else { 648*f4a2713aSLionel Sambuc Diag(AttrName, diag::err_objc_expected_property_attr) << II; 649*f4a2713aSLionel Sambuc SkipUntil(tok::r_paren, StopAtSemi); 650*f4a2713aSLionel Sambuc return; 651*f4a2713aSLionel Sambuc } 652*f4a2713aSLionel Sambuc 653*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 654*f4a2713aSLionel Sambuc break; 655*f4a2713aSLionel Sambuc 656*f4a2713aSLionel Sambuc ConsumeToken(); 657*f4a2713aSLionel Sambuc } 658*f4a2713aSLionel Sambuc 659*f4a2713aSLionel Sambuc T.consumeClose(); 660*f4a2713aSLionel Sambuc } 661*f4a2713aSLionel Sambuc 662*f4a2713aSLionel Sambuc /// objc-method-proto: 663*f4a2713aSLionel Sambuc /// objc-instance-method objc-method-decl objc-method-attributes[opt] 664*f4a2713aSLionel Sambuc /// objc-class-method objc-method-decl objc-method-attributes[opt] 665*f4a2713aSLionel Sambuc /// 666*f4a2713aSLionel Sambuc /// objc-instance-method: '-' 667*f4a2713aSLionel Sambuc /// objc-class-method: '+' 668*f4a2713aSLionel Sambuc /// 669*f4a2713aSLionel Sambuc /// objc-method-attributes: [OBJC2] 670*f4a2713aSLionel Sambuc /// __attribute__((deprecated)) 671*f4a2713aSLionel Sambuc /// 672*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, 673*f4a2713aSLionel Sambuc bool MethodDefinition) { 674*f4a2713aSLionel Sambuc assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); 675*f4a2713aSLionel Sambuc 676*f4a2713aSLionel Sambuc tok::TokenKind methodType = Tok.getKind(); 677*f4a2713aSLionel Sambuc SourceLocation mLoc = ConsumeToken(); 678*f4a2713aSLionel Sambuc Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind, 679*f4a2713aSLionel Sambuc MethodDefinition); 680*f4a2713aSLionel Sambuc // Since this rule is used for both method declarations and definitions, 681*f4a2713aSLionel Sambuc // the caller is (optionally) responsible for consuming the ';'. 682*f4a2713aSLionel Sambuc return MDecl; 683*f4a2713aSLionel Sambuc } 684*f4a2713aSLionel Sambuc 685*f4a2713aSLionel Sambuc /// objc-selector: 686*f4a2713aSLionel Sambuc /// identifier 687*f4a2713aSLionel Sambuc /// one of 688*f4a2713aSLionel Sambuc /// enum struct union if else while do for switch case default 689*f4a2713aSLionel Sambuc /// break continue return goto asm sizeof typeof __alignof 690*f4a2713aSLionel Sambuc /// unsigned long const short volatile signed restrict _Complex 691*f4a2713aSLionel Sambuc /// in out inout bycopy byref oneway int char float double void _Bool 692*f4a2713aSLionel Sambuc /// 693*f4a2713aSLionel Sambuc IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { 694*f4a2713aSLionel Sambuc 695*f4a2713aSLionel Sambuc switch (Tok.getKind()) { 696*f4a2713aSLionel Sambuc default: 697*f4a2713aSLionel Sambuc return 0; 698*f4a2713aSLionel Sambuc case tok::ampamp: 699*f4a2713aSLionel Sambuc case tok::ampequal: 700*f4a2713aSLionel Sambuc case tok::amp: 701*f4a2713aSLionel Sambuc case tok::pipe: 702*f4a2713aSLionel Sambuc case tok::tilde: 703*f4a2713aSLionel Sambuc case tok::exclaim: 704*f4a2713aSLionel Sambuc case tok::exclaimequal: 705*f4a2713aSLionel Sambuc case tok::pipepipe: 706*f4a2713aSLionel Sambuc case tok::pipeequal: 707*f4a2713aSLionel Sambuc case tok::caret: 708*f4a2713aSLionel Sambuc case tok::caretequal: { 709*f4a2713aSLionel Sambuc std::string ThisTok(PP.getSpelling(Tok)); 710*f4a2713aSLionel Sambuc if (isLetter(ThisTok[0])) { 711*f4a2713aSLionel Sambuc IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data()); 712*f4a2713aSLionel Sambuc Tok.setKind(tok::identifier); 713*f4a2713aSLionel Sambuc SelectorLoc = ConsumeToken(); 714*f4a2713aSLionel Sambuc return II; 715*f4a2713aSLionel Sambuc } 716*f4a2713aSLionel Sambuc return 0; 717*f4a2713aSLionel Sambuc } 718*f4a2713aSLionel Sambuc 719*f4a2713aSLionel Sambuc case tok::identifier: 720*f4a2713aSLionel Sambuc case tok::kw_asm: 721*f4a2713aSLionel Sambuc case tok::kw_auto: 722*f4a2713aSLionel Sambuc case tok::kw_bool: 723*f4a2713aSLionel Sambuc case tok::kw_break: 724*f4a2713aSLionel Sambuc case tok::kw_case: 725*f4a2713aSLionel Sambuc case tok::kw_catch: 726*f4a2713aSLionel Sambuc case tok::kw_char: 727*f4a2713aSLionel Sambuc case tok::kw_class: 728*f4a2713aSLionel Sambuc case tok::kw_const: 729*f4a2713aSLionel Sambuc case tok::kw_const_cast: 730*f4a2713aSLionel Sambuc case tok::kw_continue: 731*f4a2713aSLionel Sambuc case tok::kw_default: 732*f4a2713aSLionel Sambuc case tok::kw_delete: 733*f4a2713aSLionel Sambuc case tok::kw_do: 734*f4a2713aSLionel Sambuc case tok::kw_double: 735*f4a2713aSLionel Sambuc case tok::kw_dynamic_cast: 736*f4a2713aSLionel Sambuc case tok::kw_else: 737*f4a2713aSLionel Sambuc case tok::kw_enum: 738*f4a2713aSLionel Sambuc case tok::kw_explicit: 739*f4a2713aSLionel Sambuc case tok::kw_export: 740*f4a2713aSLionel Sambuc case tok::kw_extern: 741*f4a2713aSLionel Sambuc case tok::kw_false: 742*f4a2713aSLionel Sambuc case tok::kw_float: 743*f4a2713aSLionel Sambuc case tok::kw_for: 744*f4a2713aSLionel Sambuc case tok::kw_friend: 745*f4a2713aSLionel Sambuc case tok::kw_goto: 746*f4a2713aSLionel Sambuc case tok::kw_if: 747*f4a2713aSLionel Sambuc case tok::kw_inline: 748*f4a2713aSLionel Sambuc case tok::kw_int: 749*f4a2713aSLionel Sambuc case tok::kw_long: 750*f4a2713aSLionel Sambuc case tok::kw_mutable: 751*f4a2713aSLionel Sambuc case tok::kw_namespace: 752*f4a2713aSLionel Sambuc case tok::kw_new: 753*f4a2713aSLionel Sambuc case tok::kw_operator: 754*f4a2713aSLionel Sambuc case tok::kw_private: 755*f4a2713aSLionel Sambuc case tok::kw_protected: 756*f4a2713aSLionel Sambuc case tok::kw_public: 757*f4a2713aSLionel Sambuc case tok::kw_register: 758*f4a2713aSLionel Sambuc case tok::kw_reinterpret_cast: 759*f4a2713aSLionel Sambuc case tok::kw_restrict: 760*f4a2713aSLionel Sambuc case tok::kw_return: 761*f4a2713aSLionel Sambuc case tok::kw_short: 762*f4a2713aSLionel Sambuc case tok::kw_signed: 763*f4a2713aSLionel Sambuc case tok::kw_sizeof: 764*f4a2713aSLionel Sambuc case tok::kw_static: 765*f4a2713aSLionel Sambuc case tok::kw_static_cast: 766*f4a2713aSLionel Sambuc case tok::kw_struct: 767*f4a2713aSLionel Sambuc case tok::kw_switch: 768*f4a2713aSLionel Sambuc case tok::kw_template: 769*f4a2713aSLionel Sambuc case tok::kw_this: 770*f4a2713aSLionel Sambuc case tok::kw_throw: 771*f4a2713aSLionel Sambuc case tok::kw_true: 772*f4a2713aSLionel Sambuc case tok::kw_try: 773*f4a2713aSLionel Sambuc case tok::kw_typedef: 774*f4a2713aSLionel Sambuc case tok::kw_typeid: 775*f4a2713aSLionel Sambuc case tok::kw_typename: 776*f4a2713aSLionel Sambuc case tok::kw_typeof: 777*f4a2713aSLionel Sambuc case tok::kw_union: 778*f4a2713aSLionel Sambuc case tok::kw_unsigned: 779*f4a2713aSLionel Sambuc case tok::kw_using: 780*f4a2713aSLionel Sambuc case tok::kw_virtual: 781*f4a2713aSLionel Sambuc case tok::kw_void: 782*f4a2713aSLionel Sambuc case tok::kw_volatile: 783*f4a2713aSLionel Sambuc case tok::kw_wchar_t: 784*f4a2713aSLionel Sambuc case tok::kw_while: 785*f4a2713aSLionel Sambuc case tok::kw__Bool: 786*f4a2713aSLionel Sambuc case tok::kw__Complex: 787*f4a2713aSLionel Sambuc case tok::kw___alignof: 788*f4a2713aSLionel Sambuc IdentifierInfo *II = Tok.getIdentifierInfo(); 789*f4a2713aSLionel Sambuc SelectorLoc = ConsumeToken(); 790*f4a2713aSLionel Sambuc return II; 791*f4a2713aSLionel Sambuc } 792*f4a2713aSLionel Sambuc } 793*f4a2713aSLionel Sambuc 794*f4a2713aSLionel Sambuc /// objc-for-collection-in: 'in' 795*f4a2713aSLionel Sambuc /// 796*f4a2713aSLionel Sambuc bool Parser::isTokIdentifier_in() const { 797*f4a2713aSLionel Sambuc // FIXME: May have to do additional look-ahead to only allow for 798*f4a2713aSLionel Sambuc // valid tokens following an 'in'; such as an identifier, unary operators, 799*f4a2713aSLionel Sambuc // '[' etc. 800*f4a2713aSLionel Sambuc return (getLangOpts().ObjC2 && Tok.is(tok::identifier) && 801*f4a2713aSLionel Sambuc Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); 802*f4a2713aSLionel Sambuc } 803*f4a2713aSLionel Sambuc 804*f4a2713aSLionel Sambuc /// ParseObjCTypeQualifierList - This routine parses the objective-c's type 805*f4a2713aSLionel Sambuc /// qualifier list and builds their bitmask representation in the input 806*f4a2713aSLionel Sambuc /// argument. 807*f4a2713aSLionel Sambuc /// 808*f4a2713aSLionel Sambuc /// objc-type-qualifiers: 809*f4a2713aSLionel Sambuc /// objc-type-qualifier 810*f4a2713aSLionel Sambuc /// objc-type-qualifiers objc-type-qualifier 811*f4a2713aSLionel Sambuc /// 812*f4a2713aSLionel Sambuc void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, 813*f4a2713aSLionel Sambuc Declarator::TheContext Context) { 814*f4a2713aSLionel Sambuc assert(Context == Declarator::ObjCParameterContext || 815*f4a2713aSLionel Sambuc Context == Declarator::ObjCResultContext); 816*f4a2713aSLionel Sambuc 817*f4a2713aSLionel Sambuc while (1) { 818*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 819*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPassingType(getCurScope(), DS, 820*f4a2713aSLionel Sambuc Context == Declarator::ObjCParameterContext); 821*f4a2713aSLionel Sambuc return cutOffParsing(); 822*f4a2713aSLionel Sambuc } 823*f4a2713aSLionel Sambuc 824*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) 825*f4a2713aSLionel Sambuc return; 826*f4a2713aSLionel Sambuc 827*f4a2713aSLionel Sambuc const IdentifierInfo *II = Tok.getIdentifierInfo(); 828*f4a2713aSLionel Sambuc for (unsigned i = 0; i != objc_NumQuals; ++i) { 829*f4a2713aSLionel Sambuc if (II != ObjCTypeQuals[i]) 830*f4a2713aSLionel Sambuc continue; 831*f4a2713aSLionel Sambuc 832*f4a2713aSLionel Sambuc ObjCDeclSpec::ObjCDeclQualifier Qual; 833*f4a2713aSLionel Sambuc switch (i) { 834*f4a2713aSLionel Sambuc default: llvm_unreachable("Unknown decl qualifier"); 835*f4a2713aSLionel Sambuc case objc_in: Qual = ObjCDeclSpec::DQ_In; break; 836*f4a2713aSLionel Sambuc case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; 837*f4a2713aSLionel Sambuc case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; 838*f4a2713aSLionel Sambuc case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; 839*f4a2713aSLionel Sambuc case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; 840*f4a2713aSLionel Sambuc case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; 841*f4a2713aSLionel Sambuc } 842*f4a2713aSLionel Sambuc DS.setObjCDeclQualifier(Qual); 843*f4a2713aSLionel Sambuc ConsumeToken(); 844*f4a2713aSLionel Sambuc II = 0; 845*f4a2713aSLionel Sambuc break; 846*f4a2713aSLionel Sambuc } 847*f4a2713aSLionel Sambuc 848*f4a2713aSLionel Sambuc // If this wasn't a recognized qualifier, bail out. 849*f4a2713aSLionel Sambuc if (II) return; 850*f4a2713aSLionel Sambuc } 851*f4a2713aSLionel Sambuc } 852*f4a2713aSLionel Sambuc 853*f4a2713aSLionel Sambuc /// Take all the decl attributes out of the given list and add 854*f4a2713aSLionel Sambuc /// them to the given attribute set. 855*f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs, 856*f4a2713aSLionel Sambuc AttributeList *list) { 857*f4a2713aSLionel Sambuc while (list) { 858*f4a2713aSLionel Sambuc AttributeList *cur = list; 859*f4a2713aSLionel Sambuc list = cur->getNext(); 860*f4a2713aSLionel Sambuc 861*f4a2713aSLionel Sambuc if (!cur->isUsedAsTypeAttr()) { 862*f4a2713aSLionel Sambuc // Clear out the next pointer. We're really completely 863*f4a2713aSLionel Sambuc // destroying the internal invariants of the declarator here, 864*f4a2713aSLionel Sambuc // but it doesn't matter because we're done with it. 865*f4a2713aSLionel Sambuc cur->setNext(0); 866*f4a2713aSLionel Sambuc attrs.add(cur); 867*f4a2713aSLionel Sambuc } 868*f4a2713aSLionel Sambuc } 869*f4a2713aSLionel Sambuc } 870*f4a2713aSLionel Sambuc 871*f4a2713aSLionel Sambuc /// takeDeclAttributes - Take all the decl attributes from the given 872*f4a2713aSLionel Sambuc /// declarator and add them to the given list. 873*f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs, 874*f4a2713aSLionel Sambuc Declarator &D) { 875*f4a2713aSLionel Sambuc // First, take ownership of all attributes. 876*f4a2713aSLionel Sambuc attrs.getPool().takeAllFrom(D.getAttributePool()); 877*f4a2713aSLionel Sambuc attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); 878*f4a2713aSLionel Sambuc 879*f4a2713aSLionel Sambuc // Now actually move the attributes over. 880*f4a2713aSLionel Sambuc takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); 881*f4a2713aSLionel Sambuc takeDeclAttributes(attrs, D.getAttributes()); 882*f4a2713aSLionel Sambuc for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) 883*f4a2713aSLionel Sambuc takeDeclAttributes(attrs, 884*f4a2713aSLionel Sambuc const_cast<AttributeList*>(D.getTypeObject(i).getAttrs())); 885*f4a2713aSLionel Sambuc } 886*f4a2713aSLionel Sambuc 887*f4a2713aSLionel Sambuc /// objc-type-name: 888*f4a2713aSLionel Sambuc /// '(' objc-type-qualifiers[opt] type-name ')' 889*f4a2713aSLionel Sambuc /// '(' objc-type-qualifiers[opt] ')' 890*f4a2713aSLionel Sambuc /// 891*f4a2713aSLionel Sambuc ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, 892*f4a2713aSLionel Sambuc Declarator::TheContext context, 893*f4a2713aSLionel Sambuc ParsedAttributes *paramAttrs) { 894*f4a2713aSLionel Sambuc assert(context == Declarator::ObjCParameterContext || 895*f4a2713aSLionel Sambuc context == Declarator::ObjCResultContext); 896*f4a2713aSLionel Sambuc assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext)); 897*f4a2713aSLionel Sambuc 898*f4a2713aSLionel Sambuc assert(Tok.is(tok::l_paren) && "expected ("); 899*f4a2713aSLionel Sambuc 900*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 901*f4a2713aSLionel Sambuc T.consumeOpen(); 902*f4a2713aSLionel Sambuc 903*f4a2713aSLionel Sambuc SourceLocation TypeStartLoc = Tok.getLocation(); 904*f4a2713aSLionel Sambuc ObjCDeclContextSwitch ObjCDC(*this); 905*f4a2713aSLionel Sambuc 906*f4a2713aSLionel Sambuc // Parse type qualifiers, in, inout, etc. 907*f4a2713aSLionel Sambuc ParseObjCTypeQualifierList(DS, context); 908*f4a2713aSLionel Sambuc 909*f4a2713aSLionel Sambuc ParsedType Ty; 910*f4a2713aSLionel Sambuc if (isTypeSpecifierQualifier()) { 911*f4a2713aSLionel Sambuc // Parse an abstract declarator. 912*f4a2713aSLionel Sambuc DeclSpec declSpec(AttrFactory); 913*f4a2713aSLionel Sambuc declSpec.setObjCQualifiers(&DS); 914*f4a2713aSLionel Sambuc ParseSpecifierQualifierList(declSpec); 915*f4a2713aSLionel Sambuc declSpec.SetRangeEnd(Tok.getLocation()); 916*f4a2713aSLionel Sambuc Declarator declarator(declSpec, context); 917*f4a2713aSLionel Sambuc ParseDeclarator(declarator); 918*f4a2713aSLionel Sambuc 919*f4a2713aSLionel Sambuc // If that's not invalid, extract a type. 920*f4a2713aSLionel Sambuc if (!declarator.isInvalidType()) { 921*f4a2713aSLionel Sambuc TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); 922*f4a2713aSLionel Sambuc if (!type.isInvalid()) 923*f4a2713aSLionel Sambuc Ty = type.get(); 924*f4a2713aSLionel Sambuc 925*f4a2713aSLionel Sambuc // If we're parsing a parameter, steal all the decl attributes 926*f4a2713aSLionel Sambuc // and add them to the decl spec. 927*f4a2713aSLionel Sambuc if (context == Declarator::ObjCParameterContext) 928*f4a2713aSLionel Sambuc takeDeclAttributes(*paramAttrs, declarator); 929*f4a2713aSLionel Sambuc } 930*f4a2713aSLionel Sambuc } else if (context == Declarator::ObjCResultContext && 931*f4a2713aSLionel Sambuc Tok.is(tok::identifier)) { 932*f4a2713aSLionel Sambuc if (!Ident_instancetype) 933*f4a2713aSLionel Sambuc Ident_instancetype = PP.getIdentifierInfo("instancetype"); 934*f4a2713aSLionel Sambuc 935*f4a2713aSLionel Sambuc if (Tok.getIdentifierInfo() == Ident_instancetype) { 936*f4a2713aSLionel Sambuc Ty = Actions.ActOnObjCInstanceType(Tok.getLocation()); 937*f4a2713aSLionel Sambuc ConsumeToken(); 938*f4a2713aSLionel Sambuc } 939*f4a2713aSLionel Sambuc } 940*f4a2713aSLionel Sambuc 941*f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren)) 942*f4a2713aSLionel Sambuc T.consumeClose(); 943*f4a2713aSLionel Sambuc else if (Tok.getLocation() == TypeStartLoc) { 944*f4a2713aSLionel Sambuc // If we didn't eat any tokens, then this isn't a type. 945*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_type); 946*f4a2713aSLionel Sambuc SkipUntil(tok::r_paren, StopAtSemi); 947*f4a2713aSLionel Sambuc } else { 948*f4a2713aSLionel Sambuc // Otherwise, we found *something*, but didn't get a ')' in the right 949*f4a2713aSLionel Sambuc // place. Emit an error then return what we have as the type. 950*f4a2713aSLionel Sambuc T.consumeClose(); 951*f4a2713aSLionel Sambuc } 952*f4a2713aSLionel Sambuc return Ty; 953*f4a2713aSLionel Sambuc } 954*f4a2713aSLionel Sambuc 955*f4a2713aSLionel Sambuc /// objc-method-decl: 956*f4a2713aSLionel Sambuc /// objc-selector 957*f4a2713aSLionel Sambuc /// objc-keyword-selector objc-parmlist[opt] 958*f4a2713aSLionel Sambuc /// objc-type-name objc-selector 959*f4a2713aSLionel Sambuc /// objc-type-name objc-keyword-selector objc-parmlist[opt] 960*f4a2713aSLionel Sambuc /// 961*f4a2713aSLionel Sambuc /// objc-keyword-selector: 962*f4a2713aSLionel Sambuc /// objc-keyword-decl 963*f4a2713aSLionel Sambuc /// objc-keyword-selector objc-keyword-decl 964*f4a2713aSLionel Sambuc /// 965*f4a2713aSLionel Sambuc /// objc-keyword-decl: 966*f4a2713aSLionel Sambuc /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier 967*f4a2713aSLionel Sambuc /// objc-selector ':' objc-keyword-attributes[opt] identifier 968*f4a2713aSLionel Sambuc /// ':' objc-type-name objc-keyword-attributes[opt] identifier 969*f4a2713aSLionel Sambuc /// ':' objc-keyword-attributes[opt] identifier 970*f4a2713aSLionel Sambuc /// 971*f4a2713aSLionel Sambuc /// objc-parmlist: 972*f4a2713aSLionel Sambuc /// objc-parms objc-ellipsis[opt] 973*f4a2713aSLionel Sambuc /// 974*f4a2713aSLionel Sambuc /// objc-parms: 975*f4a2713aSLionel Sambuc /// objc-parms , parameter-declaration 976*f4a2713aSLionel Sambuc /// 977*f4a2713aSLionel Sambuc /// objc-ellipsis: 978*f4a2713aSLionel Sambuc /// , ... 979*f4a2713aSLionel Sambuc /// 980*f4a2713aSLionel Sambuc /// objc-keyword-attributes: [OBJC2] 981*f4a2713aSLionel Sambuc /// __attribute__((unused)) 982*f4a2713aSLionel Sambuc /// 983*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, 984*f4a2713aSLionel Sambuc tok::TokenKind mType, 985*f4a2713aSLionel Sambuc tok::ObjCKeywordKind MethodImplKind, 986*f4a2713aSLionel Sambuc bool MethodDefinition) { 987*f4a2713aSLionel Sambuc ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); 988*f4a2713aSLionel Sambuc 989*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 990*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, 991*f4a2713aSLionel Sambuc /*ReturnType=*/ ParsedType()); 992*f4a2713aSLionel Sambuc cutOffParsing(); 993*f4a2713aSLionel Sambuc return 0; 994*f4a2713aSLionel Sambuc } 995*f4a2713aSLionel Sambuc 996*f4a2713aSLionel Sambuc // Parse the return type if present. 997*f4a2713aSLionel Sambuc ParsedType ReturnType; 998*f4a2713aSLionel Sambuc ObjCDeclSpec DSRet; 999*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) 1000*f4a2713aSLionel Sambuc ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0); 1001*f4a2713aSLionel Sambuc 1002*f4a2713aSLionel Sambuc // If attributes exist before the method, parse them. 1003*f4a2713aSLionel Sambuc ParsedAttributes methodAttrs(AttrFactory); 1004*f4a2713aSLionel Sambuc if (getLangOpts().ObjC2) 1005*f4a2713aSLionel Sambuc MaybeParseGNUAttributes(methodAttrs); 1006*f4a2713aSLionel Sambuc 1007*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1008*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, 1009*f4a2713aSLionel Sambuc ReturnType); 1010*f4a2713aSLionel Sambuc cutOffParsing(); 1011*f4a2713aSLionel Sambuc return 0; 1012*f4a2713aSLionel Sambuc } 1013*f4a2713aSLionel Sambuc 1014*f4a2713aSLionel Sambuc // Now parse the selector. 1015*f4a2713aSLionel Sambuc SourceLocation selLoc; 1016*f4a2713aSLionel Sambuc IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc); 1017*f4a2713aSLionel Sambuc 1018*f4a2713aSLionel Sambuc // An unnamed colon is valid. 1019*f4a2713aSLionel Sambuc if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name. 1020*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_selector_for_method) 1021*f4a2713aSLionel Sambuc << SourceRange(mLoc, Tok.getLocation()); 1022*f4a2713aSLionel Sambuc // Skip until we get a ; or @. 1023*f4a2713aSLionel Sambuc SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); 1024*f4a2713aSLionel Sambuc return 0; 1025*f4a2713aSLionel Sambuc } 1026*f4a2713aSLionel Sambuc 1027*f4a2713aSLionel Sambuc SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; 1028*f4a2713aSLionel Sambuc if (Tok.isNot(tok::colon)) { 1029*f4a2713aSLionel Sambuc // If attributes exist after the method, parse them. 1030*f4a2713aSLionel Sambuc if (getLangOpts().ObjC2) 1031*f4a2713aSLionel Sambuc MaybeParseGNUAttributes(methodAttrs); 1032*f4a2713aSLionel Sambuc 1033*f4a2713aSLionel Sambuc Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); 1034*f4a2713aSLionel Sambuc Decl *Result 1035*f4a2713aSLionel Sambuc = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), 1036*f4a2713aSLionel Sambuc mType, DSRet, ReturnType, 1037*f4a2713aSLionel Sambuc selLoc, Sel, 0, 1038*f4a2713aSLionel Sambuc CParamInfo.data(), CParamInfo.size(), 1039*f4a2713aSLionel Sambuc methodAttrs.getList(), MethodImplKind, 1040*f4a2713aSLionel Sambuc false, MethodDefinition); 1041*f4a2713aSLionel Sambuc PD.complete(Result); 1042*f4a2713aSLionel Sambuc return Result; 1043*f4a2713aSLionel Sambuc } 1044*f4a2713aSLionel Sambuc 1045*f4a2713aSLionel Sambuc SmallVector<IdentifierInfo *, 12> KeyIdents; 1046*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 12> KeyLocs; 1047*f4a2713aSLionel Sambuc SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; 1048*f4a2713aSLionel Sambuc ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | 1049*f4a2713aSLionel Sambuc Scope::FunctionDeclarationScope | Scope::DeclScope); 1050*f4a2713aSLionel Sambuc 1051*f4a2713aSLionel Sambuc AttributePool allParamAttrs(AttrFactory); 1052*f4a2713aSLionel Sambuc while (1) { 1053*f4a2713aSLionel Sambuc ParsedAttributes paramAttrs(AttrFactory); 1054*f4a2713aSLionel Sambuc Sema::ObjCArgInfo ArgInfo; 1055*f4a2713aSLionel Sambuc 1056*f4a2713aSLionel Sambuc // Each iteration parses a single keyword argument. 1057*f4a2713aSLionel Sambuc if (Tok.isNot(tok::colon)) { 1058*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_colon); 1059*f4a2713aSLionel Sambuc break; 1060*f4a2713aSLionel Sambuc } 1061*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the ':'. 1062*f4a2713aSLionel Sambuc 1063*f4a2713aSLionel Sambuc ArgInfo.Type = ParsedType(); 1064*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) // Parse the argument type if present. 1065*f4a2713aSLionel Sambuc ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, 1066*f4a2713aSLionel Sambuc Declarator::ObjCParameterContext, 1067*f4a2713aSLionel Sambuc ¶mAttrs); 1068*f4a2713aSLionel Sambuc 1069*f4a2713aSLionel Sambuc // If attributes exist before the argument name, parse them. 1070*f4a2713aSLionel Sambuc // Regardless, collect all the attributes we've parsed so far. 1071*f4a2713aSLionel Sambuc ArgInfo.ArgAttrs = 0; 1072*f4a2713aSLionel Sambuc if (getLangOpts().ObjC2) { 1073*f4a2713aSLionel Sambuc MaybeParseGNUAttributes(paramAttrs); 1074*f4a2713aSLionel Sambuc ArgInfo.ArgAttrs = paramAttrs.getList(); 1075*f4a2713aSLionel Sambuc } 1076*f4a2713aSLionel Sambuc 1077*f4a2713aSLionel Sambuc // Code completion for the next piece of the selector. 1078*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1079*f4a2713aSLionel Sambuc KeyIdents.push_back(SelIdent); 1080*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), 1081*f4a2713aSLionel Sambuc mType == tok::minus, 1082*f4a2713aSLionel Sambuc /*AtParameterName=*/true, 1083*f4a2713aSLionel Sambuc ReturnType, KeyIdents); 1084*f4a2713aSLionel Sambuc cutOffParsing(); 1085*f4a2713aSLionel Sambuc return 0; 1086*f4a2713aSLionel Sambuc } 1087*f4a2713aSLionel Sambuc 1088*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1089*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing argument name. 1090*f4a2713aSLionel Sambuc break; 1091*f4a2713aSLionel Sambuc } 1092*f4a2713aSLionel Sambuc 1093*f4a2713aSLionel Sambuc ArgInfo.Name = Tok.getIdentifierInfo(); 1094*f4a2713aSLionel Sambuc ArgInfo.NameLoc = Tok.getLocation(); 1095*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the identifier. 1096*f4a2713aSLionel Sambuc 1097*f4a2713aSLionel Sambuc ArgInfos.push_back(ArgInfo); 1098*f4a2713aSLionel Sambuc KeyIdents.push_back(SelIdent); 1099*f4a2713aSLionel Sambuc KeyLocs.push_back(selLoc); 1100*f4a2713aSLionel Sambuc 1101*f4a2713aSLionel Sambuc // Make sure the attributes persist. 1102*f4a2713aSLionel Sambuc allParamAttrs.takeAllFrom(paramAttrs.getPool()); 1103*f4a2713aSLionel Sambuc 1104*f4a2713aSLionel Sambuc // Code completion for the next piece of the selector. 1105*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1106*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), 1107*f4a2713aSLionel Sambuc mType == tok::minus, 1108*f4a2713aSLionel Sambuc /*AtParameterName=*/false, 1109*f4a2713aSLionel Sambuc ReturnType, KeyIdents); 1110*f4a2713aSLionel Sambuc cutOffParsing(); 1111*f4a2713aSLionel Sambuc return 0; 1112*f4a2713aSLionel Sambuc } 1113*f4a2713aSLionel Sambuc 1114*f4a2713aSLionel Sambuc // Check for another keyword selector. 1115*f4a2713aSLionel Sambuc SelIdent = ParseObjCSelectorPiece(selLoc); 1116*f4a2713aSLionel Sambuc if (!SelIdent && Tok.isNot(tok::colon)) 1117*f4a2713aSLionel Sambuc break; 1118*f4a2713aSLionel Sambuc if (!SelIdent) { 1119*f4a2713aSLionel Sambuc SourceLocation ColonLoc = Tok.getLocation(); 1120*f4a2713aSLionel Sambuc if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) { 1121*f4a2713aSLionel Sambuc Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name; 1122*f4a2713aSLionel Sambuc Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name; 1123*f4a2713aSLionel Sambuc Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name; 1124*f4a2713aSLionel Sambuc } 1125*f4a2713aSLionel Sambuc } 1126*f4a2713aSLionel Sambuc // We have a selector or a colon, continue parsing. 1127*f4a2713aSLionel Sambuc } 1128*f4a2713aSLionel Sambuc 1129*f4a2713aSLionel Sambuc bool isVariadic = false; 1130*f4a2713aSLionel Sambuc bool cStyleParamWarned = false; 1131*f4a2713aSLionel Sambuc // Parse the (optional) parameter list. 1132*f4a2713aSLionel Sambuc while (Tok.is(tok::comma)) { 1133*f4a2713aSLionel Sambuc ConsumeToken(); 1134*f4a2713aSLionel Sambuc if (Tok.is(tok::ellipsis)) { 1135*f4a2713aSLionel Sambuc isVariadic = true; 1136*f4a2713aSLionel Sambuc ConsumeToken(); 1137*f4a2713aSLionel Sambuc break; 1138*f4a2713aSLionel Sambuc } 1139*f4a2713aSLionel Sambuc if (!cStyleParamWarned) { 1140*f4a2713aSLionel Sambuc Diag(Tok, diag::warn_cstyle_param); 1141*f4a2713aSLionel Sambuc cStyleParamWarned = true; 1142*f4a2713aSLionel Sambuc } 1143*f4a2713aSLionel Sambuc DeclSpec DS(AttrFactory); 1144*f4a2713aSLionel Sambuc ParseDeclarationSpecifiers(DS); 1145*f4a2713aSLionel Sambuc // Parse the declarator. 1146*f4a2713aSLionel Sambuc Declarator ParmDecl(DS, Declarator::PrototypeContext); 1147*f4a2713aSLionel Sambuc ParseDeclarator(ParmDecl); 1148*f4a2713aSLionel Sambuc IdentifierInfo *ParmII = ParmDecl.getIdentifier(); 1149*f4a2713aSLionel Sambuc Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); 1150*f4a2713aSLionel Sambuc CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, 1151*f4a2713aSLionel Sambuc ParmDecl.getIdentifierLoc(), 1152*f4a2713aSLionel Sambuc Param, 1153*f4a2713aSLionel Sambuc 0)); 1154*f4a2713aSLionel Sambuc } 1155*f4a2713aSLionel Sambuc 1156*f4a2713aSLionel Sambuc // FIXME: Add support for optional parameter list... 1157*f4a2713aSLionel Sambuc // If attributes exist after the method, parse them. 1158*f4a2713aSLionel Sambuc if (getLangOpts().ObjC2) 1159*f4a2713aSLionel Sambuc MaybeParseGNUAttributes(methodAttrs); 1160*f4a2713aSLionel Sambuc 1161*f4a2713aSLionel Sambuc if (KeyIdents.size() == 0) 1162*f4a2713aSLionel Sambuc return 0; 1163*f4a2713aSLionel Sambuc 1164*f4a2713aSLionel Sambuc Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), 1165*f4a2713aSLionel Sambuc &KeyIdents[0]); 1166*f4a2713aSLionel Sambuc Decl *Result 1167*f4a2713aSLionel Sambuc = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), 1168*f4a2713aSLionel Sambuc mType, DSRet, ReturnType, 1169*f4a2713aSLionel Sambuc KeyLocs, Sel, &ArgInfos[0], 1170*f4a2713aSLionel Sambuc CParamInfo.data(), CParamInfo.size(), 1171*f4a2713aSLionel Sambuc methodAttrs.getList(), 1172*f4a2713aSLionel Sambuc MethodImplKind, isVariadic, MethodDefinition); 1173*f4a2713aSLionel Sambuc 1174*f4a2713aSLionel Sambuc PD.complete(Result); 1175*f4a2713aSLionel Sambuc return Result; 1176*f4a2713aSLionel Sambuc } 1177*f4a2713aSLionel Sambuc 1178*f4a2713aSLionel Sambuc /// objc-protocol-refs: 1179*f4a2713aSLionel Sambuc /// '<' identifier-list '>' 1180*f4a2713aSLionel Sambuc /// 1181*f4a2713aSLionel Sambuc bool Parser:: 1182*f4a2713aSLionel Sambuc ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, 1183*f4a2713aSLionel Sambuc SmallVectorImpl<SourceLocation> &ProtocolLocs, 1184*f4a2713aSLionel Sambuc bool WarnOnDeclarations, 1185*f4a2713aSLionel Sambuc SourceLocation &LAngleLoc, SourceLocation &EndLoc) { 1186*f4a2713aSLionel Sambuc assert(Tok.is(tok::less) && "expected <"); 1187*f4a2713aSLionel Sambuc 1188*f4a2713aSLionel Sambuc LAngleLoc = ConsumeToken(); // the "<" 1189*f4a2713aSLionel Sambuc 1190*f4a2713aSLionel Sambuc SmallVector<IdentifierLocPair, 8> ProtocolIdents; 1191*f4a2713aSLionel Sambuc 1192*f4a2713aSLionel Sambuc while (1) { 1193*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1194*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), 1195*f4a2713aSLionel Sambuc ProtocolIdents.size()); 1196*f4a2713aSLionel Sambuc cutOffParsing(); 1197*f4a2713aSLionel Sambuc return true; 1198*f4a2713aSLionel Sambuc } 1199*f4a2713aSLionel Sambuc 1200*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1201*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1202*f4a2713aSLionel Sambuc SkipUntil(tok::greater, StopAtSemi); 1203*f4a2713aSLionel Sambuc return true; 1204*f4a2713aSLionel Sambuc } 1205*f4a2713aSLionel Sambuc ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(), 1206*f4a2713aSLionel Sambuc Tok.getLocation())); 1207*f4a2713aSLionel Sambuc ProtocolLocs.push_back(Tok.getLocation()); 1208*f4a2713aSLionel Sambuc ConsumeToken(); 1209*f4a2713aSLionel Sambuc 1210*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 1211*f4a2713aSLionel Sambuc break; 1212*f4a2713aSLionel Sambuc ConsumeToken(); 1213*f4a2713aSLionel Sambuc } 1214*f4a2713aSLionel Sambuc 1215*f4a2713aSLionel Sambuc // Consume the '>'. 1216*f4a2713aSLionel Sambuc if (ParseGreaterThanInTemplateList(EndLoc, /*ConsumeLastToken=*/true)) 1217*f4a2713aSLionel Sambuc return true; 1218*f4a2713aSLionel Sambuc 1219*f4a2713aSLionel Sambuc // Convert the list of protocols identifiers into a list of protocol decls. 1220*f4a2713aSLionel Sambuc Actions.FindProtocolDeclaration(WarnOnDeclarations, 1221*f4a2713aSLionel Sambuc &ProtocolIdents[0], ProtocolIdents.size(), 1222*f4a2713aSLionel Sambuc Protocols); 1223*f4a2713aSLionel Sambuc return false; 1224*f4a2713aSLionel Sambuc } 1225*f4a2713aSLionel Sambuc 1226*f4a2713aSLionel Sambuc /// \brief Parse the Objective-C protocol qualifiers that follow a typename 1227*f4a2713aSLionel Sambuc /// in a decl-specifier-seq, starting at the '<'. 1228*f4a2713aSLionel Sambuc bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) { 1229*f4a2713aSLionel Sambuc assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'"); 1230*f4a2713aSLionel Sambuc assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C"); 1231*f4a2713aSLionel Sambuc SourceLocation LAngleLoc, EndProtoLoc; 1232*f4a2713aSLionel Sambuc SmallVector<Decl *, 8> ProtocolDecl; 1233*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 8> ProtocolLocs; 1234*f4a2713aSLionel Sambuc bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, 1235*f4a2713aSLionel Sambuc LAngleLoc, EndProtoLoc); 1236*f4a2713aSLionel Sambuc DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), 1237*f4a2713aSLionel Sambuc ProtocolLocs.data(), LAngleLoc); 1238*f4a2713aSLionel Sambuc if (EndProtoLoc.isValid()) 1239*f4a2713aSLionel Sambuc DS.SetRangeEnd(EndProtoLoc); 1240*f4a2713aSLionel Sambuc return Result; 1241*f4a2713aSLionel Sambuc } 1242*f4a2713aSLionel Sambuc 1243*f4a2713aSLionel Sambuc void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, 1244*f4a2713aSLionel Sambuc BalancedDelimiterTracker &T, 1245*f4a2713aSLionel Sambuc SmallVectorImpl<Decl *> &AllIvarDecls, 1246*f4a2713aSLionel Sambuc bool RBraceMissing) { 1247*f4a2713aSLionel Sambuc if (!RBraceMissing) 1248*f4a2713aSLionel Sambuc T.consumeClose(); 1249*f4a2713aSLionel Sambuc 1250*f4a2713aSLionel Sambuc Actions.ActOnObjCContainerStartDefinition(interfaceDecl); 1251*f4a2713aSLionel Sambuc Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); 1252*f4a2713aSLionel Sambuc Actions.ActOnObjCContainerFinishDefinition(); 1253*f4a2713aSLionel Sambuc // Call ActOnFields() even if we don't have any decls. This is useful 1254*f4a2713aSLionel Sambuc // for code rewriting tools that need to be aware of the empty list. 1255*f4a2713aSLionel Sambuc Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, 1256*f4a2713aSLionel Sambuc AllIvarDecls, 1257*f4a2713aSLionel Sambuc T.getOpenLocation(), T.getCloseLocation(), 0); 1258*f4a2713aSLionel Sambuc } 1259*f4a2713aSLionel Sambuc 1260*f4a2713aSLionel Sambuc /// objc-class-instance-variables: 1261*f4a2713aSLionel Sambuc /// '{' objc-instance-variable-decl-list[opt] '}' 1262*f4a2713aSLionel Sambuc /// 1263*f4a2713aSLionel Sambuc /// objc-instance-variable-decl-list: 1264*f4a2713aSLionel Sambuc /// objc-visibility-spec 1265*f4a2713aSLionel Sambuc /// objc-instance-variable-decl ';' 1266*f4a2713aSLionel Sambuc /// ';' 1267*f4a2713aSLionel Sambuc /// objc-instance-variable-decl-list objc-visibility-spec 1268*f4a2713aSLionel Sambuc /// objc-instance-variable-decl-list objc-instance-variable-decl ';' 1269*f4a2713aSLionel Sambuc /// objc-instance-variable-decl-list ';' 1270*f4a2713aSLionel Sambuc /// 1271*f4a2713aSLionel Sambuc /// objc-visibility-spec: 1272*f4a2713aSLionel Sambuc /// @private 1273*f4a2713aSLionel Sambuc /// @protected 1274*f4a2713aSLionel Sambuc /// @public 1275*f4a2713aSLionel Sambuc /// @package [OBJC2] 1276*f4a2713aSLionel Sambuc /// 1277*f4a2713aSLionel Sambuc /// objc-instance-variable-decl: 1278*f4a2713aSLionel Sambuc /// struct-declaration 1279*f4a2713aSLionel Sambuc /// 1280*f4a2713aSLionel Sambuc void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, 1281*f4a2713aSLionel Sambuc tok::ObjCKeywordKind visibility, 1282*f4a2713aSLionel Sambuc SourceLocation atLoc) { 1283*f4a2713aSLionel Sambuc assert(Tok.is(tok::l_brace) && "expected {"); 1284*f4a2713aSLionel Sambuc SmallVector<Decl *, 32> AllIvarDecls; 1285*f4a2713aSLionel Sambuc 1286*f4a2713aSLionel Sambuc ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); 1287*f4a2713aSLionel Sambuc ObjCDeclContextSwitch ObjCDC(*this); 1288*f4a2713aSLionel Sambuc 1289*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_brace); 1290*f4a2713aSLionel Sambuc T.consumeOpen(); 1291*f4a2713aSLionel Sambuc // While we still have something to read, read the instance variables. 1292*f4a2713aSLionel Sambuc while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { 1293*f4a2713aSLionel Sambuc // Each iteration of this loop reads one objc-instance-variable-decl. 1294*f4a2713aSLionel Sambuc 1295*f4a2713aSLionel Sambuc // Check for extraneous top-level semicolon. 1296*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) { 1297*f4a2713aSLionel Sambuc ConsumeExtraSemi(InstanceVariableList); 1298*f4a2713aSLionel Sambuc continue; 1299*f4a2713aSLionel Sambuc } 1300*f4a2713aSLionel Sambuc 1301*f4a2713aSLionel Sambuc // Set the default visibility to private. 1302*f4a2713aSLionel Sambuc if (Tok.is(tok::at)) { // parse objc-visibility-spec 1303*f4a2713aSLionel Sambuc ConsumeToken(); // eat the @ sign 1304*f4a2713aSLionel Sambuc 1305*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1306*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtVisibility(getCurScope()); 1307*f4a2713aSLionel Sambuc return cutOffParsing(); 1308*f4a2713aSLionel Sambuc } 1309*f4a2713aSLionel Sambuc 1310*f4a2713aSLionel Sambuc switch (Tok.getObjCKeywordID()) { 1311*f4a2713aSLionel Sambuc case tok::objc_private: 1312*f4a2713aSLionel Sambuc case tok::objc_public: 1313*f4a2713aSLionel Sambuc case tok::objc_protected: 1314*f4a2713aSLionel Sambuc case tok::objc_package: 1315*f4a2713aSLionel Sambuc visibility = Tok.getObjCKeywordID(); 1316*f4a2713aSLionel Sambuc ConsumeToken(); 1317*f4a2713aSLionel Sambuc continue; 1318*f4a2713aSLionel Sambuc 1319*f4a2713aSLionel Sambuc case tok::objc_end: 1320*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_unexpected_atend); 1321*f4a2713aSLionel Sambuc Tok.setLocation(Tok.getLocation().getLocWithOffset(-1)); 1322*f4a2713aSLionel Sambuc Tok.setKind(tok::at); 1323*f4a2713aSLionel Sambuc Tok.setLength(1); 1324*f4a2713aSLionel Sambuc PP.EnterToken(Tok); 1325*f4a2713aSLionel Sambuc HelperActionsForIvarDeclarations(interfaceDecl, atLoc, 1326*f4a2713aSLionel Sambuc T, AllIvarDecls, true); 1327*f4a2713aSLionel Sambuc return; 1328*f4a2713aSLionel Sambuc 1329*f4a2713aSLionel Sambuc default: 1330*f4a2713aSLionel Sambuc Diag(Tok, diag::err_objc_illegal_visibility_spec); 1331*f4a2713aSLionel Sambuc continue; 1332*f4a2713aSLionel Sambuc } 1333*f4a2713aSLionel Sambuc } 1334*f4a2713aSLionel Sambuc 1335*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1336*f4a2713aSLionel Sambuc Actions.CodeCompleteOrdinaryName(getCurScope(), 1337*f4a2713aSLionel Sambuc Sema::PCC_ObjCInstanceVariableList); 1338*f4a2713aSLionel Sambuc return cutOffParsing(); 1339*f4a2713aSLionel Sambuc } 1340*f4a2713aSLionel Sambuc 1341*f4a2713aSLionel Sambuc struct ObjCIvarCallback : FieldCallback { 1342*f4a2713aSLionel Sambuc Parser &P; 1343*f4a2713aSLionel Sambuc Decl *IDecl; 1344*f4a2713aSLionel Sambuc tok::ObjCKeywordKind visibility; 1345*f4a2713aSLionel Sambuc SmallVectorImpl<Decl *> &AllIvarDecls; 1346*f4a2713aSLionel Sambuc 1347*f4a2713aSLionel Sambuc ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V, 1348*f4a2713aSLionel Sambuc SmallVectorImpl<Decl *> &AllIvarDecls) : 1349*f4a2713aSLionel Sambuc P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { 1350*f4a2713aSLionel Sambuc } 1351*f4a2713aSLionel Sambuc 1352*f4a2713aSLionel Sambuc void invoke(ParsingFieldDeclarator &FD) { 1353*f4a2713aSLionel Sambuc P.Actions.ActOnObjCContainerStartDefinition(IDecl); 1354*f4a2713aSLionel Sambuc // Install the declarator into the interface decl. 1355*f4a2713aSLionel Sambuc Decl *Field 1356*f4a2713aSLionel Sambuc = P.Actions.ActOnIvar(P.getCurScope(), 1357*f4a2713aSLionel Sambuc FD.D.getDeclSpec().getSourceRange().getBegin(), 1358*f4a2713aSLionel Sambuc FD.D, FD.BitfieldSize, visibility); 1359*f4a2713aSLionel Sambuc P.Actions.ActOnObjCContainerFinishDefinition(); 1360*f4a2713aSLionel Sambuc if (Field) 1361*f4a2713aSLionel Sambuc AllIvarDecls.push_back(Field); 1362*f4a2713aSLionel Sambuc FD.complete(Field); 1363*f4a2713aSLionel Sambuc } 1364*f4a2713aSLionel Sambuc } Callback(*this, interfaceDecl, visibility, AllIvarDecls); 1365*f4a2713aSLionel Sambuc 1366*f4a2713aSLionel Sambuc // Parse all the comma separated declarators. 1367*f4a2713aSLionel Sambuc ParsingDeclSpec DS(*this); 1368*f4a2713aSLionel Sambuc ParseStructDeclaration(DS, Callback); 1369*f4a2713aSLionel Sambuc 1370*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) { 1371*f4a2713aSLionel Sambuc ConsumeToken(); 1372*f4a2713aSLionel Sambuc } else { 1373*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_semi_decl_list); 1374*f4a2713aSLionel Sambuc // Skip to end of block or statement 1375*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); 1376*f4a2713aSLionel Sambuc } 1377*f4a2713aSLionel Sambuc } 1378*f4a2713aSLionel Sambuc HelperActionsForIvarDeclarations(interfaceDecl, atLoc, 1379*f4a2713aSLionel Sambuc T, AllIvarDecls, false); 1380*f4a2713aSLionel Sambuc return; 1381*f4a2713aSLionel Sambuc } 1382*f4a2713aSLionel Sambuc 1383*f4a2713aSLionel Sambuc /// objc-protocol-declaration: 1384*f4a2713aSLionel Sambuc /// objc-protocol-definition 1385*f4a2713aSLionel Sambuc /// objc-protocol-forward-reference 1386*f4a2713aSLionel Sambuc /// 1387*f4a2713aSLionel Sambuc /// objc-protocol-definition: 1388*f4a2713aSLionel Sambuc /// \@protocol identifier 1389*f4a2713aSLionel Sambuc /// objc-protocol-refs[opt] 1390*f4a2713aSLionel Sambuc /// objc-interface-decl-list 1391*f4a2713aSLionel Sambuc /// \@end 1392*f4a2713aSLionel Sambuc /// 1393*f4a2713aSLionel Sambuc /// objc-protocol-forward-reference: 1394*f4a2713aSLionel Sambuc /// \@protocol identifier-list ';' 1395*f4a2713aSLionel Sambuc /// 1396*f4a2713aSLionel Sambuc /// "\@protocol identifier ;" should be resolved as "\@protocol 1397*f4a2713aSLionel Sambuc /// identifier-list ;": objc-interface-decl-list may not start with a 1398*f4a2713aSLionel Sambuc /// semicolon in the first alternative if objc-protocol-refs are omitted. 1399*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy 1400*f4a2713aSLionel Sambuc Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, 1401*f4a2713aSLionel Sambuc ParsedAttributes &attrs) { 1402*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_protocol) && 1403*f4a2713aSLionel Sambuc "ParseObjCAtProtocolDeclaration(): Expected @protocol"); 1404*f4a2713aSLionel Sambuc ConsumeToken(); // the "protocol" identifier 1405*f4a2713aSLionel Sambuc 1406*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1407*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCProtocolDecl(getCurScope()); 1408*f4a2713aSLionel Sambuc cutOffParsing(); 1409*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1410*f4a2713aSLionel Sambuc } 1411*f4a2713aSLionel Sambuc 1412*f4a2713aSLionel Sambuc MaybeSkipAttributes(tok::objc_protocol); 1413*f4a2713aSLionel Sambuc 1414*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1415*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing protocol name. 1416*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1417*f4a2713aSLionel Sambuc } 1418*f4a2713aSLionel Sambuc // Save the protocol name, then consume it. 1419*f4a2713aSLionel Sambuc IdentifierInfo *protocolName = Tok.getIdentifierInfo(); 1420*f4a2713aSLionel Sambuc SourceLocation nameLoc = ConsumeToken(); 1421*f4a2713aSLionel Sambuc 1422*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) { // forward declaration of one protocol. 1423*f4a2713aSLionel Sambuc IdentifierLocPair ProtoInfo(protocolName, nameLoc); 1424*f4a2713aSLionel Sambuc ConsumeToken(); 1425*f4a2713aSLionel Sambuc return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, 1426*f4a2713aSLionel Sambuc attrs.getList()); 1427*f4a2713aSLionel Sambuc } 1428*f4a2713aSLionel Sambuc 1429*f4a2713aSLionel Sambuc CheckNestedObjCContexts(AtLoc); 1430*f4a2713aSLionel Sambuc 1431*f4a2713aSLionel Sambuc if (Tok.is(tok::comma)) { // list of forward declarations. 1432*f4a2713aSLionel Sambuc SmallVector<IdentifierLocPair, 8> ProtocolRefs; 1433*f4a2713aSLionel Sambuc ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); 1434*f4a2713aSLionel Sambuc 1435*f4a2713aSLionel Sambuc // Parse the list of forward declarations. 1436*f4a2713aSLionel Sambuc while (1) { 1437*f4a2713aSLionel Sambuc ConsumeToken(); // the ',' 1438*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1439*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1440*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 1441*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1442*f4a2713aSLionel Sambuc } 1443*f4a2713aSLionel Sambuc ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(), 1444*f4a2713aSLionel Sambuc Tok.getLocation())); 1445*f4a2713aSLionel Sambuc ConsumeToken(); // the identifier 1446*f4a2713aSLionel Sambuc 1447*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 1448*f4a2713aSLionel Sambuc break; 1449*f4a2713aSLionel Sambuc } 1450*f4a2713aSLionel Sambuc // Consume the ';'. 1451*f4a2713aSLionel Sambuc if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol")) 1452*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1453*f4a2713aSLionel Sambuc 1454*f4a2713aSLionel Sambuc return Actions.ActOnForwardProtocolDeclaration(AtLoc, 1455*f4a2713aSLionel Sambuc &ProtocolRefs[0], 1456*f4a2713aSLionel Sambuc ProtocolRefs.size(), 1457*f4a2713aSLionel Sambuc attrs.getList()); 1458*f4a2713aSLionel Sambuc } 1459*f4a2713aSLionel Sambuc 1460*f4a2713aSLionel Sambuc // Last, and definitely not least, parse a protocol declaration. 1461*f4a2713aSLionel Sambuc SourceLocation LAngleLoc, EndProtoLoc; 1462*f4a2713aSLionel Sambuc 1463*f4a2713aSLionel Sambuc SmallVector<Decl *, 8> ProtocolRefs; 1464*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 8> ProtocolLocs; 1465*f4a2713aSLionel Sambuc if (Tok.is(tok::less) && 1466*f4a2713aSLionel Sambuc ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, 1467*f4a2713aSLionel Sambuc LAngleLoc, EndProtoLoc)) 1468*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1469*f4a2713aSLionel Sambuc 1470*f4a2713aSLionel Sambuc Decl *ProtoType = 1471*f4a2713aSLionel Sambuc Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, 1472*f4a2713aSLionel Sambuc ProtocolRefs.data(), 1473*f4a2713aSLionel Sambuc ProtocolRefs.size(), 1474*f4a2713aSLionel Sambuc ProtocolLocs.data(), 1475*f4a2713aSLionel Sambuc EndProtoLoc, attrs.getList()); 1476*f4a2713aSLionel Sambuc 1477*f4a2713aSLionel Sambuc ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); 1478*f4a2713aSLionel Sambuc return Actions.ConvertDeclToDeclGroup(ProtoType); 1479*f4a2713aSLionel Sambuc } 1480*f4a2713aSLionel Sambuc 1481*f4a2713aSLionel Sambuc /// objc-implementation: 1482*f4a2713aSLionel Sambuc /// objc-class-implementation-prologue 1483*f4a2713aSLionel Sambuc /// objc-category-implementation-prologue 1484*f4a2713aSLionel Sambuc /// 1485*f4a2713aSLionel Sambuc /// objc-class-implementation-prologue: 1486*f4a2713aSLionel Sambuc /// @implementation identifier objc-superclass[opt] 1487*f4a2713aSLionel Sambuc /// objc-class-instance-variables[opt] 1488*f4a2713aSLionel Sambuc /// 1489*f4a2713aSLionel Sambuc /// objc-category-implementation-prologue: 1490*f4a2713aSLionel Sambuc /// @implementation identifier ( identifier ) 1491*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy 1492*f4a2713aSLionel Sambuc Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { 1493*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_implementation) && 1494*f4a2713aSLionel Sambuc "ParseObjCAtImplementationDeclaration(): Expected @implementation"); 1495*f4a2713aSLionel Sambuc CheckNestedObjCContexts(AtLoc); 1496*f4a2713aSLionel Sambuc ConsumeToken(); // the "implementation" identifier 1497*f4a2713aSLionel Sambuc 1498*f4a2713aSLionel Sambuc // Code completion after '@implementation'. 1499*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1500*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCImplementationDecl(getCurScope()); 1501*f4a2713aSLionel Sambuc cutOffParsing(); 1502*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1503*f4a2713aSLionel Sambuc } 1504*f4a2713aSLionel Sambuc 1505*f4a2713aSLionel Sambuc MaybeSkipAttributes(tok::objc_implementation); 1506*f4a2713aSLionel Sambuc 1507*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1508*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing class or category name. 1509*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1510*f4a2713aSLionel Sambuc } 1511*f4a2713aSLionel Sambuc // We have a class or category name - consume it. 1512*f4a2713aSLionel Sambuc IdentifierInfo *nameId = Tok.getIdentifierInfo(); 1513*f4a2713aSLionel Sambuc SourceLocation nameLoc = ConsumeToken(); // consume class or category name 1514*f4a2713aSLionel Sambuc Decl *ObjCImpDecl = 0; 1515*f4a2713aSLionel Sambuc 1516*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) { 1517*f4a2713aSLionel Sambuc // we have a category implementation. 1518*f4a2713aSLionel Sambuc ConsumeParen(); 1519*f4a2713aSLionel Sambuc SourceLocation categoryLoc, rparenLoc; 1520*f4a2713aSLionel Sambuc IdentifierInfo *categoryId = 0; 1521*f4a2713aSLionel Sambuc 1522*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1523*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); 1524*f4a2713aSLionel Sambuc cutOffParsing(); 1525*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1526*f4a2713aSLionel Sambuc } 1527*f4a2713aSLionel Sambuc 1528*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier)) { 1529*f4a2713aSLionel Sambuc categoryId = Tok.getIdentifierInfo(); 1530*f4a2713aSLionel Sambuc categoryLoc = ConsumeToken(); 1531*f4a2713aSLionel Sambuc } else { 1532*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing category name. 1533*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1534*f4a2713aSLionel Sambuc } 1535*f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) { 1536*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_rparen); 1537*f4a2713aSLionel Sambuc SkipUntil(tok::r_paren); // don't stop at ';' 1538*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1539*f4a2713aSLionel Sambuc } 1540*f4a2713aSLionel Sambuc rparenLoc = ConsumeParen(); 1541*f4a2713aSLionel Sambuc if (Tok.is(tok::less)) { // we have illegal '<' try to recover 1542*f4a2713aSLionel Sambuc Diag(Tok, diag::err_unexpected_protocol_qualifier); 1543*f4a2713aSLionel Sambuc AttributeFactory attr; 1544*f4a2713aSLionel Sambuc DeclSpec DS(attr); 1545*f4a2713aSLionel Sambuc (void)ParseObjCProtocolQualifiers(DS); 1546*f4a2713aSLionel Sambuc } 1547*f4a2713aSLionel Sambuc ObjCImpDecl = Actions.ActOnStartCategoryImplementation( 1548*f4a2713aSLionel Sambuc AtLoc, nameId, nameLoc, categoryId, 1549*f4a2713aSLionel Sambuc categoryLoc); 1550*f4a2713aSLionel Sambuc 1551*f4a2713aSLionel Sambuc } else { 1552*f4a2713aSLionel Sambuc // We have a class implementation 1553*f4a2713aSLionel Sambuc SourceLocation superClassLoc; 1554*f4a2713aSLionel Sambuc IdentifierInfo *superClassId = 0; 1555*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { 1556*f4a2713aSLionel Sambuc // We have a super class 1557*f4a2713aSLionel Sambuc ConsumeToken(); 1558*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1559*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing super class name. 1560*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1561*f4a2713aSLionel Sambuc } 1562*f4a2713aSLionel Sambuc superClassId = Tok.getIdentifierInfo(); 1563*f4a2713aSLionel Sambuc superClassLoc = ConsumeToken(); // Consume super class name 1564*f4a2713aSLionel Sambuc } 1565*f4a2713aSLionel Sambuc ObjCImpDecl = Actions.ActOnStartClassImplementation( 1566*f4a2713aSLionel Sambuc AtLoc, nameId, nameLoc, 1567*f4a2713aSLionel Sambuc superClassId, superClassLoc); 1568*f4a2713aSLionel Sambuc 1569*f4a2713aSLionel Sambuc if (Tok.is(tok::l_brace)) // we have ivars 1570*f4a2713aSLionel Sambuc ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc); 1571*f4a2713aSLionel Sambuc else if (Tok.is(tok::less)) { // we have illegal '<' try to recover 1572*f4a2713aSLionel Sambuc Diag(Tok, diag::err_unexpected_protocol_qualifier); 1573*f4a2713aSLionel Sambuc // try to recover. 1574*f4a2713aSLionel Sambuc AttributeFactory attr; 1575*f4a2713aSLionel Sambuc DeclSpec DS(attr); 1576*f4a2713aSLionel Sambuc (void)ParseObjCProtocolQualifiers(DS); 1577*f4a2713aSLionel Sambuc } 1578*f4a2713aSLionel Sambuc } 1579*f4a2713aSLionel Sambuc assert(ObjCImpDecl); 1580*f4a2713aSLionel Sambuc 1581*f4a2713aSLionel Sambuc SmallVector<Decl *, 8> DeclsInGroup; 1582*f4a2713aSLionel Sambuc 1583*f4a2713aSLionel Sambuc { 1584*f4a2713aSLionel Sambuc ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); 1585*f4a2713aSLionel Sambuc while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) { 1586*f4a2713aSLionel Sambuc ParsedAttributesWithRange attrs(AttrFactory); 1587*f4a2713aSLionel Sambuc MaybeParseCXX11Attributes(attrs); 1588*f4a2713aSLionel Sambuc MaybeParseMicrosoftAttributes(attrs); 1589*f4a2713aSLionel Sambuc if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) { 1590*f4a2713aSLionel Sambuc DeclGroupRef DG = DGP.get(); 1591*f4a2713aSLionel Sambuc DeclsInGroup.append(DG.begin(), DG.end()); 1592*f4a2713aSLionel Sambuc } 1593*f4a2713aSLionel Sambuc } 1594*f4a2713aSLionel Sambuc } 1595*f4a2713aSLionel Sambuc 1596*f4a2713aSLionel Sambuc return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup); 1597*f4a2713aSLionel Sambuc } 1598*f4a2713aSLionel Sambuc 1599*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy 1600*f4a2713aSLionel Sambuc Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { 1601*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_end) && 1602*f4a2713aSLionel Sambuc "ParseObjCAtEndDeclaration(): Expected @end"); 1603*f4a2713aSLionel Sambuc ConsumeToken(); // the "end" identifier 1604*f4a2713aSLionel Sambuc if (CurParsedObjCImpl) 1605*f4a2713aSLionel Sambuc CurParsedObjCImpl->finish(atEnd); 1606*f4a2713aSLionel Sambuc else 1607*f4a2713aSLionel Sambuc // missing @implementation 1608*f4a2713aSLionel Sambuc Diag(atEnd.getBegin(), diag::err_expected_objc_container); 1609*f4a2713aSLionel Sambuc return DeclGroupPtrTy(); 1610*f4a2713aSLionel Sambuc } 1611*f4a2713aSLionel Sambuc 1612*f4a2713aSLionel Sambuc Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { 1613*f4a2713aSLionel Sambuc if (!Finished) { 1614*f4a2713aSLionel Sambuc finish(P.Tok.getLocation()); 1615*f4a2713aSLionel Sambuc if (P.Tok.is(tok::eof)) { 1616*f4a2713aSLionel Sambuc P.Diag(P.Tok, diag::err_objc_missing_end) 1617*f4a2713aSLionel Sambuc << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); 1618*f4a2713aSLionel Sambuc P.Diag(Dcl->getLocStart(), diag::note_objc_container_start) 1619*f4a2713aSLionel Sambuc << Sema::OCK_Implementation; 1620*f4a2713aSLionel Sambuc } 1621*f4a2713aSLionel Sambuc } 1622*f4a2713aSLionel Sambuc P.CurParsedObjCImpl = 0; 1623*f4a2713aSLionel Sambuc assert(LateParsedObjCMethods.empty()); 1624*f4a2713aSLionel Sambuc } 1625*f4a2713aSLionel Sambuc 1626*f4a2713aSLionel Sambuc void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { 1627*f4a2713aSLionel Sambuc assert(!Finished); 1628*f4a2713aSLionel Sambuc P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl); 1629*f4a2713aSLionel Sambuc for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) 1630*f4a2713aSLionel Sambuc P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 1631*f4a2713aSLionel Sambuc true/*Methods*/); 1632*f4a2713aSLionel Sambuc 1633*f4a2713aSLionel Sambuc P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd); 1634*f4a2713aSLionel Sambuc 1635*f4a2713aSLionel Sambuc if (HasCFunction) 1636*f4a2713aSLionel Sambuc for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) 1637*f4a2713aSLionel Sambuc P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 1638*f4a2713aSLionel Sambuc false/*c-functions*/); 1639*f4a2713aSLionel Sambuc 1640*f4a2713aSLionel Sambuc /// \brief Clear and free the cached objc methods. 1641*f4a2713aSLionel Sambuc for (LateParsedObjCMethodContainer::iterator 1642*f4a2713aSLionel Sambuc I = LateParsedObjCMethods.begin(), 1643*f4a2713aSLionel Sambuc E = LateParsedObjCMethods.end(); I != E; ++I) 1644*f4a2713aSLionel Sambuc delete *I; 1645*f4a2713aSLionel Sambuc LateParsedObjCMethods.clear(); 1646*f4a2713aSLionel Sambuc 1647*f4a2713aSLionel Sambuc Finished = true; 1648*f4a2713aSLionel Sambuc } 1649*f4a2713aSLionel Sambuc 1650*f4a2713aSLionel Sambuc /// compatibility-alias-decl: 1651*f4a2713aSLionel Sambuc /// @compatibility_alias alias-name class-name ';' 1652*f4a2713aSLionel Sambuc /// 1653*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { 1654*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && 1655*f4a2713aSLionel Sambuc "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); 1656*f4a2713aSLionel Sambuc ConsumeToken(); // consume compatibility_alias 1657*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1658*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1659*f4a2713aSLionel Sambuc return 0; 1660*f4a2713aSLionel Sambuc } 1661*f4a2713aSLionel Sambuc IdentifierInfo *aliasId = Tok.getIdentifierInfo(); 1662*f4a2713aSLionel Sambuc SourceLocation aliasLoc = ConsumeToken(); // consume alias-name 1663*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1664*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1665*f4a2713aSLionel Sambuc return 0; 1666*f4a2713aSLionel Sambuc } 1667*f4a2713aSLionel Sambuc IdentifierInfo *classId = Tok.getIdentifierInfo(); 1668*f4a2713aSLionel Sambuc SourceLocation classLoc = ConsumeToken(); // consume class-name; 1669*f4a2713aSLionel Sambuc ExpectAndConsume(tok::semi, diag::err_expected_semi_after, 1670*f4a2713aSLionel Sambuc "@compatibility_alias"); 1671*f4a2713aSLionel Sambuc return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, 1672*f4a2713aSLionel Sambuc classId, classLoc); 1673*f4a2713aSLionel Sambuc } 1674*f4a2713aSLionel Sambuc 1675*f4a2713aSLionel Sambuc /// property-synthesis: 1676*f4a2713aSLionel Sambuc /// @synthesize property-ivar-list ';' 1677*f4a2713aSLionel Sambuc /// 1678*f4a2713aSLionel Sambuc /// property-ivar-list: 1679*f4a2713aSLionel Sambuc /// property-ivar 1680*f4a2713aSLionel Sambuc /// property-ivar-list ',' property-ivar 1681*f4a2713aSLionel Sambuc /// 1682*f4a2713aSLionel Sambuc /// property-ivar: 1683*f4a2713aSLionel Sambuc /// identifier 1684*f4a2713aSLionel Sambuc /// identifier '=' identifier 1685*f4a2713aSLionel Sambuc /// 1686*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { 1687*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && 1688*f4a2713aSLionel Sambuc "ParseObjCPropertySynthesize(): Expected '@synthesize'"); 1689*f4a2713aSLionel Sambuc ConsumeToken(); // consume synthesize 1690*f4a2713aSLionel Sambuc 1691*f4a2713aSLionel Sambuc while (true) { 1692*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1693*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); 1694*f4a2713aSLionel Sambuc cutOffParsing(); 1695*f4a2713aSLionel Sambuc return 0; 1696*f4a2713aSLionel Sambuc } 1697*f4a2713aSLionel Sambuc 1698*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1699*f4a2713aSLionel Sambuc Diag(Tok, diag::err_synthesized_property_name); 1700*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 1701*f4a2713aSLionel Sambuc return 0; 1702*f4a2713aSLionel Sambuc } 1703*f4a2713aSLionel Sambuc 1704*f4a2713aSLionel Sambuc IdentifierInfo *propertyIvar = 0; 1705*f4a2713aSLionel Sambuc IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1706*f4a2713aSLionel Sambuc SourceLocation propertyLoc = ConsumeToken(); // consume property name 1707*f4a2713aSLionel Sambuc SourceLocation propertyIvarLoc; 1708*f4a2713aSLionel Sambuc if (Tok.is(tok::equal)) { 1709*f4a2713aSLionel Sambuc // property '=' ivar-name 1710*f4a2713aSLionel Sambuc ConsumeToken(); // consume '=' 1711*f4a2713aSLionel Sambuc 1712*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1713*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); 1714*f4a2713aSLionel Sambuc cutOffParsing(); 1715*f4a2713aSLionel Sambuc return 0; 1716*f4a2713aSLionel Sambuc } 1717*f4a2713aSLionel Sambuc 1718*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1719*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1720*f4a2713aSLionel Sambuc break; 1721*f4a2713aSLionel Sambuc } 1722*f4a2713aSLionel Sambuc propertyIvar = Tok.getIdentifierInfo(); 1723*f4a2713aSLionel Sambuc propertyIvarLoc = ConsumeToken(); // consume ivar-name 1724*f4a2713aSLionel Sambuc } 1725*f4a2713aSLionel Sambuc Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, 1726*f4a2713aSLionel Sambuc propertyId, propertyIvar, propertyIvarLoc); 1727*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 1728*f4a2713aSLionel Sambuc break; 1729*f4a2713aSLionel Sambuc ConsumeToken(); // consume ',' 1730*f4a2713aSLionel Sambuc } 1731*f4a2713aSLionel Sambuc ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize"); 1732*f4a2713aSLionel Sambuc return 0; 1733*f4a2713aSLionel Sambuc } 1734*f4a2713aSLionel Sambuc 1735*f4a2713aSLionel Sambuc /// property-dynamic: 1736*f4a2713aSLionel Sambuc /// @dynamic property-list 1737*f4a2713aSLionel Sambuc /// 1738*f4a2713aSLionel Sambuc /// property-list: 1739*f4a2713aSLionel Sambuc /// identifier 1740*f4a2713aSLionel Sambuc /// property-list ',' identifier 1741*f4a2713aSLionel Sambuc /// 1742*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { 1743*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && 1744*f4a2713aSLionel Sambuc "ParseObjCPropertyDynamic(): Expected '@dynamic'"); 1745*f4a2713aSLionel Sambuc ConsumeToken(); // consume dynamic 1746*f4a2713aSLionel Sambuc while (true) { 1747*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 1748*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); 1749*f4a2713aSLionel Sambuc cutOffParsing(); 1750*f4a2713aSLionel Sambuc return 0; 1751*f4a2713aSLionel Sambuc } 1752*f4a2713aSLionel Sambuc 1753*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) { 1754*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); 1755*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 1756*f4a2713aSLionel Sambuc return 0; 1757*f4a2713aSLionel Sambuc } 1758*f4a2713aSLionel Sambuc 1759*f4a2713aSLionel Sambuc IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1760*f4a2713aSLionel Sambuc SourceLocation propertyLoc = ConsumeToken(); // consume property name 1761*f4a2713aSLionel Sambuc Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, 1762*f4a2713aSLionel Sambuc propertyId, 0, SourceLocation()); 1763*f4a2713aSLionel Sambuc 1764*f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) 1765*f4a2713aSLionel Sambuc break; 1766*f4a2713aSLionel Sambuc ConsumeToken(); // consume ',' 1767*f4a2713aSLionel Sambuc } 1768*f4a2713aSLionel Sambuc ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic"); 1769*f4a2713aSLionel Sambuc return 0; 1770*f4a2713aSLionel Sambuc } 1771*f4a2713aSLionel Sambuc 1772*f4a2713aSLionel Sambuc /// objc-throw-statement: 1773*f4a2713aSLionel Sambuc /// throw expression[opt]; 1774*f4a2713aSLionel Sambuc /// 1775*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { 1776*f4a2713aSLionel Sambuc ExprResult Res; 1777*f4a2713aSLionel Sambuc ConsumeToken(); // consume throw 1778*f4a2713aSLionel Sambuc if (Tok.isNot(tok::semi)) { 1779*f4a2713aSLionel Sambuc Res = ParseExpression(); 1780*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 1781*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 1782*f4a2713aSLionel Sambuc return StmtError(); 1783*f4a2713aSLionel Sambuc } 1784*f4a2713aSLionel Sambuc } 1785*f4a2713aSLionel Sambuc // consume ';' 1786*f4a2713aSLionel Sambuc ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw"); 1787*f4a2713aSLionel Sambuc return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope()); 1788*f4a2713aSLionel Sambuc } 1789*f4a2713aSLionel Sambuc 1790*f4a2713aSLionel Sambuc /// objc-synchronized-statement: 1791*f4a2713aSLionel Sambuc /// @synchronized '(' expression ')' compound-statement 1792*f4a2713aSLionel Sambuc /// 1793*f4a2713aSLionel Sambuc StmtResult 1794*f4a2713aSLionel Sambuc Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { 1795*f4a2713aSLionel Sambuc ConsumeToken(); // consume synchronized 1796*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) { 1797*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; 1798*f4a2713aSLionel Sambuc return StmtError(); 1799*f4a2713aSLionel Sambuc } 1800*f4a2713aSLionel Sambuc 1801*f4a2713aSLionel Sambuc // The operand is surrounded with parentheses. 1802*f4a2713aSLionel Sambuc ConsumeParen(); // '(' 1803*f4a2713aSLionel Sambuc ExprResult operand(ParseExpression()); 1804*f4a2713aSLionel Sambuc 1805*f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren)) { 1806*f4a2713aSLionel Sambuc ConsumeParen(); // ')' 1807*f4a2713aSLionel Sambuc } else { 1808*f4a2713aSLionel Sambuc if (!operand.isInvalid()) 1809*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_rparen); 1810*f4a2713aSLionel Sambuc 1811*f4a2713aSLionel Sambuc // Skip forward until we see a left brace, but don't consume it. 1812*f4a2713aSLionel Sambuc SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); 1813*f4a2713aSLionel Sambuc } 1814*f4a2713aSLionel Sambuc 1815*f4a2713aSLionel Sambuc // Require a compound statement. 1816*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_brace)) { 1817*f4a2713aSLionel Sambuc if (!operand.isInvalid()) 1818*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lbrace); 1819*f4a2713aSLionel Sambuc return StmtError(); 1820*f4a2713aSLionel Sambuc } 1821*f4a2713aSLionel Sambuc 1822*f4a2713aSLionel Sambuc // Check the @synchronized operand now. 1823*f4a2713aSLionel Sambuc if (!operand.isInvalid()) 1824*f4a2713aSLionel Sambuc operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take()); 1825*f4a2713aSLionel Sambuc 1826*f4a2713aSLionel Sambuc // Parse the compound statement within a new scope. 1827*f4a2713aSLionel Sambuc ParseScope bodyScope(this, Scope::DeclScope); 1828*f4a2713aSLionel Sambuc StmtResult body(ParseCompoundStatementBody()); 1829*f4a2713aSLionel Sambuc bodyScope.Exit(); 1830*f4a2713aSLionel Sambuc 1831*f4a2713aSLionel Sambuc // If there was a semantic or parse error earlier with the 1832*f4a2713aSLionel Sambuc // operand, fail now. 1833*f4a2713aSLionel Sambuc if (operand.isInvalid()) 1834*f4a2713aSLionel Sambuc return StmtError(); 1835*f4a2713aSLionel Sambuc 1836*f4a2713aSLionel Sambuc if (body.isInvalid()) 1837*f4a2713aSLionel Sambuc body = Actions.ActOnNullStmt(Tok.getLocation()); 1838*f4a2713aSLionel Sambuc 1839*f4a2713aSLionel Sambuc return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get()); 1840*f4a2713aSLionel Sambuc } 1841*f4a2713aSLionel Sambuc 1842*f4a2713aSLionel Sambuc /// objc-try-catch-statement: 1843*f4a2713aSLionel Sambuc /// @try compound-statement objc-catch-list[opt] 1844*f4a2713aSLionel Sambuc /// @try compound-statement objc-catch-list[opt] @finally compound-statement 1845*f4a2713aSLionel Sambuc /// 1846*f4a2713aSLionel Sambuc /// objc-catch-list: 1847*f4a2713aSLionel Sambuc /// @catch ( parameter-declaration ) compound-statement 1848*f4a2713aSLionel Sambuc /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement 1849*f4a2713aSLionel Sambuc /// catch-parameter-declaration: 1850*f4a2713aSLionel Sambuc /// parameter-declaration 1851*f4a2713aSLionel Sambuc /// '...' [OBJC2] 1852*f4a2713aSLionel Sambuc /// 1853*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { 1854*f4a2713aSLionel Sambuc bool catch_or_finally_seen = false; 1855*f4a2713aSLionel Sambuc 1856*f4a2713aSLionel Sambuc ConsumeToken(); // consume try 1857*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_brace)) { 1858*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lbrace); 1859*f4a2713aSLionel Sambuc return StmtError(); 1860*f4a2713aSLionel Sambuc } 1861*f4a2713aSLionel Sambuc StmtVector CatchStmts; 1862*f4a2713aSLionel Sambuc StmtResult FinallyStmt; 1863*f4a2713aSLionel Sambuc ParseScope TryScope(this, Scope::DeclScope); 1864*f4a2713aSLionel Sambuc StmtResult TryBody(ParseCompoundStatementBody()); 1865*f4a2713aSLionel Sambuc TryScope.Exit(); 1866*f4a2713aSLionel Sambuc if (TryBody.isInvalid()) 1867*f4a2713aSLionel Sambuc TryBody = Actions.ActOnNullStmt(Tok.getLocation()); 1868*f4a2713aSLionel Sambuc 1869*f4a2713aSLionel Sambuc while (Tok.is(tok::at)) { 1870*f4a2713aSLionel Sambuc // At this point, we need to lookahead to determine if this @ is the start 1871*f4a2713aSLionel Sambuc // of an @catch or @finally. We don't want to consume the @ token if this 1872*f4a2713aSLionel Sambuc // is an @try or @encode or something else. 1873*f4a2713aSLionel Sambuc Token AfterAt = GetLookAheadToken(1); 1874*f4a2713aSLionel Sambuc if (!AfterAt.isObjCAtKeyword(tok::objc_catch) && 1875*f4a2713aSLionel Sambuc !AfterAt.isObjCAtKeyword(tok::objc_finally)) 1876*f4a2713aSLionel Sambuc break; 1877*f4a2713aSLionel Sambuc 1878*f4a2713aSLionel Sambuc SourceLocation AtCatchFinallyLoc = ConsumeToken(); 1879*f4a2713aSLionel Sambuc if (Tok.isObjCAtKeyword(tok::objc_catch)) { 1880*f4a2713aSLionel Sambuc Decl *FirstPart = 0; 1881*f4a2713aSLionel Sambuc ConsumeToken(); // consume catch 1882*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) { 1883*f4a2713aSLionel Sambuc ConsumeParen(); 1884*f4a2713aSLionel Sambuc ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope); 1885*f4a2713aSLionel Sambuc if (Tok.isNot(tok::ellipsis)) { 1886*f4a2713aSLionel Sambuc DeclSpec DS(AttrFactory); 1887*f4a2713aSLionel Sambuc ParseDeclarationSpecifiers(DS); 1888*f4a2713aSLionel Sambuc Declarator ParmDecl(DS, Declarator::ObjCCatchContext); 1889*f4a2713aSLionel Sambuc ParseDeclarator(ParmDecl); 1890*f4a2713aSLionel Sambuc 1891*f4a2713aSLionel Sambuc // Inform the actions module about the declarator, so it 1892*f4a2713aSLionel Sambuc // gets added to the current scope. 1893*f4a2713aSLionel Sambuc FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl); 1894*f4a2713aSLionel Sambuc } else 1895*f4a2713aSLionel Sambuc ConsumeToken(); // consume '...' 1896*f4a2713aSLionel Sambuc 1897*f4a2713aSLionel Sambuc SourceLocation RParenLoc; 1898*f4a2713aSLionel Sambuc 1899*f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren)) 1900*f4a2713aSLionel Sambuc RParenLoc = ConsumeParen(); 1901*f4a2713aSLionel Sambuc else // Skip over garbage, until we get to ')'. Eat the ')'. 1902*f4a2713aSLionel Sambuc SkipUntil(tok::r_paren, StopAtSemi); 1903*f4a2713aSLionel Sambuc 1904*f4a2713aSLionel Sambuc StmtResult CatchBody(true); 1905*f4a2713aSLionel Sambuc if (Tok.is(tok::l_brace)) 1906*f4a2713aSLionel Sambuc CatchBody = ParseCompoundStatementBody(); 1907*f4a2713aSLionel Sambuc else 1908*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lbrace); 1909*f4a2713aSLionel Sambuc if (CatchBody.isInvalid()) 1910*f4a2713aSLionel Sambuc CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); 1911*f4a2713aSLionel Sambuc 1912*f4a2713aSLionel Sambuc StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, 1913*f4a2713aSLionel Sambuc RParenLoc, 1914*f4a2713aSLionel Sambuc FirstPart, 1915*f4a2713aSLionel Sambuc CatchBody.take()); 1916*f4a2713aSLionel Sambuc if (!Catch.isInvalid()) 1917*f4a2713aSLionel Sambuc CatchStmts.push_back(Catch.release()); 1918*f4a2713aSLionel Sambuc 1919*f4a2713aSLionel Sambuc } else { 1920*f4a2713aSLionel Sambuc Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) 1921*f4a2713aSLionel Sambuc << "@catch clause"; 1922*f4a2713aSLionel Sambuc return StmtError(); 1923*f4a2713aSLionel Sambuc } 1924*f4a2713aSLionel Sambuc catch_or_finally_seen = true; 1925*f4a2713aSLionel Sambuc } else { 1926*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); 1927*f4a2713aSLionel Sambuc ConsumeToken(); // consume finally 1928*f4a2713aSLionel Sambuc ParseScope FinallyScope(this, Scope::DeclScope); 1929*f4a2713aSLionel Sambuc 1930*f4a2713aSLionel Sambuc StmtResult FinallyBody(true); 1931*f4a2713aSLionel Sambuc if (Tok.is(tok::l_brace)) 1932*f4a2713aSLionel Sambuc FinallyBody = ParseCompoundStatementBody(); 1933*f4a2713aSLionel Sambuc else 1934*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lbrace); 1935*f4a2713aSLionel Sambuc if (FinallyBody.isInvalid()) 1936*f4a2713aSLionel Sambuc FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); 1937*f4a2713aSLionel Sambuc FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, 1938*f4a2713aSLionel Sambuc FinallyBody.take()); 1939*f4a2713aSLionel Sambuc catch_or_finally_seen = true; 1940*f4a2713aSLionel Sambuc break; 1941*f4a2713aSLionel Sambuc } 1942*f4a2713aSLionel Sambuc } 1943*f4a2713aSLionel Sambuc if (!catch_or_finally_seen) { 1944*f4a2713aSLionel Sambuc Diag(atLoc, diag::err_missing_catch_finally); 1945*f4a2713aSLionel Sambuc return StmtError(); 1946*f4a2713aSLionel Sambuc } 1947*f4a2713aSLionel Sambuc 1948*f4a2713aSLionel Sambuc return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(), 1949*f4a2713aSLionel Sambuc CatchStmts, 1950*f4a2713aSLionel Sambuc FinallyStmt.take()); 1951*f4a2713aSLionel Sambuc } 1952*f4a2713aSLionel Sambuc 1953*f4a2713aSLionel Sambuc /// objc-autoreleasepool-statement: 1954*f4a2713aSLionel Sambuc /// @autoreleasepool compound-statement 1955*f4a2713aSLionel Sambuc /// 1956*f4a2713aSLionel Sambuc StmtResult 1957*f4a2713aSLionel Sambuc Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { 1958*f4a2713aSLionel Sambuc ConsumeToken(); // consume autoreleasepool 1959*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_brace)) { 1960*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_lbrace); 1961*f4a2713aSLionel Sambuc return StmtError(); 1962*f4a2713aSLionel Sambuc } 1963*f4a2713aSLionel Sambuc // Enter a scope to hold everything within the compound stmt. Compound 1964*f4a2713aSLionel Sambuc // statements can always hold declarations. 1965*f4a2713aSLionel Sambuc ParseScope BodyScope(this, Scope::DeclScope); 1966*f4a2713aSLionel Sambuc 1967*f4a2713aSLionel Sambuc StmtResult AutoreleasePoolBody(ParseCompoundStatementBody()); 1968*f4a2713aSLionel Sambuc 1969*f4a2713aSLionel Sambuc BodyScope.Exit(); 1970*f4a2713aSLionel Sambuc if (AutoreleasePoolBody.isInvalid()) 1971*f4a2713aSLionel Sambuc AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation()); 1972*f4a2713aSLionel Sambuc return Actions.ActOnObjCAutoreleasePoolStmt(atLoc, 1973*f4a2713aSLionel Sambuc AutoreleasePoolBody.take()); 1974*f4a2713aSLionel Sambuc } 1975*f4a2713aSLionel Sambuc 1976*f4a2713aSLionel Sambuc /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them 1977*f4a2713aSLionel Sambuc /// for later parsing. 1978*f4a2713aSLionel Sambuc void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { 1979*f4a2713aSLionel Sambuc LexedMethod* LM = new LexedMethod(this, MDecl); 1980*f4a2713aSLionel Sambuc CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); 1981*f4a2713aSLionel Sambuc CachedTokens &Toks = LM->Toks; 1982*f4a2713aSLionel Sambuc // Begin by storing the '{' or 'try' or ':' token. 1983*f4a2713aSLionel Sambuc Toks.push_back(Tok); 1984*f4a2713aSLionel Sambuc if (Tok.is(tok::kw_try)) { 1985*f4a2713aSLionel Sambuc ConsumeToken(); 1986*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { 1987*f4a2713aSLionel Sambuc Toks.push_back(Tok); 1988*f4a2713aSLionel Sambuc ConsumeToken(); 1989*f4a2713aSLionel Sambuc while (Tok.isNot(tok::l_brace)) { 1990*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); 1991*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 1992*f4a2713aSLionel Sambuc } 1993*f4a2713aSLionel Sambuc } 1994*f4a2713aSLionel Sambuc Toks.push_back(Tok); // also store '{' 1995*f4a2713aSLionel Sambuc } 1996*f4a2713aSLionel Sambuc else if (Tok.is(tok::colon)) { 1997*f4a2713aSLionel Sambuc ConsumeToken(); 1998*f4a2713aSLionel Sambuc while (Tok.isNot(tok::l_brace)) { 1999*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); 2000*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 2001*f4a2713aSLionel Sambuc } 2002*f4a2713aSLionel Sambuc Toks.push_back(Tok); // also store '{' 2003*f4a2713aSLionel Sambuc } 2004*f4a2713aSLionel Sambuc ConsumeBrace(); 2005*f4a2713aSLionel Sambuc // Consume everything up to (and including) the matching right brace. 2006*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 2007*f4a2713aSLionel Sambuc while (Tok.is(tok::kw_catch)) { 2008*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 2009*f4a2713aSLionel Sambuc ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 2010*f4a2713aSLionel Sambuc } 2011*f4a2713aSLionel Sambuc } 2012*f4a2713aSLionel Sambuc 2013*f4a2713aSLionel Sambuc /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' 2014*f4a2713aSLionel Sambuc /// 2015*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDefinition() { 2016*f4a2713aSLionel Sambuc Decl *MDecl = ParseObjCMethodPrototype(); 2017*f4a2713aSLionel Sambuc 2018*f4a2713aSLionel Sambuc PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(), 2019*f4a2713aSLionel Sambuc "parsing Objective-C method"); 2020*f4a2713aSLionel Sambuc 2021*f4a2713aSLionel Sambuc // parse optional ';' 2022*f4a2713aSLionel Sambuc if (Tok.is(tok::semi)) { 2023*f4a2713aSLionel Sambuc if (CurParsedObjCImpl) { 2024*f4a2713aSLionel Sambuc Diag(Tok, diag::warn_semicolon_before_method_body) 2025*f4a2713aSLionel Sambuc << FixItHint::CreateRemoval(Tok.getLocation()); 2026*f4a2713aSLionel Sambuc } 2027*f4a2713aSLionel Sambuc ConsumeToken(); 2028*f4a2713aSLionel Sambuc } 2029*f4a2713aSLionel Sambuc 2030*f4a2713aSLionel Sambuc // We should have an opening brace now. 2031*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_brace)) { 2032*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_method_body); 2033*f4a2713aSLionel Sambuc 2034*f4a2713aSLionel Sambuc // Skip over garbage, until we get to '{'. Don't eat the '{'. 2035*f4a2713aSLionel Sambuc SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); 2036*f4a2713aSLionel Sambuc 2037*f4a2713aSLionel Sambuc // If we didn't find the '{', bail out. 2038*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_brace)) 2039*f4a2713aSLionel Sambuc return 0; 2040*f4a2713aSLionel Sambuc } 2041*f4a2713aSLionel Sambuc 2042*f4a2713aSLionel Sambuc if (!MDecl) { 2043*f4a2713aSLionel Sambuc ConsumeBrace(); 2044*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace); 2045*f4a2713aSLionel Sambuc return 0; 2046*f4a2713aSLionel Sambuc } 2047*f4a2713aSLionel Sambuc 2048*f4a2713aSLionel Sambuc // Allow the rest of sema to find private method decl implementations. 2049*f4a2713aSLionel Sambuc Actions.AddAnyMethodToGlobalPool(MDecl); 2050*f4a2713aSLionel Sambuc assert (CurParsedObjCImpl 2051*f4a2713aSLionel Sambuc && "ParseObjCMethodDefinition - Method out of @implementation"); 2052*f4a2713aSLionel Sambuc // Consume the tokens and store them for later parsing. 2053*f4a2713aSLionel Sambuc StashAwayMethodOrFunctionBodyTokens(MDecl); 2054*f4a2713aSLionel Sambuc return MDecl; 2055*f4a2713aSLionel Sambuc } 2056*f4a2713aSLionel Sambuc 2057*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { 2058*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2059*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtStatement(getCurScope()); 2060*f4a2713aSLionel Sambuc cutOffParsing(); 2061*f4a2713aSLionel Sambuc return StmtError(); 2062*f4a2713aSLionel Sambuc } 2063*f4a2713aSLionel Sambuc 2064*f4a2713aSLionel Sambuc if (Tok.isObjCAtKeyword(tok::objc_try)) 2065*f4a2713aSLionel Sambuc return ParseObjCTryStmt(AtLoc); 2066*f4a2713aSLionel Sambuc 2067*f4a2713aSLionel Sambuc if (Tok.isObjCAtKeyword(tok::objc_throw)) 2068*f4a2713aSLionel Sambuc return ParseObjCThrowStmt(AtLoc); 2069*f4a2713aSLionel Sambuc 2070*f4a2713aSLionel Sambuc if (Tok.isObjCAtKeyword(tok::objc_synchronized)) 2071*f4a2713aSLionel Sambuc return ParseObjCSynchronizedStmt(AtLoc); 2072*f4a2713aSLionel Sambuc 2073*f4a2713aSLionel Sambuc if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool)) 2074*f4a2713aSLionel Sambuc return ParseObjCAutoreleasePoolStmt(AtLoc); 2075*f4a2713aSLionel Sambuc 2076*f4a2713aSLionel Sambuc ExprResult Res(ParseExpressionWithLeadingAt(AtLoc)); 2077*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 2078*f4a2713aSLionel Sambuc // If the expression is invalid, skip ahead to the next semicolon. Not 2079*f4a2713aSLionel Sambuc // doing this opens us up to the possibility of infinite loops if 2080*f4a2713aSLionel Sambuc // ParseExpression does not consume any tokens. 2081*f4a2713aSLionel Sambuc SkipUntil(tok::semi); 2082*f4a2713aSLionel Sambuc return StmtError(); 2083*f4a2713aSLionel Sambuc } 2084*f4a2713aSLionel Sambuc 2085*f4a2713aSLionel Sambuc // Otherwise, eat the semicolon. 2086*f4a2713aSLionel Sambuc ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); 2087*f4a2713aSLionel Sambuc return Actions.ActOnExprStmt(Res); 2088*f4a2713aSLionel Sambuc } 2089*f4a2713aSLionel Sambuc 2090*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { 2091*f4a2713aSLionel Sambuc switch (Tok.getKind()) { 2092*f4a2713aSLionel Sambuc case tok::code_completion: 2093*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCAtExpression(getCurScope()); 2094*f4a2713aSLionel Sambuc cutOffParsing(); 2095*f4a2713aSLionel Sambuc return ExprError(); 2096*f4a2713aSLionel Sambuc 2097*f4a2713aSLionel Sambuc case tok::minus: 2098*f4a2713aSLionel Sambuc case tok::plus: { 2099*f4a2713aSLionel Sambuc tok::TokenKind Kind = Tok.getKind(); 2100*f4a2713aSLionel Sambuc SourceLocation OpLoc = ConsumeToken(); 2101*f4a2713aSLionel Sambuc 2102*f4a2713aSLionel Sambuc if (!Tok.is(tok::numeric_constant)) { 2103*f4a2713aSLionel Sambuc const char *Symbol = 0; 2104*f4a2713aSLionel Sambuc switch (Kind) { 2105*f4a2713aSLionel Sambuc case tok::minus: Symbol = "-"; break; 2106*f4a2713aSLionel Sambuc case tok::plus: Symbol = "+"; break; 2107*f4a2713aSLionel Sambuc default: llvm_unreachable("missing unary operator case"); 2108*f4a2713aSLionel Sambuc } 2109*f4a2713aSLionel Sambuc Diag(Tok, diag::err_nsnumber_nonliteral_unary) 2110*f4a2713aSLionel Sambuc << Symbol; 2111*f4a2713aSLionel Sambuc return ExprError(); 2112*f4a2713aSLionel Sambuc } 2113*f4a2713aSLionel Sambuc 2114*f4a2713aSLionel Sambuc ExprResult Lit(Actions.ActOnNumericConstant(Tok)); 2115*f4a2713aSLionel Sambuc if (Lit.isInvalid()) { 2116*f4a2713aSLionel Sambuc return Lit; 2117*f4a2713aSLionel Sambuc } 2118*f4a2713aSLionel Sambuc ConsumeToken(); // Consume the literal token. 2119*f4a2713aSLionel Sambuc 2120*f4a2713aSLionel Sambuc Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take()); 2121*f4a2713aSLionel Sambuc if (Lit.isInvalid()) 2122*f4a2713aSLionel Sambuc return Lit; 2123*f4a2713aSLionel Sambuc 2124*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix( 2125*f4a2713aSLionel Sambuc Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); 2126*f4a2713aSLionel Sambuc } 2127*f4a2713aSLionel Sambuc 2128*f4a2713aSLionel Sambuc case tok::string_literal: // primary-expression: string-literal 2129*f4a2713aSLionel Sambuc case tok::wide_string_literal: 2130*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc)); 2131*f4a2713aSLionel Sambuc 2132*f4a2713aSLionel Sambuc case tok::char_constant: 2133*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc)); 2134*f4a2713aSLionel Sambuc 2135*f4a2713aSLionel Sambuc case tok::numeric_constant: 2136*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc)); 2137*f4a2713aSLionel Sambuc 2138*f4a2713aSLionel Sambuc case tok::kw_true: // Objective-C++, etc. 2139*f4a2713aSLionel Sambuc case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes 2140*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true)); 2141*f4a2713aSLionel Sambuc case tok::kw_false: // Objective-C++, etc. 2142*f4a2713aSLionel Sambuc case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no 2143*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false)); 2144*f4a2713aSLionel Sambuc 2145*f4a2713aSLionel Sambuc case tok::l_square: 2146*f4a2713aSLionel Sambuc // Objective-C array literal 2147*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc)); 2148*f4a2713aSLionel Sambuc 2149*f4a2713aSLionel Sambuc case tok::l_brace: 2150*f4a2713aSLionel Sambuc // Objective-C dictionary literal 2151*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc)); 2152*f4a2713aSLionel Sambuc 2153*f4a2713aSLionel Sambuc case tok::l_paren: 2154*f4a2713aSLionel Sambuc // Objective-C boxed expression 2155*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc)); 2156*f4a2713aSLionel Sambuc 2157*f4a2713aSLionel Sambuc default: 2158*f4a2713aSLionel Sambuc if (Tok.getIdentifierInfo() == 0) 2159*f4a2713aSLionel Sambuc return ExprError(Diag(AtLoc, diag::err_unexpected_at)); 2160*f4a2713aSLionel Sambuc 2161*f4a2713aSLionel Sambuc switch (Tok.getIdentifierInfo()->getObjCKeywordID()) { 2162*f4a2713aSLionel Sambuc case tok::objc_encode: 2163*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc)); 2164*f4a2713aSLionel Sambuc case tok::objc_protocol: 2165*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc)); 2166*f4a2713aSLionel Sambuc case tok::objc_selector: 2167*f4a2713aSLionel Sambuc return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); 2168*f4a2713aSLionel Sambuc default: { 2169*f4a2713aSLionel Sambuc const char *str = 0; 2170*f4a2713aSLionel Sambuc if (GetLookAheadToken(1).is(tok::l_brace)) { 2171*f4a2713aSLionel Sambuc char ch = Tok.getIdentifierInfo()->getNameStart()[0]; 2172*f4a2713aSLionel Sambuc str = 2173*f4a2713aSLionel Sambuc ch == 't' ? "try" 2174*f4a2713aSLionel Sambuc : (ch == 'f' ? "finally" 2175*f4a2713aSLionel Sambuc : (ch == 'a' ? "autoreleasepool" : 0)); 2176*f4a2713aSLionel Sambuc } 2177*f4a2713aSLionel Sambuc if (str) { 2178*f4a2713aSLionel Sambuc SourceLocation kwLoc = Tok.getLocation(); 2179*f4a2713aSLionel Sambuc return ExprError(Diag(AtLoc, diag::err_unexpected_at) << 2180*f4a2713aSLionel Sambuc FixItHint::CreateReplacement(kwLoc, str)); 2181*f4a2713aSLionel Sambuc } 2182*f4a2713aSLionel Sambuc else 2183*f4a2713aSLionel Sambuc return ExprError(Diag(AtLoc, diag::err_unexpected_at)); 2184*f4a2713aSLionel Sambuc } 2185*f4a2713aSLionel Sambuc } 2186*f4a2713aSLionel Sambuc } 2187*f4a2713aSLionel Sambuc } 2188*f4a2713aSLionel Sambuc 2189*f4a2713aSLionel Sambuc /// \brief Parse the receiver of an Objective-C++ message send. 2190*f4a2713aSLionel Sambuc /// 2191*f4a2713aSLionel Sambuc /// This routine parses the receiver of a message send in 2192*f4a2713aSLionel Sambuc /// Objective-C++ either as a type or as an expression. Note that this 2193*f4a2713aSLionel Sambuc /// routine must not be called to parse a send to 'super', since it 2194*f4a2713aSLionel Sambuc /// has no way to return such a result. 2195*f4a2713aSLionel Sambuc /// 2196*f4a2713aSLionel Sambuc /// \param IsExpr Whether the receiver was parsed as an expression. 2197*f4a2713aSLionel Sambuc /// 2198*f4a2713aSLionel Sambuc /// \param TypeOrExpr If the receiver was parsed as an expression (\c 2199*f4a2713aSLionel Sambuc /// IsExpr is true), the parsed expression. If the receiver was parsed 2200*f4a2713aSLionel Sambuc /// as a type (\c IsExpr is false), the parsed type. 2201*f4a2713aSLionel Sambuc /// 2202*f4a2713aSLionel Sambuc /// \returns True if an error occurred during parsing or semantic 2203*f4a2713aSLionel Sambuc /// analysis, in which case the arguments do not have valid 2204*f4a2713aSLionel Sambuc /// values. Otherwise, returns false for a successful parse. 2205*f4a2713aSLionel Sambuc /// 2206*f4a2713aSLionel Sambuc /// objc-receiver: [C++] 2207*f4a2713aSLionel Sambuc /// 'super' [not parsed here] 2208*f4a2713aSLionel Sambuc /// expression 2209*f4a2713aSLionel Sambuc /// simple-type-specifier 2210*f4a2713aSLionel Sambuc /// typename-specifier 2211*f4a2713aSLionel Sambuc bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { 2212*f4a2713aSLionel Sambuc InMessageExpressionRAIIObject InMessage(*this, true); 2213*f4a2713aSLionel Sambuc 2214*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || 2215*f4a2713aSLionel Sambuc Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) 2216*f4a2713aSLionel Sambuc TryAnnotateTypeOrScopeToken(); 2217*f4a2713aSLionel Sambuc 2218*f4a2713aSLionel Sambuc if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) { 2219*f4a2713aSLionel Sambuc // objc-receiver: 2220*f4a2713aSLionel Sambuc // expression 2221*f4a2713aSLionel Sambuc ExprResult Receiver = ParseExpression(); 2222*f4a2713aSLionel Sambuc if (Receiver.isInvalid()) 2223*f4a2713aSLionel Sambuc return true; 2224*f4a2713aSLionel Sambuc 2225*f4a2713aSLionel Sambuc IsExpr = true; 2226*f4a2713aSLionel Sambuc TypeOrExpr = Receiver.take(); 2227*f4a2713aSLionel Sambuc return false; 2228*f4a2713aSLionel Sambuc } 2229*f4a2713aSLionel Sambuc 2230*f4a2713aSLionel Sambuc // objc-receiver: 2231*f4a2713aSLionel Sambuc // typename-specifier 2232*f4a2713aSLionel Sambuc // simple-type-specifier 2233*f4a2713aSLionel Sambuc // expression (that starts with one of the above) 2234*f4a2713aSLionel Sambuc DeclSpec DS(AttrFactory); 2235*f4a2713aSLionel Sambuc ParseCXXSimpleTypeSpecifier(DS); 2236*f4a2713aSLionel Sambuc 2237*f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren)) { 2238*f4a2713aSLionel Sambuc // If we see an opening parentheses at this point, we are 2239*f4a2713aSLionel Sambuc // actually parsing an expression that starts with a 2240*f4a2713aSLionel Sambuc // function-style cast, e.g., 2241*f4a2713aSLionel Sambuc // 2242*f4a2713aSLionel Sambuc // postfix-expression: 2243*f4a2713aSLionel Sambuc // simple-type-specifier ( expression-list [opt] ) 2244*f4a2713aSLionel Sambuc // typename-specifier ( expression-list [opt] ) 2245*f4a2713aSLionel Sambuc // 2246*f4a2713aSLionel Sambuc // Parse the remainder of this case, then the (optional) 2247*f4a2713aSLionel Sambuc // postfix-expression suffix, followed by the (optional) 2248*f4a2713aSLionel Sambuc // right-hand side of the binary expression. We have an 2249*f4a2713aSLionel Sambuc // instance method. 2250*f4a2713aSLionel Sambuc ExprResult Receiver = ParseCXXTypeConstructExpression(DS); 2251*f4a2713aSLionel Sambuc if (!Receiver.isInvalid()) 2252*f4a2713aSLionel Sambuc Receiver = ParsePostfixExpressionSuffix(Receiver.take()); 2253*f4a2713aSLionel Sambuc if (!Receiver.isInvalid()) 2254*f4a2713aSLionel Sambuc Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma); 2255*f4a2713aSLionel Sambuc if (Receiver.isInvalid()) 2256*f4a2713aSLionel Sambuc return true; 2257*f4a2713aSLionel Sambuc 2258*f4a2713aSLionel Sambuc IsExpr = true; 2259*f4a2713aSLionel Sambuc TypeOrExpr = Receiver.take(); 2260*f4a2713aSLionel Sambuc return false; 2261*f4a2713aSLionel Sambuc } 2262*f4a2713aSLionel Sambuc 2263*f4a2713aSLionel Sambuc // We have a class message. Turn the simple-type-specifier or 2264*f4a2713aSLionel Sambuc // typename-specifier we parsed into a type and parse the 2265*f4a2713aSLionel Sambuc // remainder of the class message. 2266*f4a2713aSLionel Sambuc Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 2267*f4a2713aSLionel Sambuc TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); 2268*f4a2713aSLionel Sambuc if (Type.isInvalid()) 2269*f4a2713aSLionel Sambuc return true; 2270*f4a2713aSLionel Sambuc 2271*f4a2713aSLionel Sambuc IsExpr = false; 2272*f4a2713aSLionel Sambuc TypeOrExpr = Type.get().getAsOpaquePtr(); 2273*f4a2713aSLionel Sambuc return false; 2274*f4a2713aSLionel Sambuc } 2275*f4a2713aSLionel Sambuc 2276*f4a2713aSLionel Sambuc /// \brief Determine whether the parser is currently referring to a an 2277*f4a2713aSLionel Sambuc /// Objective-C message send, using a simplified heuristic to avoid overhead. 2278*f4a2713aSLionel Sambuc /// 2279*f4a2713aSLionel Sambuc /// This routine will only return true for a subset of valid message-send 2280*f4a2713aSLionel Sambuc /// expressions. 2281*f4a2713aSLionel Sambuc bool Parser::isSimpleObjCMessageExpression() { 2282*f4a2713aSLionel Sambuc assert(Tok.is(tok::l_square) && getLangOpts().ObjC1 && 2283*f4a2713aSLionel Sambuc "Incorrect start for isSimpleObjCMessageExpression"); 2284*f4a2713aSLionel Sambuc return GetLookAheadToken(1).is(tok::identifier) && 2285*f4a2713aSLionel Sambuc GetLookAheadToken(2).is(tok::identifier); 2286*f4a2713aSLionel Sambuc } 2287*f4a2713aSLionel Sambuc 2288*f4a2713aSLionel Sambuc bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { 2289*f4a2713aSLionel Sambuc if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) || 2290*f4a2713aSLionel Sambuc InMessageExpression) 2291*f4a2713aSLionel Sambuc return false; 2292*f4a2713aSLionel Sambuc 2293*f4a2713aSLionel Sambuc 2294*f4a2713aSLionel Sambuc ParsedType Type; 2295*f4a2713aSLionel Sambuc 2296*f4a2713aSLionel Sambuc if (Tok.is(tok::annot_typename)) 2297*f4a2713aSLionel Sambuc Type = getTypeAnnotation(Tok); 2298*f4a2713aSLionel Sambuc else if (Tok.is(tok::identifier)) 2299*f4a2713aSLionel Sambuc Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), 2300*f4a2713aSLionel Sambuc getCurScope()); 2301*f4a2713aSLionel Sambuc else 2302*f4a2713aSLionel Sambuc return false; 2303*f4a2713aSLionel Sambuc 2304*f4a2713aSLionel Sambuc if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) { 2305*f4a2713aSLionel Sambuc const Token &AfterNext = GetLookAheadToken(2); 2306*f4a2713aSLionel Sambuc if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) { 2307*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier)) 2308*f4a2713aSLionel Sambuc TryAnnotateTypeOrScopeToken(); 2309*f4a2713aSLionel Sambuc 2310*f4a2713aSLionel Sambuc return Tok.is(tok::annot_typename); 2311*f4a2713aSLionel Sambuc } 2312*f4a2713aSLionel Sambuc } 2313*f4a2713aSLionel Sambuc 2314*f4a2713aSLionel Sambuc return false; 2315*f4a2713aSLionel Sambuc } 2316*f4a2713aSLionel Sambuc 2317*f4a2713aSLionel Sambuc /// objc-message-expr: 2318*f4a2713aSLionel Sambuc /// '[' objc-receiver objc-message-args ']' 2319*f4a2713aSLionel Sambuc /// 2320*f4a2713aSLionel Sambuc /// objc-receiver: [C] 2321*f4a2713aSLionel Sambuc /// 'super' 2322*f4a2713aSLionel Sambuc /// expression 2323*f4a2713aSLionel Sambuc /// class-name 2324*f4a2713aSLionel Sambuc /// type-name 2325*f4a2713aSLionel Sambuc /// 2326*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCMessageExpression() { 2327*f4a2713aSLionel Sambuc assert(Tok.is(tok::l_square) && "'[' expected"); 2328*f4a2713aSLionel Sambuc SourceLocation LBracLoc = ConsumeBracket(); // consume '[' 2329*f4a2713aSLionel Sambuc 2330*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2331*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCMessageReceiver(getCurScope()); 2332*f4a2713aSLionel Sambuc cutOffParsing(); 2333*f4a2713aSLionel Sambuc return ExprError(); 2334*f4a2713aSLionel Sambuc } 2335*f4a2713aSLionel Sambuc 2336*f4a2713aSLionel Sambuc InMessageExpressionRAIIObject InMessage(*this, true); 2337*f4a2713aSLionel Sambuc 2338*f4a2713aSLionel Sambuc if (getLangOpts().CPlusPlus) { 2339*f4a2713aSLionel Sambuc // We completely separate the C and C++ cases because C++ requires 2340*f4a2713aSLionel Sambuc // more complicated (read: slower) parsing. 2341*f4a2713aSLionel Sambuc 2342*f4a2713aSLionel Sambuc // Handle send to super. 2343*f4a2713aSLionel Sambuc // FIXME: This doesn't benefit from the same typo-correction we 2344*f4a2713aSLionel Sambuc // get in Objective-C. 2345*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && 2346*f4a2713aSLionel Sambuc NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) 2347*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 2348*f4a2713aSLionel Sambuc ParsedType(), 0); 2349*f4a2713aSLionel Sambuc 2350*f4a2713aSLionel Sambuc // Parse the receiver, which is either a type or an expression. 2351*f4a2713aSLionel Sambuc bool IsExpr; 2352*f4a2713aSLionel Sambuc void *TypeOrExpr = NULL; 2353*f4a2713aSLionel Sambuc if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { 2354*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2355*f4a2713aSLionel Sambuc return ExprError(); 2356*f4a2713aSLionel Sambuc } 2357*f4a2713aSLionel Sambuc 2358*f4a2713aSLionel Sambuc if (IsExpr) 2359*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 2360*f4a2713aSLionel Sambuc ParsedType(), 2361*f4a2713aSLionel Sambuc static_cast<Expr*>(TypeOrExpr)); 2362*f4a2713aSLionel Sambuc 2363*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 2364*f4a2713aSLionel Sambuc ParsedType::getFromOpaquePtr(TypeOrExpr), 2365*f4a2713aSLionel Sambuc 0); 2366*f4a2713aSLionel Sambuc } 2367*f4a2713aSLionel Sambuc 2368*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier)) { 2369*f4a2713aSLionel Sambuc IdentifierInfo *Name = Tok.getIdentifierInfo(); 2370*f4a2713aSLionel Sambuc SourceLocation NameLoc = Tok.getLocation(); 2371*f4a2713aSLionel Sambuc ParsedType ReceiverType; 2372*f4a2713aSLionel Sambuc switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc, 2373*f4a2713aSLionel Sambuc Name == Ident_super, 2374*f4a2713aSLionel Sambuc NextToken().is(tok::period), 2375*f4a2713aSLionel Sambuc ReceiverType)) { 2376*f4a2713aSLionel Sambuc case Sema::ObjCSuperMessage: 2377*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 2378*f4a2713aSLionel Sambuc ParsedType(), 0); 2379*f4a2713aSLionel Sambuc 2380*f4a2713aSLionel Sambuc case Sema::ObjCClassMessage: 2381*f4a2713aSLionel Sambuc if (!ReceiverType) { 2382*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2383*f4a2713aSLionel Sambuc return ExprError(); 2384*f4a2713aSLionel Sambuc } 2385*f4a2713aSLionel Sambuc 2386*f4a2713aSLionel Sambuc ConsumeToken(); // the type name 2387*f4a2713aSLionel Sambuc 2388*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 2389*f4a2713aSLionel Sambuc ReceiverType, 0); 2390*f4a2713aSLionel Sambuc 2391*f4a2713aSLionel Sambuc case Sema::ObjCInstanceMessage: 2392*f4a2713aSLionel Sambuc // Fall through to parse an expression. 2393*f4a2713aSLionel Sambuc break; 2394*f4a2713aSLionel Sambuc } 2395*f4a2713aSLionel Sambuc } 2396*f4a2713aSLionel Sambuc 2397*f4a2713aSLionel Sambuc // Otherwise, an arbitrary expression can be the receiver of a send. 2398*f4a2713aSLionel Sambuc ExprResult Res(ParseExpression()); 2399*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 2400*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2401*f4a2713aSLionel Sambuc return Res; 2402*f4a2713aSLionel Sambuc } 2403*f4a2713aSLionel Sambuc 2404*f4a2713aSLionel Sambuc return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 2405*f4a2713aSLionel Sambuc ParsedType(), Res.take()); 2406*f4a2713aSLionel Sambuc } 2407*f4a2713aSLionel Sambuc 2408*f4a2713aSLionel Sambuc /// \brief Parse the remainder of an Objective-C message following the 2409*f4a2713aSLionel Sambuc /// '[' objc-receiver. 2410*f4a2713aSLionel Sambuc /// 2411*f4a2713aSLionel Sambuc /// This routine handles sends to super, class messages (sent to a 2412*f4a2713aSLionel Sambuc /// class name), and instance messages (sent to an object), and the 2413*f4a2713aSLionel Sambuc /// target is represented by \p SuperLoc, \p ReceiverType, or \p 2414*f4a2713aSLionel Sambuc /// ReceiverExpr, respectively. Only one of these parameters may have 2415*f4a2713aSLionel Sambuc /// a valid value. 2416*f4a2713aSLionel Sambuc /// 2417*f4a2713aSLionel Sambuc /// \param LBracLoc The location of the opening '['. 2418*f4a2713aSLionel Sambuc /// 2419*f4a2713aSLionel Sambuc /// \param SuperLoc If this is a send to 'super', the location of the 2420*f4a2713aSLionel Sambuc /// 'super' keyword that indicates a send to the superclass. 2421*f4a2713aSLionel Sambuc /// 2422*f4a2713aSLionel Sambuc /// \param ReceiverType If this is a class message, the type of the 2423*f4a2713aSLionel Sambuc /// class we are sending a message to. 2424*f4a2713aSLionel Sambuc /// 2425*f4a2713aSLionel Sambuc /// \param ReceiverExpr If this is an instance message, the expression 2426*f4a2713aSLionel Sambuc /// used to compute the receiver object. 2427*f4a2713aSLionel Sambuc /// 2428*f4a2713aSLionel Sambuc /// objc-message-args: 2429*f4a2713aSLionel Sambuc /// objc-selector 2430*f4a2713aSLionel Sambuc /// objc-keywordarg-list 2431*f4a2713aSLionel Sambuc /// 2432*f4a2713aSLionel Sambuc /// objc-keywordarg-list: 2433*f4a2713aSLionel Sambuc /// objc-keywordarg 2434*f4a2713aSLionel Sambuc /// objc-keywordarg-list objc-keywordarg 2435*f4a2713aSLionel Sambuc /// 2436*f4a2713aSLionel Sambuc /// objc-keywordarg: 2437*f4a2713aSLionel Sambuc /// selector-name[opt] ':' objc-keywordexpr 2438*f4a2713aSLionel Sambuc /// 2439*f4a2713aSLionel Sambuc /// objc-keywordexpr: 2440*f4a2713aSLionel Sambuc /// nonempty-expr-list 2441*f4a2713aSLionel Sambuc /// 2442*f4a2713aSLionel Sambuc /// nonempty-expr-list: 2443*f4a2713aSLionel Sambuc /// assignment-expression 2444*f4a2713aSLionel Sambuc /// nonempty-expr-list , assignment-expression 2445*f4a2713aSLionel Sambuc /// 2446*f4a2713aSLionel Sambuc ExprResult 2447*f4a2713aSLionel Sambuc Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, 2448*f4a2713aSLionel Sambuc SourceLocation SuperLoc, 2449*f4a2713aSLionel Sambuc ParsedType ReceiverType, 2450*f4a2713aSLionel Sambuc ExprArg ReceiverExpr) { 2451*f4a2713aSLionel Sambuc InMessageExpressionRAIIObject InMessage(*this, true); 2452*f4a2713aSLionel Sambuc 2453*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2454*f4a2713aSLionel Sambuc if (SuperLoc.isValid()) 2455*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None, 2456*f4a2713aSLionel Sambuc false); 2457*f4a2713aSLionel Sambuc else if (ReceiverType) 2458*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None, 2459*f4a2713aSLionel Sambuc false); 2460*f4a2713aSLionel Sambuc else 2461*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, 2462*f4a2713aSLionel Sambuc None, false); 2463*f4a2713aSLionel Sambuc cutOffParsing(); 2464*f4a2713aSLionel Sambuc return ExprError(); 2465*f4a2713aSLionel Sambuc } 2466*f4a2713aSLionel Sambuc 2467*f4a2713aSLionel Sambuc // Parse objc-selector 2468*f4a2713aSLionel Sambuc SourceLocation Loc; 2469*f4a2713aSLionel Sambuc IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); 2470*f4a2713aSLionel Sambuc 2471*f4a2713aSLionel Sambuc SmallVector<IdentifierInfo *, 12> KeyIdents; 2472*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 12> KeyLocs; 2473*f4a2713aSLionel Sambuc ExprVector KeyExprs; 2474*f4a2713aSLionel Sambuc 2475*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { 2476*f4a2713aSLionel Sambuc while (1) { 2477*f4a2713aSLionel Sambuc // Each iteration parses a single keyword argument. 2478*f4a2713aSLionel Sambuc KeyIdents.push_back(selIdent); 2479*f4a2713aSLionel Sambuc KeyLocs.push_back(Loc); 2480*f4a2713aSLionel Sambuc 2481*f4a2713aSLionel Sambuc if (Tok.isNot(tok::colon)) { 2482*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_colon); 2483*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2484*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2485*f4a2713aSLionel Sambuc // the enclosing expression. 2486*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2487*f4a2713aSLionel Sambuc return ExprError(); 2488*f4a2713aSLionel Sambuc } 2489*f4a2713aSLionel Sambuc 2490*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the ':'. 2491*f4a2713aSLionel Sambuc /// Parse the expression after ':' 2492*f4a2713aSLionel Sambuc 2493*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2494*f4a2713aSLionel Sambuc if (SuperLoc.isValid()) 2495*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, 2496*f4a2713aSLionel Sambuc KeyIdents, 2497*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/true); 2498*f4a2713aSLionel Sambuc else if (ReceiverType) 2499*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, 2500*f4a2713aSLionel Sambuc KeyIdents, 2501*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/true); 2502*f4a2713aSLionel Sambuc else 2503*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, 2504*f4a2713aSLionel Sambuc KeyIdents, 2505*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/true); 2506*f4a2713aSLionel Sambuc 2507*f4a2713aSLionel Sambuc cutOffParsing(); 2508*f4a2713aSLionel Sambuc return ExprError(); 2509*f4a2713aSLionel Sambuc } 2510*f4a2713aSLionel Sambuc 2511*f4a2713aSLionel Sambuc ExprResult Expr; 2512*f4a2713aSLionel Sambuc if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 2513*f4a2713aSLionel Sambuc Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 2514*f4a2713aSLionel Sambuc Expr = ParseBraceInitializer(); 2515*f4a2713aSLionel Sambuc } else 2516*f4a2713aSLionel Sambuc Expr = ParseAssignmentExpression(); 2517*f4a2713aSLionel Sambuc 2518*f4a2713aSLionel Sambuc ExprResult Res(Expr); 2519*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 2520*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2521*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2522*f4a2713aSLionel Sambuc // the enclosing expression. 2523*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2524*f4a2713aSLionel Sambuc return Res; 2525*f4a2713aSLionel Sambuc } 2526*f4a2713aSLionel Sambuc 2527*f4a2713aSLionel Sambuc // We have a valid expression. 2528*f4a2713aSLionel Sambuc KeyExprs.push_back(Res.release()); 2529*f4a2713aSLionel Sambuc 2530*f4a2713aSLionel Sambuc // Code completion after each argument. 2531*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2532*f4a2713aSLionel Sambuc if (SuperLoc.isValid()) 2533*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, 2534*f4a2713aSLionel Sambuc KeyIdents, 2535*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/false); 2536*f4a2713aSLionel Sambuc else if (ReceiverType) 2537*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, 2538*f4a2713aSLionel Sambuc KeyIdents, 2539*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/false); 2540*f4a2713aSLionel Sambuc else 2541*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, 2542*f4a2713aSLionel Sambuc KeyIdents, 2543*f4a2713aSLionel Sambuc /*AtArgumentEpression=*/false); 2544*f4a2713aSLionel Sambuc cutOffParsing(); 2545*f4a2713aSLionel Sambuc return ExprError(); 2546*f4a2713aSLionel Sambuc } 2547*f4a2713aSLionel Sambuc 2548*f4a2713aSLionel Sambuc // Check for another keyword selector. 2549*f4a2713aSLionel Sambuc selIdent = ParseObjCSelectorPiece(Loc); 2550*f4a2713aSLionel Sambuc if (!selIdent && Tok.isNot(tok::colon)) 2551*f4a2713aSLionel Sambuc break; 2552*f4a2713aSLionel Sambuc // We have a selector or a colon, continue parsing. 2553*f4a2713aSLionel Sambuc } 2554*f4a2713aSLionel Sambuc // Parse the, optional, argument list, comma separated. 2555*f4a2713aSLionel Sambuc while (Tok.is(tok::comma)) { 2556*f4a2713aSLionel Sambuc SourceLocation commaLoc = ConsumeToken(); // Eat the ','. 2557*f4a2713aSLionel Sambuc /// Parse the expression after ',' 2558*f4a2713aSLionel Sambuc ExprResult Res(ParseAssignmentExpression()); 2559*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 2560*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { 2561*f4a2713aSLionel Sambuc Diag(commaLoc, diag::note_extra_comma_message_arg) << 2562*f4a2713aSLionel Sambuc FixItHint::CreateRemoval(commaLoc); 2563*f4a2713aSLionel Sambuc } 2564*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2565*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2566*f4a2713aSLionel Sambuc // the enclosing expression. 2567*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2568*f4a2713aSLionel Sambuc return Res; 2569*f4a2713aSLionel Sambuc } 2570*f4a2713aSLionel Sambuc 2571*f4a2713aSLionel Sambuc // We have a valid expression. 2572*f4a2713aSLionel Sambuc KeyExprs.push_back(Res.release()); 2573*f4a2713aSLionel Sambuc } 2574*f4a2713aSLionel Sambuc } else if (!selIdent) { 2575*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_ident); // missing selector name. 2576*f4a2713aSLionel Sambuc 2577*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2578*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2579*f4a2713aSLionel Sambuc // the enclosing expression. 2580*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2581*f4a2713aSLionel Sambuc return ExprError(); 2582*f4a2713aSLionel Sambuc } 2583*f4a2713aSLionel Sambuc 2584*f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_square)) { 2585*f4a2713aSLionel Sambuc if (Tok.is(tok::identifier)) 2586*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_colon); 2587*f4a2713aSLionel Sambuc else 2588*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_rsquare); 2589*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2590*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2591*f4a2713aSLionel Sambuc // the enclosing expression. 2592*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2593*f4a2713aSLionel Sambuc return ExprError(); 2594*f4a2713aSLionel Sambuc } 2595*f4a2713aSLionel Sambuc 2596*f4a2713aSLionel Sambuc SourceLocation RBracLoc = ConsumeBracket(); // consume ']' 2597*f4a2713aSLionel Sambuc 2598*f4a2713aSLionel Sambuc unsigned nKeys = KeyIdents.size(); 2599*f4a2713aSLionel Sambuc if (nKeys == 0) { 2600*f4a2713aSLionel Sambuc KeyIdents.push_back(selIdent); 2601*f4a2713aSLionel Sambuc KeyLocs.push_back(Loc); 2602*f4a2713aSLionel Sambuc } 2603*f4a2713aSLionel Sambuc Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); 2604*f4a2713aSLionel Sambuc 2605*f4a2713aSLionel Sambuc if (SuperLoc.isValid()) 2606*f4a2713aSLionel Sambuc return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel, 2607*f4a2713aSLionel Sambuc LBracLoc, KeyLocs, RBracLoc, KeyExprs); 2608*f4a2713aSLionel Sambuc else if (ReceiverType) 2609*f4a2713aSLionel Sambuc return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel, 2610*f4a2713aSLionel Sambuc LBracLoc, KeyLocs, RBracLoc, KeyExprs); 2611*f4a2713aSLionel Sambuc return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel, 2612*f4a2713aSLionel Sambuc LBracLoc, KeyLocs, RBracLoc, KeyExprs); 2613*f4a2713aSLionel Sambuc } 2614*f4a2713aSLionel Sambuc 2615*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { 2616*f4a2713aSLionel Sambuc ExprResult Res(ParseStringLiteralExpression()); 2617*f4a2713aSLionel Sambuc if (Res.isInvalid()) return Res; 2618*f4a2713aSLionel Sambuc 2619*f4a2713aSLionel Sambuc // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string 2620*f4a2713aSLionel Sambuc // expressions. At this point, we know that the only valid thing that starts 2621*f4a2713aSLionel Sambuc // with '@' is an @"". 2622*f4a2713aSLionel Sambuc SmallVector<SourceLocation, 4> AtLocs; 2623*f4a2713aSLionel Sambuc ExprVector AtStrings; 2624*f4a2713aSLionel Sambuc AtLocs.push_back(AtLoc); 2625*f4a2713aSLionel Sambuc AtStrings.push_back(Res.release()); 2626*f4a2713aSLionel Sambuc 2627*f4a2713aSLionel Sambuc while (Tok.is(tok::at)) { 2628*f4a2713aSLionel Sambuc AtLocs.push_back(ConsumeToken()); // eat the @. 2629*f4a2713aSLionel Sambuc 2630*f4a2713aSLionel Sambuc // Invalid unless there is a string literal. 2631*f4a2713aSLionel Sambuc if (!isTokenStringLiteral()) 2632*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_objc_concat_string)); 2633*f4a2713aSLionel Sambuc 2634*f4a2713aSLionel Sambuc ExprResult Lit(ParseStringLiteralExpression()); 2635*f4a2713aSLionel Sambuc if (Lit.isInvalid()) 2636*f4a2713aSLionel Sambuc return Lit; 2637*f4a2713aSLionel Sambuc 2638*f4a2713aSLionel Sambuc AtStrings.push_back(Lit.release()); 2639*f4a2713aSLionel Sambuc } 2640*f4a2713aSLionel Sambuc 2641*f4a2713aSLionel Sambuc return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), 2642*f4a2713aSLionel Sambuc AtStrings.size()); 2643*f4a2713aSLionel Sambuc } 2644*f4a2713aSLionel Sambuc 2645*f4a2713aSLionel Sambuc /// ParseObjCBooleanLiteral - 2646*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' boolean-keyword 2647*f4a2713aSLionel Sambuc /// ; 2648*f4a2713aSLionel Sambuc /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no' 2649*f4a2713aSLionel Sambuc /// ; 2650*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, 2651*f4a2713aSLionel Sambuc bool ArgValue) { 2652*f4a2713aSLionel Sambuc SourceLocation EndLoc = ConsumeToken(); // consume the keyword. 2653*f4a2713aSLionel Sambuc return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue); 2654*f4a2713aSLionel Sambuc } 2655*f4a2713aSLionel Sambuc 2656*f4a2713aSLionel Sambuc /// ParseObjCCharacterLiteral - 2657*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' character-literal 2658*f4a2713aSLionel Sambuc /// ; 2659*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { 2660*f4a2713aSLionel Sambuc ExprResult Lit(Actions.ActOnCharacterConstant(Tok)); 2661*f4a2713aSLionel Sambuc if (Lit.isInvalid()) { 2662*f4a2713aSLionel Sambuc return Lit; 2663*f4a2713aSLionel Sambuc } 2664*f4a2713aSLionel Sambuc ConsumeToken(); // Consume the literal token. 2665*f4a2713aSLionel Sambuc return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); 2666*f4a2713aSLionel Sambuc } 2667*f4a2713aSLionel Sambuc 2668*f4a2713aSLionel Sambuc /// ParseObjCNumericLiteral - 2669*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' scalar-literal 2670*f4a2713aSLionel Sambuc /// ; 2671*f4a2713aSLionel Sambuc /// scalar-literal : | numeric-constant /* any numeric constant. */ 2672*f4a2713aSLionel Sambuc /// ; 2673*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { 2674*f4a2713aSLionel Sambuc ExprResult Lit(Actions.ActOnNumericConstant(Tok)); 2675*f4a2713aSLionel Sambuc if (Lit.isInvalid()) { 2676*f4a2713aSLionel Sambuc return Lit; 2677*f4a2713aSLionel Sambuc } 2678*f4a2713aSLionel Sambuc ConsumeToken(); // Consume the literal token. 2679*f4a2713aSLionel Sambuc return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); 2680*f4a2713aSLionel Sambuc } 2681*f4a2713aSLionel Sambuc 2682*f4a2713aSLionel Sambuc /// ParseObjCBoxedExpr - 2683*f4a2713aSLionel Sambuc /// objc-box-expression: 2684*f4a2713aSLionel Sambuc /// @( assignment-expression ) 2685*f4a2713aSLionel Sambuc ExprResult 2686*f4a2713aSLionel Sambuc Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { 2687*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) 2688*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@"); 2689*f4a2713aSLionel Sambuc 2690*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 2691*f4a2713aSLionel Sambuc T.consumeOpen(); 2692*f4a2713aSLionel Sambuc ExprResult ValueExpr(ParseAssignmentExpression()); 2693*f4a2713aSLionel Sambuc if (T.consumeClose()) 2694*f4a2713aSLionel Sambuc return ExprError(); 2695*f4a2713aSLionel Sambuc 2696*f4a2713aSLionel Sambuc if (ValueExpr.isInvalid()) 2697*f4a2713aSLionel Sambuc return ExprError(); 2698*f4a2713aSLionel Sambuc 2699*f4a2713aSLionel Sambuc // Wrap the sub-expression in a parenthesized expression, to distinguish 2700*f4a2713aSLionel Sambuc // a boxed expression from a literal. 2701*f4a2713aSLionel Sambuc SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); 2702*f4a2713aSLionel Sambuc ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take()); 2703*f4a2713aSLionel Sambuc return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), 2704*f4a2713aSLionel Sambuc ValueExpr.take()); 2705*f4a2713aSLionel Sambuc } 2706*f4a2713aSLionel Sambuc 2707*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { 2708*f4a2713aSLionel Sambuc ExprVector ElementExprs; // array elements. 2709*f4a2713aSLionel Sambuc ConsumeBracket(); // consume the l_square. 2710*f4a2713aSLionel Sambuc 2711*f4a2713aSLionel Sambuc while (Tok.isNot(tok::r_square)) { 2712*f4a2713aSLionel Sambuc // Parse list of array element expressions (all must be id types). 2713*f4a2713aSLionel Sambuc ExprResult Res(ParseAssignmentExpression()); 2714*f4a2713aSLionel Sambuc if (Res.isInvalid()) { 2715*f4a2713aSLionel Sambuc // We must manually skip to a ']', otherwise the expression skipper will 2716*f4a2713aSLionel Sambuc // stop at the ']' when it skips to the ';'. We want it to skip beyond 2717*f4a2713aSLionel Sambuc // the enclosing expression. 2718*f4a2713aSLionel Sambuc SkipUntil(tok::r_square, StopAtSemi); 2719*f4a2713aSLionel Sambuc return Res; 2720*f4a2713aSLionel Sambuc } 2721*f4a2713aSLionel Sambuc 2722*f4a2713aSLionel Sambuc // Parse the ellipsis that indicates a pack expansion. 2723*f4a2713aSLionel Sambuc if (Tok.is(tok::ellipsis)) 2724*f4a2713aSLionel Sambuc Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken()); 2725*f4a2713aSLionel Sambuc if (Res.isInvalid()) 2726*f4a2713aSLionel Sambuc return true; 2727*f4a2713aSLionel Sambuc 2728*f4a2713aSLionel Sambuc ElementExprs.push_back(Res.release()); 2729*f4a2713aSLionel Sambuc 2730*f4a2713aSLionel Sambuc if (Tok.is(tok::comma)) 2731*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the ','. 2732*f4a2713aSLionel Sambuc else if (Tok.isNot(tok::r_square)) 2733*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma)); 2734*f4a2713aSLionel Sambuc } 2735*f4a2713aSLionel Sambuc SourceLocation EndLoc = ConsumeBracket(); // location of ']' 2736*f4a2713aSLionel Sambuc MultiExprArg Args(ElementExprs); 2737*f4a2713aSLionel Sambuc return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); 2738*f4a2713aSLionel Sambuc } 2739*f4a2713aSLionel Sambuc 2740*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { 2741*f4a2713aSLionel Sambuc SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements. 2742*f4a2713aSLionel Sambuc ConsumeBrace(); // consume the l_square. 2743*f4a2713aSLionel Sambuc while (Tok.isNot(tok::r_brace)) { 2744*f4a2713aSLionel Sambuc // Parse the comma separated key : value expressions. 2745*f4a2713aSLionel Sambuc ExprResult KeyExpr; 2746*f4a2713aSLionel Sambuc { 2747*f4a2713aSLionel Sambuc ColonProtectionRAIIObject X(*this); 2748*f4a2713aSLionel Sambuc KeyExpr = ParseAssignmentExpression(); 2749*f4a2713aSLionel Sambuc if (KeyExpr.isInvalid()) { 2750*f4a2713aSLionel Sambuc // We must manually skip to a '}', otherwise the expression skipper will 2751*f4a2713aSLionel Sambuc // stop at the '}' when it skips to the ';'. We want it to skip beyond 2752*f4a2713aSLionel Sambuc // the enclosing expression. 2753*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace, StopAtSemi); 2754*f4a2713aSLionel Sambuc return KeyExpr; 2755*f4a2713aSLionel Sambuc } 2756*f4a2713aSLionel Sambuc } 2757*f4a2713aSLionel Sambuc 2758*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) { 2759*f4a2713aSLionel Sambuc ConsumeToken(); 2760*f4a2713aSLionel Sambuc } else { 2761*f4a2713aSLionel Sambuc Diag(Tok, diag::err_expected_colon); 2762*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace, StopAtSemi); 2763*f4a2713aSLionel Sambuc return ExprError(); 2764*f4a2713aSLionel Sambuc } 2765*f4a2713aSLionel Sambuc 2766*f4a2713aSLionel Sambuc ExprResult ValueExpr(ParseAssignmentExpression()); 2767*f4a2713aSLionel Sambuc if (ValueExpr.isInvalid()) { 2768*f4a2713aSLionel Sambuc // We must manually skip to a '}', otherwise the expression skipper will 2769*f4a2713aSLionel Sambuc // stop at the '}' when it skips to the ';'. We want it to skip beyond 2770*f4a2713aSLionel Sambuc // the enclosing expression. 2771*f4a2713aSLionel Sambuc SkipUntil(tok::r_brace, StopAtSemi); 2772*f4a2713aSLionel Sambuc return ValueExpr; 2773*f4a2713aSLionel Sambuc } 2774*f4a2713aSLionel Sambuc 2775*f4a2713aSLionel Sambuc // Parse the ellipsis that designates this as a pack expansion. 2776*f4a2713aSLionel Sambuc SourceLocation EllipsisLoc; 2777*f4a2713aSLionel Sambuc if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus) 2778*f4a2713aSLionel Sambuc EllipsisLoc = ConsumeToken(); 2779*f4a2713aSLionel Sambuc 2780*f4a2713aSLionel Sambuc // We have a valid expression. Collect it in a vector so we can 2781*f4a2713aSLionel Sambuc // build the argument list. 2782*f4a2713aSLionel Sambuc ObjCDictionaryElement Element = { 2783*f4a2713aSLionel Sambuc KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None 2784*f4a2713aSLionel Sambuc }; 2785*f4a2713aSLionel Sambuc Elements.push_back(Element); 2786*f4a2713aSLionel Sambuc 2787*f4a2713aSLionel Sambuc if (Tok.is(tok::comma)) 2788*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the ','. 2789*f4a2713aSLionel Sambuc else if (Tok.isNot(tok::r_brace)) 2790*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma)); 2791*f4a2713aSLionel Sambuc } 2792*f4a2713aSLionel Sambuc SourceLocation EndLoc = ConsumeBrace(); 2793*f4a2713aSLionel Sambuc 2794*f4a2713aSLionel Sambuc // Create the ObjCDictionaryLiteral. 2795*f4a2713aSLionel Sambuc return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), 2796*f4a2713aSLionel Sambuc Elements.data(), Elements.size()); 2797*f4a2713aSLionel Sambuc } 2798*f4a2713aSLionel Sambuc 2799*f4a2713aSLionel Sambuc /// objc-encode-expression: 2800*f4a2713aSLionel Sambuc /// \@encode ( type-name ) 2801*f4a2713aSLionel Sambuc ExprResult 2802*f4a2713aSLionel Sambuc Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { 2803*f4a2713aSLionel Sambuc assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!"); 2804*f4a2713aSLionel Sambuc 2805*f4a2713aSLionel Sambuc SourceLocation EncLoc = ConsumeToken(); 2806*f4a2713aSLionel Sambuc 2807*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) 2808*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode"); 2809*f4a2713aSLionel Sambuc 2810*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 2811*f4a2713aSLionel Sambuc T.consumeOpen(); 2812*f4a2713aSLionel Sambuc 2813*f4a2713aSLionel Sambuc TypeResult Ty = ParseTypeName(); 2814*f4a2713aSLionel Sambuc 2815*f4a2713aSLionel Sambuc T.consumeClose(); 2816*f4a2713aSLionel Sambuc 2817*f4a2713aSLionel Sambuc if (Ty.isInvalid()) 2818*f4a2713aSLionel Sambuc return ExprError(); 2819*f4a2713aSLionel Sambuc 2820*f4a2713aSLionel Sambuc return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(), 2821*f4a2713aSLionel Sambuc Ty.get(), T.getCloseLocation()); 2822*f4a2713aSLionel Sambuc } 2823*f4a2713aSLionel Sambuc 2824*f4a2713aSLionel Sambuc /// objc-protocol-expression 2825*f4a2713aSLionel Sambuc /// \@protocol ( protocol-name ) 2826*f4a2713aSLionel Sambuc ExprResult 2827*f4a2713aSLionel Sambuc Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { 2828*f4a2713aSLionel Sambuc SourceLocation ProtoLoc = ConsumeToken(); 2829*f4a2713aSLionel Sambuc 2830*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) 2831*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol"); 2832*f4a2713aSLionel Sambuc 2833*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 2834*f4a2713aSLionel Sambuc T.consumeOpen(); 2835*f4a2713aSLionel Sambuc 2836*f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) 2837*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_ident)); 2838*f4a2713aSLionel Sambuc 2839*f4a2713aSLionel Sambuc IdentifierInfo *protocolId = Tok.getIdentifierInfo(); 2840*f4a2713aSLionel Sambuc SourceLocation ProtoIdLoc = ConsumeToken(); 2841*f4a2713aSLionel Sambuc 2842*f4a2713aSLionel Sambuc T.consumeClose(); 2843*f4a2713aSLionel Sambuc 2844*f4a2713aSLionel Sambuc return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, 2845*f4a2713aSLionel Sambuc T.getOpenLocation(), ProtoIdLoc, 2846*f4a2713aSLionel Sambuc T.getCloseLocation()); 2847*f4a2713aSLionel Sambuc } 2848*f4a2713aSLionel Sambuc 2849*f4a2713aSLionel Sambuc /// objc-selector-expression 2850*f4a2713aSLionel Sambuc /// @selector '(' objc-keyword-selector ')' 2851*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { 2852*f4a2713aSLionel Sambuc SourceLocation SelectorLoc = ConsumeToken(); 2853*f4a2713aSLionel Sambuc 2854*f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) 2855*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector"); 2856*f4a2713aSLionel Sambuc 2857*f4a2713aSLionel Sambuc SmallVector<IdentifierInfo *, 12> KeyIdents; 2858*f4a2713aSLionel Sambuc SourceLocation sLoc; 2859*f4a2713aSLionel Sambuc 2860*f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren); 2861*f4a2713aSLionel Sambuc T.consumeOpen(); 2862*f4a2713aSLionel Sambuc 2863*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2864*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); 2865*f4a2713aSLionel Sambuc cutOffParsing(); 2866*f4a2713aSLionel Sambuc return ExprError(); 2867*f4a2713aSLionel Sambuc } 2868*f4a2713aSLionel Sambuc 2869*f4a2713aSLionel Sambuc IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc); 2870*f4a2713aSLionel Sambuc if (!SelIdent && // missing selector name. 2871*f4a2713aSLionel Sambuc Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) 2872*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_ident)); 2873*f4a2713aSLionel Sambuc 2874*f4a2713aSLionel Sambuc KeyIdents.push_back(SelIdent); 2875*f4a2713aSLionel Sambuc unsigned nColons = 0; 2876*f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) { 2877*f4a2713aSLionel Sambuc while (1) { 2878*f4a2713aSLionel Sambuc if (Tok.is(tok::coloncolon)) { // Handle :: in C++. 2879*f4a2713aSLionel Sambuc ++nColons; 2880*f4a2713aSLionel Sambuc KeyIdents.push_back(0); 2881*f4a2713aSLionel Sambuc } else if (Tok.isNot(tok::colon)) 2882*f4a2713aSLionel Sambuc return ExprError(Diag(Tok, diag::err_expected_colon)); 2883*f4a2713aSLionel Sambuc 2884*f4a2713aSLionel Sambuc ++nColons; 2885*f4a2713aSLionel Sambuc ConsumeToken(); // Eat the ':' or '::'. 2886*f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren)) 2887*f4a2713aSLionel Sambuc break; 2888*f4a2713aSLionel Sambuc 2889*f4a2713aSLionel Sambuc if (Tok.is(tok::code_completion)) { 2890*f4a2713aSLionel Sambuc Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); 2891*f4a2713aSLionel Sambuc cutOffParsing(); 2892*f4a2713aSLionel Sambuc return ExprError(); 2893*f4a2713aSLionel Sambuc } 2894*f4a2713aSLionel Sambuc 2895*f4a2713aSLionel Sambuc // Check for another keyword selector. 2896*f4a2713aSLionel Sambuc SourceLocation Loc; 2897*f4a2713aSLionel Sambuc SelIdent = ParseObjCSelectorPiece(Loc); 2898*f4a2713aSLionel Sambuc KeyIdents.push_back(SelIdent); 2899*f4a2713aSLionel Sambuc if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) 2900*f4a2713aSLionel Sambuc break; 2901*f4a2713aSLionel Sambuc } 2902*f4a2713aSLionel Sambuc } 2903*f4a2713aSLionel Sambuc T.consumeClose(); 2904*f4a2713aSLionel Sambuc Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); 2905*f4a2713aSLionel Sambuc return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, 2906*f4a2713aSLionel Sambuc T.getOpenLocation(), 2907*f4a2713aSLionel Sambuc T.getCloseLocation()); 2908*f4a2713aSLionel Sambuc } 2909*f4a2713aSLionel Sambuc 2910*f4a2713aSLionel Sambuc void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { 2911*f4a2713aSLionel Sambuc // MCDecl might be null due to error in method or c-function prototype, etc. 2912*f4a2713aSLionel Sambuc Decl *MCDecl = LM.D; 2913*f4a2713aSLionel Sambuc bool skip = MCDecl && 2914*f4a2713aSLionel Sambuc ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) || 2915*f4a2713aSLionel Sambuc (!parseMethod && Actions.isObjCMethodDecl(MCDecl))); 2916*f4a2713aSLionel Sambuc if (skip) 2917*f4a2713aSLionel Sambuc return; 2918*f4a2713aSLionel Sambuc 2919*f4a2713aSLionel Sambuc // Save the current token position. 2920*f4a2713aSLionel Sambuc SourceLocation OrigLoc = Tok.getLocation(); 2921*f4a2713aSLionel Sambuc 2922*f4a2713aSLionel Sambuc assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); 2923*f4a2713aSLionel Sambuc // Append the current token at the end of the new token stream so that it 2924*f4a2713aSLionel Sambuc // doesn't get lost. 2925*f4a2713aSLionel Sambuc LM.Toks.push_back(Tok); 2926*f4a2713aSLionel Sambuc PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 2927*f4a2713aSLionel Sambuc 2928*f4a2713aSLionel Sambuc // Consume the previously pushed token. 2929*f4a2713aSLionel Sambuc ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 2930*f4a2713aSLionel Sambuc 2931*f4a2713aSLionel Sambuc assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || 2932*f4a2713aSLionel Sambuc Tok.is(tok::colon)) && 2933*f4a2713aSLionel Sambuc "Inline objective-c method not starting with '{' or 'try' or ':'"); 2934*f4a2713aSLionel Sambuc // Enter a scope for the method or c-fucntion body. 2935*f4a2713aSLionel Sambuc ParseScope BodyScope(this, 2936*f4a2713aSLionel Sambuc parseMethod 2937*f4a2713aSLionel Sambuc ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope 2938*f4a2713aSLionel Sambuc : Scope::FnScope|Scope::DeclScope); 2939*f4a2713aSLionel Sambuc 2940*f4a2713aSLionel Sambuc // Tell the actions module that we have entered a method or c-function definition 2941*f4a2713aSLionel Sambuc // with the specified Declarator for the method/function. 2942*f4a2713aSLionel Sambuc if (parseMethod) 2943*f4a2713aSLionel Sambuc Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); 2944*f4a2713aSLionel Sambuc else 2945*f4a2713aSLionel Sambuc Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); 2946*f4a2713aSLionel Sambuc if (Tok.is(tok::kw_try)) 2947*f4a2713aSLionel Sambuc MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope); 2948*f4a2713aSLionel Sambuc else { 2949*f4a2713aSLionel Sambuc if (Tok.is(tok::colon)) 2950*f4a2713aSLionel Sambuc ParseConstructorInitializer(MCDecl); 2951*f4a2713aSLionel Sambuc MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope); 2952*f4a2713aSLionel Sambuc } 2953*f4a2713aSLionel Sambuc 2954*f4a2713aSLionel Sambuc if (Tok.getLocation() != OrigLoc) { 2955*f4a2713aSLionel Sambuc // Due to parsing error, we either went over the cached tokens or 2956*f4a2713aSLionel Sambuc // there are still cached tokens left. If it's the latter case skip the 2957*f4a2713aSLionel Sambuc // leftover tokens. 2958*f4a2713aSLionel Sambuc // Since this is an uncommon situation that should be avoided, use the 2959*f4a2713aSLionel Sambuc // expensive isBeforeInTranslationUnit call. 2960*f4a2713aSLionel Sambuc if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 2961*f4a2713aSLionel Sambuc OrigLoc)) 2962*f4a2713aSLionel Sambuc while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) 2963*f4a2713aSLionel Sambuc ConsumeAnyToken(); 2964*f4a2713aSLionel Sambuc } 2965*f4a2713aSLionel Sambuc 2966*f4a2713aSLionel Sambuc return; 2967*f4a2713aSLionel Sambuc } 2968