10b57cec5SDimitry Andric //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the Objective-C portions of the Parser interface. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 14bdd1243dSDimitry Andric #include "clang/AST/ODRDiagsEmitter.h" 150b57cec5SDimitry Andric #include "clang/AST/PrettyDeclStackTrace.h" 160b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 175ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h" 180b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h" 195ffd83dbSDimitry Andric #include "clang/Parse/Parser.h" 200b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h" 210b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h" 220b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 23*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h" 24*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace clang; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric /// Skips attributes after an Objective-C @ directive. Emits a diagnostic. 310b57cec5SDimitry Andric void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { 320b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory); 330b57cec5SDimitry Andric if (Tok.is(tok::kw___attribute)) { 340b57cec5SDimitry Andric if (Kind == tok::objc_interface || Kind == tok::objc_protocol) 350b57cec5SDimitry Andric Diag(Tok, diag::err_objc_postfix_attribute_hint) 360b57cec5SDimitry Andric << (Kind == tok::objc_protocol); 370b57cec5SDimitry Andric else 380b57cec5SDimitry Andric Diag(Tok, diag::err_objc_postfix_attribute); 390b57cec5SDimitry Andric ParseGNUAttributes(attrs); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// ParseObjCAtDirectives - Handle parts of the external-declaration production: 440b57cec5SDimitry Andric /// external-declaration: [C99 6.9] 450b57cec5SDimitry Andric /// [OBJC] objc-class-definition 460b57cec5SDimitry Andric /// [OBJC] objc-class-declaration 470b57cec5SDimitry Andric /// [OBJC] objc-alias-declaration 480b57cec5SDimitry Andric /// [OBJC] objc-protocol-definition 490b57cec5SDimitry Andric /// [OBJC] objc-method-definition 500b57cec5SDimitry Andric /// [OBJC] '@' 'end' 51bdd1243dSDimitry Andric Parser::DeclGroupPtrTy 52bdd1243dSDimitry Andric Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs, 53bdd1243dSDimitry Andric ParsedAttributes &DeclSpecAttrs) { 54bdd1243dSDimitry Andric DeclAttrs.takeAllFrom(DeclSpecAttrs); 55bdd1243dSDimitry Andric 560b57cec5SDimitry Andric SourceLocation AtLoc = ConsumeToken(); // the "@" 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 590b57cec5SDimitry Andric cutOffParsing(); 60*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope()); 610b57cec5SDimitry Andric return nullptr; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 64bdd1243dSDimitry Andric switch (Tok.getObjCKeywordID()) { 65bdd1243dSDimitry Andric case tok::objc_interface: 66bdd1243dSDimitry Andric case tok::objc_protocol: 67bdd1243dSDimitry Andric case tok::objc_implementation: 68bdd1243dSDimitry Andric break; 69bdd1243dSDimitry Andric default: 705f757f3fSDimitry Andric for (const auto &Attr : DeclAttrs) { 71bdd1243dSDimitry Andric if (Attr.isGNUAttribute()) 72bdd1243dSDimitry Andric Diag(Tok.getLocation(), diag::err_objc_unexpected_attr); 735f757f3fSDimitry Andric } 74bdd1243dSDimitry Andric } 75bdd1243dSDimitry Andric 760b57cec5SDimitry Andric Decl *SingleDecl = nullptr; 770b57cec5SDimitry Andric switch (Tok.getObjCKeywordID()) { 780b57cec5SDimitry Andric case tok::objc_class: 790b57cec5SDimitry Andric return ParseObjCAtClassDeclaration(AtLoc); 800b57cec5SDimitry Andric case tok::objc_interface: 81bdd1243dSDimitry Andric SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DeclAttrs); 820b57cec5SDimitry Andric break; 830b57cec5SDimitry Andric case tok::objc_protocol: 84bdd1243dSDimitry Andric return ParseObjCAtProtocolDeclaration(AtLoc, DeclAttrs); 850b57cec5SDimitry Andric case tok::objc_implementation: 86bdd1243dSDimitry Andric return ParseObjCAtImplementationDeclaration(AtLoc, DeclAttrs); 870b57cec5SDimitry Andric case tok::objc_end: 880b57cec5SDimitry Andric return ParseObjCAtEndDeclaration(AtLoc); 890b57cec5SDimitry Andric case tok::objc_compatibility_alias: 900b57cec5SDimitry Andric SingleDecl = ParseObjCAtAliasDeclaration(AtLoc); 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric case tok::objc_synthesize: 930b57cec5SDimitry Andric SingleDecl = ParseObjCPropertySynthesize(AtLoc); 940b57cec5SDimitry Andric break; 950b57cec5SDimitry Andric case tok::objc_dynamic: 960b57cec5SDimitry Andric SingleDecl = ParseObjCPropertyDynamic(AtLoc); 970b57cec5SDimitry Andric break; 980b57cec5SDimitry Andric case tok::objc_import: 990b57cec5SDimitry Andric if (getLangOpts().Modules || getLangOpts().DebuggerSupport) { 10081ad6265SDimitry Andric Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module; 10181ad6265SDimitry Andric SingleDecl = ParseModuleImport(AtLoc, IS); 1020b57cec5SDimitry Andric break; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric Diag(AtLoc, diag::err_atimport); 1050b57cec5SDimitry Andric SkipUntil(tok::semi); 1060b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(nullptr); 1070b57cec5SDimitry Andric default: 1080b57cec5SDimitry Andric Diag(AtLoc, diag::err_unexpected_at); 1090b57cec5SDimitry Andric SkipUntil(tok::semi); 1100b57cec5SDimitry Andric SingleDecl = nullptr; 1110b57cec5SDimitry Andric break; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(SingleDecl); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric /// Class to handle popping type parameters when leaving the scope. 1170b57cec5SDimitry Andric class Parser::ObjCTypeParamListScope { 1180b57cec5SDimitry Andric Sema &Actions; 1190b57cec5SDimitry Andric Scope *S; 1200b57cec5SDimitry Andric ObjCTypeParamList *Params; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric public: 1230b57cec5SDimitry Andric ObjCTypeParamListScope(Sema &Actions, Scope *S) 1240b57cec5SDimitry Andric : Actions(Actions), S(S), Params(nullptr) {} 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric ~ObjCTypeParamListScope() { 1270b57cec5SDimitry Andric leave(); 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric void enter(ObjCTypeParamList *P) { 1310b57cec5SDimitry Andric assert(!Params); 1320b57cec5SDimitry Andric Params = P; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric void leave() { 1360b57cec5SDimitry Andric if (Params) 137*0fca6ea1SDimitry Andric Actions.ObjC().popObjCTypeParamList(S, Params); 1380b57cec5SDimitry Andric Params = nullptr; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric }; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// 1430b57cec5SDimitry Andric /// objc-class-declaration: 1440b57cec5SDimitry Andric /// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';' 1450b57cec5SDimitry Andric /// 1460b57cec5SDimitry Andric /// objc-class-forward-decl: 1470b57cec5SDimitry Andric /// identifier objc-type-parameter-list[opt] 1480b57cec5SDimitry Andric /// 1490b57cec5SDimitry Andric Parser::DeclGroupPtrTy 1500b57cec5SDimitry Andric Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { 1510b57cec5SDimitry Andric ConsumeToken(); // the identifier "class" 1520b57cec5SDimitry Andric SmallVector<IdentifierInfo *, 8> ClassNames; 1530b57cec5SDimitry Andric SmallVector<SourceLocation, 8> ClassLocs; 1540b57cec5SDimitry Andric SmallVector<ObjCTypeParamList *, 8> ClassTypeParams; 1550b57cec5SDimitry Andric 15604eeddc0SDimitry Andric while (true) { 1570b57cec5SDimitry Andric MaybeSkipAttributes(tok::objc_class); 15806c3fb27SDimitry Andric if (Tok.is(tok::code_completion)) { 15906c3fb27SDimitry Andric cutOffParsing(); 160*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCClassForwardDecl(getCurScope()); 16106c3fb27SDimitry Andric return Actions.ConvertDeclToDeclGroup(nullptr); 16206c3fb27SDimitry Andric } 1630b57cec5SDimitry Andric if (expectIdentifier()) { 1640b57cec5SDimitry Andric SkipUntil(tok::semi); 1650b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(nullptr); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric ClassNames.push_back(Tok.getIdentifierInfo()); 1680b57cec5SDimitry Andric ClassLocs.push_back(Tok.getLocation()); 1690b57cec5SDimitry Andric ConsumeToken(); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric // Parse the optional objc-type-parameter-list. 1720b57cec5SDimitry Andric ObjCTypeParamList *TypeParams = nullptr; 1730b57cec5SDimitry Andric if (Tok.is(tok::less)) 1740b57cec5SDimitry Andric TypeParams = parseObjCTypeParamList(); 1750b57cec5SDimitry Andric ClassTypeParams.push_back(TypeParams); 1760b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) 1770b57cec5SDimitry Andric break; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Consume the ';'. 1810b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class")) 1820b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(nullptr); 1830b57cec5SDimitry Andric 184*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnForwardClassDeclaration( 185*0fca6ea1SDimitry Andric atLoc, ClassNames.data(), ClassLocs.data(), ClassTypeParams, 1860b57cec5SDimitry Andric ClassNames.size()); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) 1900b57cec5SDimitry Andric { 191*0fca6ea1SDimitry Andric SemaObjC::ObjCContainerKind ock = Actions.ObjC().getObjCContainerKind(); 192*0fca6ea1SDimitry Andric if (ock == SemaObjC::OCK_None) 1930b57cec5SDimitry Andric return; 1940b57cec5SDimitry Andric 195*0fca6ea1SDimitry Andric Decl *Decl = Actions.ObjC().getObjCDeclContext(); 1960b57cec5SDimitry Andric if (CurParsedObjCImpl) { 1970b57cec5SDimitry Andric CurParsedObjCImpl->finish(AtLoc); 1980b57cec5SDimitry Andric } else { 199*0fca6ea1SDimitry Andric Actions.ObjC().ActOnAtEnd(getCurScope(), AtLoc); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric Diag(AtLoc, diag::err_objc_missing_end) 2020b57cec5SDimitry Andric << FixItHint::CreateInsertion(AtLoc, "@end\n"); 2030b57cec5SDimitry Andric if (Decl) 2040b57cec5SDimitry Andric Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric /// 2080b57cec5SDimitry Andric /// objc-interface: 2090b57cec5SDimitry Andric /// objc-class-interface-attributes[opt] objc-class-interface 2100b57cec5SDimitry Andric /// objc-category-interface 2110b57cec5SDimitry Andric /// 2120b57cec5SDimitry Andric /// objc-class-interface: 2130b57cec5SDimitry Andric /// '@' 'interface' identifier objc-type-parameter-list[opt] 2140b57cec5SDimitry Andric /// objc-superclass[opt] objc-protocol-refs[opt] 2150b57cec5SDimitry Andric /// objc-class-instance-variables[opt] 2160b57cec5SDimitry Andric /// objc-interface-decl-list 2170b57cec5SDimitry Andric /// @end 2180b57cec5SDimitry Andric /// 2190b57cec5SDimitry Andric /// objc-category-interface: 2200b57cec5SDimitry Andric /// '@' 'interface' identifier objc-type-parameter-list[opt] 2210b57cec5SDimitry Andric /// '(' identifier[opt] ')' objc-protocol-refs[opt] 2220b57cec5SDimitry Andric /// objc-interface-decl-list 2230b57cec5SDimitry Andric /// @end 2240b57cec5SDimitry Andric /// 2250b57cec5SDimitry Andric /// objc-superclass: 2260b57cec5SDimitry Andric /// ':' identifier objc-type-arguments[opt] 2270b57cec5SDimitry Andric /// 2280b57cec5SDimitry Andric /// objc-class-interface-attributes: 2290b57cec5SDimitry Andric /// __attribute__((visibility("default"))) 2300b57cec5SDimitry Andric /// __attribute__((visibility("hidden"))) 2310b57cec5SDimitry Andric /// __attribute__((deprecated)) 2320b57cec5SDimitry Andric /// __attribute__((unavailable)) 2330b57cec5SDimitry Andric /// __attribute__((objc_exception)) - used by NSException on 64-bit 2340b57cec5SDimitry Andric /// __attribute__((objc_root_class)) 2350b57cec5SDimitry Andric /// 2360b57cec5SDimitry Andric Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, 2370b57cec5SDimitry Andric ParsedAttributes &attrs) { 2380b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_interface) && 2390b57cec5SDimitry Andric "ParseObjCAtInterfaceDeclaration(): Expected @interface"); 2400b57cec5SDimitry Andric CheckNestedObjCContexts(AtLoc); 2410b57cec5SDimitry Andric ConsumeToken(); // the "interface" identifier 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Code completion after '@interface'. 2440b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 2450b57cec5SDimitry Andric cutOffParsing(); 246*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCInterfaceDecl(getCurScope()); 2470b57cec5SDimitry Andric return nullptr; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric MaybeSkipAttributes(tok::objc_interface); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric if (expectIdentifier()) 2530b57cec5SDimitry Andric return nullptr; // missing class or category name. 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // We have a class or category name - consume it. 2560b57cec5SDimitry Andric IdentifierInfo *nameId = Tok.getIdentifierInfo(); 2570b57cec5SDimitry Andric SourceLocation nameLoc = ConsumeToken(); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter 2600b57cec5SDimitry Andric // case, LAngleLoc will be valid and ProtocolIdents will capture the 2610b57cec5SDimitry Andric // protocol references (that have not yet been resolved). 2620b57cec5SDimitry Andric SourceLocation LAngleLoc, EndProtoLoc; 2630b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 8> ProtocolIdents; 2640b57cec5SDimitry Andric ObjCTypeParamList *typeParameterList = nullptr; 2650b57cec5SDimitry Andric ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); 2660b57cec5SDimitry Andric if (Tok.is(tok::less)) 2670b57cec5SDimitry Andric typeParameterList = parseObjCTypeParamListOrProtocolRefs( 2680b57cec5SDimitry Andric typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric if (Tok.is(tok::l_paren) && 2710b57cec5SDimitry Andric !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 2740b57cec5SDimitry Andric T.consumeOpen(); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric SourceLocation categoryLoc; 2770b57cec5SDimitry Andric IdentifierInfo *categoryId = nullptr; 2780b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 2790b57cec5SDimitry Andric cutOffParsing(); 280*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCInterfaceCategory( 281*0fca6ea1SDimitry Andric getCurScope(), nameId, nameLoc); 2820b57cec5SDimitry Andric return nullptr; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric // For ObjC2, the category name is optional (not an error). 2860b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 2870b57cec5SDimitry Andric categoryId = Tok.getIdentifierInfo(); 2880b57cec5SDimitry Andric categoryLoc = ConsumeToken(); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric else if (!getLangOpts().ObjC) { 2910b57cec5SDimitry Andric Diag(Tok, diag::err_expected) 2920b57cec5SDimitry Andric << tok::identifier; // missing category name. 2930b57cec5SDimitry Andric return nullptr; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric T.consumeClose(); 2970b57cec5SDimitry Andric if (T.getCloseLocation().isInvalid()) 2980b57cec5SDimitry Andric return nullptr; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Next, we need to check for any protocol references. 3010b57cec5SDimitry Andric assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols"); 3020b57cec5SDimitry Andric SmallVector<Decl *, 8> ProtocolRefs; 3030b57cec5SDimitry Andric SmallVector<SourceLocation, 8> ProtocolLocs; 3040b57cec5SDimitry Andric if (Tok.is(tok::less) && 3050b57cec5SDimitry Andric ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true, 3060b57cec5SDimitry Andric LAngleLoc, EndProtoLoc, 3070b57cec5SDimitry Andric /*consumeLastToken=*/true)) 3080b57cec5SDimitry Andric return nullptr; 3090b57cec5SDimitry Andric 310*0fca6ea1SDimitry Andric ObjCCategoryDecl *CategoryType = Actions.ObjC().ActOnStartCategoryInterface( 3110b57cec5SDimitry Andric AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, 3120b57cec5SDimitry Andric ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), 3130b57cec5SDimitry Andric EndProtoLoc, attrs); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) 3160b57cec5SDimitry Andric ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric return CategoryType; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric // Parse a class interface. 3230b57cec5SDimitry Andric IdentifierInfo *superClassId = nullptr; 3240b57cec5SDimitry Andric SourceLocation superClassLoc; 3250b57cec5SDimitry Andric SourceLocation typeArgsLAngleLoc; 3260b57cec5SDimitry Andric SmallVector<ParsedType, 4> typeArgs; 3270b57cec5SDimitry Andric SourceLocation typeArgsRAngleLoc; 3280b57cec5SDimitry Andric SmallVector<Decl *, 4> protocols; 3290b57cec5SDimitry Andric SmallVector<SourceLocation, 4> protocolLocs; 3300b57cec5SDimitry Andric if (Tok.is(tok::colon)) { // a super class is specified. 3310b57cec5SDimitry Andric ConsumeToken(); 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric // Code completion of superclass names. 3340b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3350b57cec5SDimitry Andric cutOffParsing(); 336*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSuperclass(getCurScope(), nameId, 337*0fca6ea1SDimitry Andric nameLoc); 3380b57cec5SDimitry Andric return nullptr; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric if (expectIdentifier()) 3420b57cec5SDimitry Andric return nullptr; // missing super class name. 3430b57cec5SDimitry Andric superClassId = Tok.getIdentifierInfo(); 3440b57cec5SDimitry Andric superClassLoc = ConsumeToken(); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric // Type arguments for the superclass or protocol conformances. 3470b57cec5SDimitry Andric if (Tok.is(tok::less)) { 3480b57cec5SDimitry Andric parseObjCTypeArgsOrProtocolQualifiers( 3490b57cec5SDimitry Andric nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc, 3500b57cec5SDimitry Andric protocols, protocolLocs, EndProtoLoc, 3510b57cec5SDimitry Andric /*consumeLastToken=*/true, 3520b57cec5SDimitry Andric /*warnOnIncompleteProtocols=*/true); 3530b57cec5SDimitry Andric if (Tok.is(tok::eof)) 3540b57cec5SDimitry Andric return nullptr; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric // Next, we need to check for any protocol references. 3590b57cec5SDimitry Andric if (LAngleLoc.isValid()) { 3600b57cec5SDimitry Andric if (!ProtocolIdents.empty()) { 3610b57cec5SDimitry Andric // We already parsed the protocols named when we thought we had a 3620b57cec5SDimitry Andric // type parameter list. Translate them into actual protocol references. 3630b57cec5SDimitry Andric for (const auto &pair : ProtocolIdents) { 3640b57cec5SDimitry Andric protocolLocs.push_back(pair.second); 3650b57cec5SDimitry Andric } 366*0fca6ea1SDimitry Andric Actions.ObjC().FindProtocolDeclaration(/*WarnOnDeclarations=*/true, 3670b57cec5SDimitry Andric /*ForObjCContainer=*/true, 3680b57cec5SDimitry Andric ProtocolIdents, protocols); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric } else if (protocols.empty() && Tok.is(tok::less) && 3710b57cec5SDimitry Andric ParseObjCProtocolReferences(protocols, protocolLocs, true, true, 3720b57cec5SDimitry Andric LAngleLoc, EndProtoLoc, 3730b57cec5SDimitry Andric /*consumeLastToken=*/true)) { 3740b57cec5SDimitry Andric return nullptr; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric if (Tok.isNot(tok::less)) 378*0fca6ea1SDimitry Andric Actions.ObjC().ActOnTypedefedProtocols(protocols, protocolLocs, 3790b57cec5SDimitry Andric superClassId, superClassLoc); 3800b57cec5SDimitry Andric 381*0fca6ea1SDimitry Andric SkipBodyInfo SkipBody; 382*0fca6ea1SDimitry Andric ObjCInterfaceDecl *ClsType = Actions.ObjC().ActOnStartClassInterface( 3830b57cec5SDimitry Andric getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, 3840b57cec5SDimitry Andric superClassLoc, typeArgs, 3850b57cec5SDimitry Andric SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), 386bdd1243dSDimitry Andric protocols.size(), protocolLocs.data(), EndProtoLoc, attrs, &SkipBody); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) 3890b57cec5SDimitry Andric ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); 3920b57cec5SDimitry Andric 393bdd1243dSDimitry Andric if (SkipBody.CheckSameAsPrevious) { 394bdd1243dSDimitry Andric auto *PreviousDef = cast<ObjCInterfaceDecl>(SkipBody.Previous); 395bdd1243dSDimitry Andric if (Actions.ActOnDuplicateODRHashDefinition(ClsType, PreviousDef)) { 396bdd1243dSDimitry Andric ClsType->mergeDuplicateDefinitionWithCommon(PreviousDef->getDefinition()); 397bdd1243dSDimitry Andric } else { 398bdd1243dSDimitry Andric ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(), 399bdd1243dSDimitry Andric getPreprocessor().getLangOpts()); 400bdd1243dSDimitry Andric DiagsEmitter.diagnoseMismatch(PreviousDef, ClsType); 401bdd1243dSDimitry Andric ClsType->setInvalidDecl(); 402bdd1243dSDimitry Andric } 403bdd1243dSDimitry Andric } 404bdd1243dSDimitry Andric 4050b57cec5SDimitry Andric return ClsType; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric /// Add an attribute for a context-sensitive type nullability to the given 4090b57cec5SDimitry Andric /// declarator. 4100b57cec5SDimitry Andric static void addContextSensitiveTypeNullability(Parser &P, 4110b57cec5SDimitry Andric Declarator &D, 4120b57cec5SDimitry Andric NullabilityKind nullability, 4130b57cec5SDimitry Andric SourceLocation nullabilityLoc, 4140b57cec5SDimitry Andric bool &addedToDeclSpec) { 4150b57cec5SDimitry Andric // Create the attribute. 4160b57cec5SDimitry Andric auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * { 4170b57cec5SDimitry Andric return Pool.create(P.getNullabilityKeyword(nullability), 4180b57cec5SDimitry Andric SourceRange(nullabilityLoc), nullptr, SourceLocation(), 41906c3fb27SDimitry Andric nullptr, 0, ParsedAttr::Form::ContextSensitiveKeyword()); 4200b57cec5SDimitry Andric }; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric if (D.getNumTypeObjects() > 0) { 4230b57cec5SDimitry Andric // Add the attribute to the declarator chunk nearest the declarator. 4240b57cec5SDimitry Andric D.getTypeObject(0).getAttrs().addAtEnd( 4250b57cec5SDimitry Andric getNullabilityAttr(D.getAttributePool())); 4260b57cec5SDimitry Andric } else if (!addedToDeclSpec) { 4270b57cec5SDimitry Andric // Otherwise, just put it on the declaration specifiers (if one 4280b57cec5SDimitry Andric // isn't there already). 4290b57cec5SDimitry Andric D.getMutableDeclSpec().getAttributes().addAtEnd( 4300b57cec5SDimitry Andric getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); 4310b57cec5SDimitry Andric addedToDeclSpec = true; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric /// Parse an Objective-C type parameter list, if present, or capture 4360b57cec5SDimitry Andric /// the locations of the protocol identifiers for a list of protocol 4370b57cec5SDimitry Andric /// references. 4380b57cec5SDimitry Andric /// 4390b57cec5SDimitry Andric /// objc-type-parameter-list: 4400b57cec5SDimitry Andric /// '<' objc-type-parameter (',' objc-type-parameter)* '>' 4410b57cec5SDimitry Andric /// 4420b57cec5SDimitry Andric /// objc-type-parameter: 4430b57cec5SDimitry Andric /// objc-type-parameter-variance? identifier objc-type-parameter-bound[opt] 4440b57cec5SDimitry Andric /// 4450b57cec5SDimitry Andric /// objc-type-parameter-bound: 4460b57cec5SDimitry Andric /// ':' type-name 4470b57cec5SDimitry Andric /// 4480b57cec5SDimitry Andric /// objc-type-parameter-variance: 4490b57cec5SDimitry Andric /// '__covariant' 4500b57cec5SDimitry Andric /// '__contravariant' 4510b57cec5SDimitry Andric /// 4520b57cec5SDimitry Andric /// \param lAngleLoc The location of the starting '<'. 4530b57cec5SDimitry Andric /// 4540b57cec5SDimitry Andric /// \param protocolIdents Will capture the list of identifiers, if the 4550b57cec5SDimitry Andric /// angle brackets contain a list of protocol references rather than a 4560b57cec5SDimitry Andric /// type parameter list. 4570b57cec5SDimitry Andric /// 4580b57cec5SDimitry Andric /// \param rAngleLoc The location of the ending '>'. 4590b57cec5SDimitry Andric ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( 4600b57cec5SDimitry Andric ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, 4610b57cec5SDimitry Andric SmallVectorImpl<IdentifierLocPair> &protocolIdents, 4620b57cec5SDimitry Andric SourceLocation &rAngleLoc, bool mayBeProtocolList) { 4630b57cec5SDimitry Andric assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list"); 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric // Within the type parameter list, don't treat '>' as an operator. 4660b57cec5SDimitry Andric GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // Local function to "flush" the protocol identifiers, turning them into 4690b57cec5SDimitry Andric // type parameters. 4700b57cec5SDimitry Andric SmallVector<Decl *, 4> typeParams; 4710b57cec5SDimitry Andric auto makeProtocolIdentsIntoTypeParameters = [&]() { 4720b57cec5SDimitry Andric unsigned index = 0; 4730b57cec5SDimitry Andric for (const auto &pair : protocolIdents) { 474*0fca6ea1SDimitry Andric DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam( 4750b57cec5SDimitry Andric getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(), 4760b57cec5SDimitry Andric index++, pair.first, pair.second, SourceLocation(), nullptr); 4770b57cec5SDimitry Andric if (typeParam.isUsable()) 4780b57cec5SDimitry Andric typeParams.push_back(typeParam.get()); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric protocolIdents.clear(); 4820b57cec5SDimitry Andric mayBeProtocolList = false; 4830b57cec5SDimitry Andric }; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric bool invalid = false; 4860b57cec5SDimitry Andric lAngleLoc = ConsumeToken(); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric do { 4890b57cec5SDimitry Andric // Parse the variance, if any. 4900b57cec5SDimitry Andric SourceLocation varianceLoc; 4910b57cec5SDimitry Andric ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant; 4920b57cec5SDimitry Andric if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) { 4930b57cec5SDimitry Andric variance = Tok.is(tok::kw___covariant) 4940b57cec5SDimitry Andric ? ObjCTypeParamVariance::Covariant 4950b57cec5SDimitry Andric : ObjCTypeParamVariance::Contravariant; 4960b57cec5SDimitry Andric varianceLoc = ConsumeToken(); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric // Once we've seen a variance specific , we know this is not a 4990b57cec5SDimitry Andric // list of protocol references. 5000b57cec5SDimitry Andric if (mayBeProtocolList) { 5010b57cec5SDimitry Andric // Up until now, we have been queuing up parameters because they 5020b57cec5SDimitry Andric // might be protocol references. Turn them into parameters now. 5030b57cec5SDimitry Andric makeProtocolIdentsIntoTypeParameters(); 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric // Parse the identifier. 5080b57cec5SDimitry Andric if (!Tok.is(tok::identifier)) { 5090b57cec5SDimitry Andric // Code completion. 5100b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 5110b57cec5SDimitry Andric // FIXME: If these aren't protocol references, we'll need different 5120b57cec5SDimitry Andric // completions. 5130b57cec5SDimitry Andric cutOffParsing(); 514*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( 515*0fca6ea1SDimitry Andric protocolIdents); 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric // FIXME: Better recovery here?. 5180b57cec5SDimitry Andric return nullptr; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric Diag(Tok, diag::err_objc_expected_type_parameter); 5220b57cec5SDimitry Andric invalid = true; 5230b57cec5SDimitry Andric break; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric IdentifierInfo *paramName = Tok.getIdentifierInfo(); 5270b57cec5SDimitry Andric SourceLocation paramLoc = ConsumeToken(); 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric // If there is a bound, parse it. 5300b57cec5SDimitry Andric SourceLocation colonLoc; 5310b57cec5SDimitry Andric TypeResult boundType; 5320b57cec5SDimitry Andric if (TryConsumeToken(tok::colon, colonLoc)) { 5330b57cec5SDimitry Andric // Once we've seen a bound, we know this is not a list of protocol 5340b57cec5SDimitry Andric // references. 5350b57cec5SDimitry Andric if (mayBeProtocolList) { 5360b57cec5SDimitry Andric // Up until now, we have been queuing up parameters because they 5370b57cec5SDimitry Andric // might be protocol references. Turn them into parameters now. 5380b57cec5SDimitry Andric makeProtocolIdentsIntoTypeParameters(); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric // type-name 5420b57cec5SDimitry Andric boundType = ParseTypeName(); 5430b57cec5SDimitry Andric if (boundType.isInvalid()) 5440b57cec5SDimitry Andric invalid = true; 5450b57cec5SDimitry Andric } else if (mayBeProtocolList) { 5460b57cec5SDimitry Andric // If this could still be a protocol list, just capture the identifier. 5470b57cec5SDimitry Andric // We don't want to turn it into a parameter. 5480b57cec5SDimitry Andric protocolIdents.push_back(std::make_pair(paramName, paramLoc)); 5490b57cec5SDimitry Andric continue; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric // Create the type parameter. 553*0fca6ea1SDimitry Andric DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam( 5540b57cec5SDimitry Andric getCurScope(), variance, varianceLoc, typeParams.size(), paramName, 5550b57cec5SDimitry Andric paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr); 5560b57cec5SDimitry Andric if (typeParam.isUsable()) 5570b57cec5SDimitry Andric typeParams.push_back(typeParam.get()); 5580b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma)); 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric // Parse the '>'. 5610b57cec5SDimitry Andric if (invalid) { 5620b57cec5SDimitry Andric SkipUntil(tok::greater, tok::at, StopBeforeMatch); 5630b57cec5SDimitry Andric if (Tok.is(tok::greater)) 5640b57cec5SDimitry Andric ConsumeToken(); 5655ffd83dbSDimitry Andric } else if (ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, 5660b57cec5SDimitry Andric /*ConsumeLastToken=*/true, 5670b57cec5SDimitry Andric /*ObjCGenericList=*/true)) { 5680b57cec5SDimitry Andric SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus, 5690b57cec5SDimitry Andric tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace, 5700b57cec5SDimitry Andric tok::comma, tok::semi }, 5710b57cec5SDimitry Andric StopBeforeMatch); 5720b57cec5SDimitry Andric if (Tok.is(tok::greater)) 5730b57cec5SDimitry Andric ConsumeToken(); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric if (mayBeProtocolList) { 5770b57cec5SDimitry Andric // A type parameter list must be followed by either a ':' (indicating the 5780b57cec5SDimitry Andric // presence of a superclass) or a '(' (indicating that this is a category 5790b57cec5SDimitry Andric // or extension). This disambiguates between an objc-type-parameter-list 5800b57cec5SDimitry Andric // and a objc-protocol-refs. 5810b57cec5SDimitry Andric if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) { 5820b57cec5SDimitry Andric // Returning null indicates that we don't have a type parameter list. 5830b57cec5SDimitry Andric // The results the caller needs to handle the protocol references are 5840b57cec5SDimitry Andric // captured in the reference parameters already. 5850b57cec5SDimitry Andric return nullptr; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // We have a type parameter list that looks like a list of protocol 5890b57cec5SDimitry Andric // references. Turn that parameter list into type parameters. 5900b57cec5SDimitry Andric makeProtocolIdentsIntoTypeParameters(); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric // Form the type parameter list and enter its scope. 594*0fca6ea1SDimitry Andric ObjCTypeParamList *list = Actions.ObjC().actOnObjCTypeParamList( 595*0fca6ea1SDimitry Andric getCurScope(), lAngleLoc, typeParams, rAngleLoc); 5960b57cec5SDimitry Andric Scope.enter(list); 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric // Clear out the angle locations; they're used by the caller to indicate 5990b57cec5SDimitry Andric // whether there are any protocol references. 6000b57cec5SDimitry Andric lAngleLoc = SourceLocation(); 6010b57cec5SDimitry Andric rAngleLoc = SourceLocation(); 6020b57cec5SDimitry Andric return invalid ? nullptr : list; 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric /// Parse an objc-type-parameter-list. 6060b57cec5SDimitry Andric ObjCTypeParamList *Parser::parseObjCTypeParamList() { 6070b57cec5SDimitry Andric SourceLocation lAngleLoc; 6080b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 1> protocolIdents; 6090b57cec5SDimitry Andric SourceLocation rAngleLoc; 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric ObjCTypeParamListScope Scope(Actions, getCurScope()); 6120b57cec5SDimitry Andric return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents, 6130b57cec5SDimitry Andric rAngleLoc, 6140b57cec5SDimitry Andric /*mayBeProtocolList=*/false); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6175f757f3fSDimitry Andric static bool isTopLevelObjCKeyword(tok::ObjCKeywordKind DirectiveKind) { 6185f757f3fSDimitry Andric switch (DirectiveKind) { 6195f757f3fSDimitry Andric case tok::objc_class: 6205f757f3fSDimitry Andric case tok::objc_compatibility_alias: 6215f757f3fSDimitry Andric case tok::objc_interface: 6225f757f3fSDimitry Andric case tok::objc_implementation: 6235f757f3fSDimitry Andric case tok::objc_protocol: 6245f757f3fSDimitry Andric return true; 6255f757f3fSDimitry Andric default: 6265f757f3fSDimitry Andric return false; 6275f757f3fSDimitry Andric } 6285f757f3fSDimitry Andric } 6295f757f3fSDimitry Andric 6300b57cec5SDimitry Andric /// objc-interface-decl-list: 6310b57cec5SDimitry Andric /// empty 6320b57cec5SDimitry Andric /// objc-interface-decl-list objc-property-decl [OBJC2] 6330b57cec5SDimitry Andric /// objc-interface-decl-list objc-method-requirement [OBJC2] 6340b57cec5SDimitry Andric /// objc-interface-decl-list objc-method-proto ';' 6350b57cec5SDimitry Andric /// objc-interface-decl-list declaration 6360b57cec5SDimitry Andric /// objc-interface-decl-list ';' 6370b57cec5SDimitry Andric /// 6380b57cec5SDimitry Andric /// objc-method-requirement: [OBJC2] 6390b57cec5SDimitry Andric /// @required 6400b57cec5SDimitry Andric /// @optional 6410b57cec5SDimitry Andric /// 6420b57cec5SDimitry Andric void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, 6430b57cec5SDimitry Andric Decl *CDecl) { 6440b57cec5SDimitry Andric SmallVector<Decl *, 32> allMethods; 6450b57cec5SDimitry Andric SmallVector<DeclGroupPtrTy, 8> allTUVariables; 6460b57cec5SDimitry Andric tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric SourceRange AtEnd; 6490b57cec5SDimitry Andric 65004eeddc0SDimitry Andric while (true) { 6510b57cec5SDimitry Andric // If this is a method prototype, parse it. 6520b57cec5SDimitry Andric if (Tok.isOneOf(tok::minus, tok::plus)) { 6530b57cec5SDimitry Andric if (Decl *methodPrototype = 6540b57cec5SDimitry Andric ParseObjCMethodPrototype(MethodImplKind, false)) 6550b57cec5SDimitry Andric allMethods.push_back(methodPrototype); 6560b57cec5SDimitry Andric // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for 6570b57cec5SDimitry Andric // method definitions. 6580b57cec5SDimitry Andric if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) { 6590b57cec5SDimitry Andric // We didn't find a semi and we error'ed out. Skip until a ';' or '@'. 6600b57cec5SDimitry Andric SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); 6610b57cec5SDimitry Andric if (Tok.is(tok::semi)) 6620b57cec5SDimitry Andric ConsumeToken(); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric continue; 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 6670b57cec5SDimitry Andric Diag(Tok, diag::err_expected_minus_or_plus); 6680b57cec5SDimitry Andric ParseObjCMethodDecl(Tok.getLocation(), 6690b57cec5SDimitry Andric tok::minus, 6700b57cec5SDimitry Andric MethodImplKind, false); 6710b57cec5SDimitry Andric continue; 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric // Ignore excess semicolons. 6740b57cec5SDimitry Andric if (Tok.is(tok::semi)) { 6750b57cec5SDimitry Andric // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons, 6760b57cec5SDimitry Andric // to make -Wextra-semi diagnose them. 6770b57cec5SDimitry Andric ConsumeToken(); 6780b57cec5SDimitry Andric continue; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric // If we got to the end of the file, exit the loop. 6820b57cec5SDimitry Andric if (isEofOrEom()) 6830b57cec5SDimitry Andric break; 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric // Code completion within an Objective-C interface. 6860b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 687fe6060f1SDimitry Andric cutOffParsing(); 688*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteOrdinaryName( 689*0fca6ea1SDimitry Andric getCurScope(), CurParsedObjCImpl 690*0fca6ea1SDimitry Andric ? SemaCodeCompletion::PCC_ObjCImplementation 691*0fca6ea1SDimitry Andric : SemaCodeCompletion::PCC_ObjCInterface); 692fe6060f1SDimitry Andric return; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric // If we don't have an @ directive, parse it as a function definition. 6960b57cec5SDimitry Andric if (Tok.isNot(tok::at)) { 6970b57cec5SDimitry Andric // The code below does not consume '}'s because it is afraid of eating the 6980b57cec5SDimitry Andric // end of a namespace. Because of the way this code is structured, an 6990b57cec5SDimitry Andric // erroneous r_brace would cause an infinite loop if not handled here. 7000b57cec5SDimitry Andric if (Tok.is(tok::r_brace)) 7010b57cec5SDimitry Andric break; 7020b57cec5SDimitry Andric 703bdd1243dSDimitry Andric ParsedAttributes EmptyDeclAttrs(AttrFactory); 704bdd1243dSDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric // Since we call ParseDeclarationOrFunctionDefinition() instead of 7070b57cec5SDimitry Andric // ParseExternalDeclaration() below (so that this doesn't parse nested 7080b57cec5SDimitry Andric // @interfaces), this needs to duplicate some code from the latter. 7090b57cec5SDimitry Andric if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { 7100b57cec5SDimitry Andric SourceLocation DeclEnd; 71181ad6265SDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 712bdd1243dSDimitry Andric allTUVariables.push_back(ParseDeclaration(DeclaratorContext::File, 713bdd1243dSDimitry Andric DeclEnd, EmptyDeclAttrs, 714bdd1243dSDimitry Andric EmptyDeclSpecAttrs)); 7150b57cec5SDimitry Andric continue; 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 718bdd1243dSDimitry Andric allTUVariables.push_back(ParseDeclarationOrFunctionDefinition( 719bdd1243dSDimitry Andric EmptyDeclAttrs, EmptyDeclSpecAttrs)); 7200b57cec5SDimitry Andric continue; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7235f757f3fSDimitry Andric // Otherwise, we have an @ directive, peak at the next token 7245f757f3fSDimitry Andric SourceLocation AtLoc = Tok.getLocation(); 7255f757f3fSDimitry Andric const auto &NextTok = NextToken(); 7265f757f3fSDimitry Andric if (NextTok.is(tok::code_completion)) { 727fe6060f1SDimitry Andric cutOffParsing(); 728*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope()); 729fe6060f1SDimitry Andric return; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7325f757f3fSDimitry Andric tok::ObjCKeywordKind DirectiveKind = NextTok.getObjCKeywordID(); 7330b57cec5SDimitry Andric if (DirectiveKind == tok::objc_end) { // @end -> terminate list 7345f757f3fSDimitry Andric ConsumeToken(); // the "@" 7350b57cec5SDimitry Andric AtEnd.setBegin(AtLoc); 7360b57cec5SDimitry Andric AtEnd.setEnd(Tok.getLocation()); 7370b57cec5SDimitry Andric break; 7380b57cec5SDimitry Andric } else if (DirectiveKind == tok::objc_not_keyword) { 7395f757f3fSDimitry Andric Diag(NextTok, diag::err_objc_unknown_at); 7400b57cec5SDimitry Andric SkipUntil(tok::semi); 7410b57cec5SDimitry Andric continue; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7445f757f3fSDimitry Andric // If we see something like '@interface' that's only allowed at the top 7455f757f3fSDimitry Andric // level, bail out as if we saw an '@end'. We'll diagnose this below. 7465f757f3fSDimitry Andric if (isTopLevelObjCKeyword(DirectiveKind)) 7475f757f3fSDimitry Andric break; 7485f757f3fSDimitry Andric 7495f757f3fSDimitry Andric // Otherwise parse it as part of the current declaration. Eat "@identifier". 7505f757f3fSDimitry Andric ConsumeToken(); 7510b57cec5SDimitry Andric ConsumeToken(); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric switch (DirectiveKind) { 7540b57cec5SDimitry Andric default: 7550b57cec5SDimitry Andric // FIXME: If someone forgets an @end on a protocol, this loop will 7560b57cec5SDimitry Andric // continue to eat up tons of stuff and spew lots of nonsense errors. It 7570b57cec5SDimitry Andric // would probably be better to bail out if we saw an @class or @interface 7580b57cec5SDimitry Andric // or something like that. 7590b57cec5SDimitry Andric Diag(AtLoc, diag::err_objc_illegal_interface_qual); 7600b57cec5SDimitry Andric // Skip until we see an '@' or '}' or ';'. 7610b57cec5SDimitry Andric SkipUntil(tok::r_brace, tok::at, StopAtSemi); 7620b57cec5SDimitry Andric break; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric case tok::objc_required: 7650b57cec5SDimitry Andric case tok::objc_optional: 7660b57cec5SDimitry Andric // This is only valid on protocols. 7670b57cec5SDimitry Andric if (contextKey != tok::objc_protocol) 7680b57cec5SDimitry Andric Diag(AtLoc, diag::err_objc_directive_only_in_protocol); 7690b57cec5SDimitry Andric else 7700b57cec5SDimitry Andric MethodImplKind = DirectiveKind; 7710b57cec5SDimitry Andric break; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric case tok::objc_property: 7740b57cec5SDimitry Andric ObjCDeclSpec OCDS; 7750b57cec5SDimitry Andric SourceLocation LParenLoc; 7760b57cec5SDimitry Andric // Parse property attribute list, if any. 7770b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 7780b57cec5SDimitry Andric LParenLoc = Tok.getLocation(); 7790b57cec5SDimitry Andric ParseObjCPropertyAttribute(OCDS); 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric bool addedToDeclSpec = false; 783*0fca6ea1SDimitry Andric auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) -> Decl * { 7840b57cec5SDimitry Andric if (FD.D.getIdentifier() == nullptr) { 7850b57cec5SDimitry Andric Diag(AtLoc, diag::err_objc_property_requires_field_name) 7860b57cec5SDimitry Andric << FD.D.getSourceRange(); 787*0fca6ea1SDimitry Andric return nullptr; 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric if (FD.BitfieldSize) { 7900b57cec5SDimitry Andric Diag(AtLoc, diag::err_objc_property_bitfield) 7910b57cec5SDimitry Andric << FD.D.getSourceRange(); 792*0fca6ea1SDimitry Andric return nullptr; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric // Map a nullability property attribute to a context-sensitive keyword 7960b57cec5SDimitry Andric // attribute. 7975ffd83dbSDimitry Andric if (OCDS.getPropertyAttributes() & 7985ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_nullability) 7990b57cec5SDimitry Andric addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(), 8000b57cec5SDimitry Andric OCDS.getNullabilityLoc(), 8010b57cec5SDimitry Andric addedToDeclSpec); 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric // Install the property declarator into interfaceDecl. 804*0fca6ea1SDimitry Andric const IdentifierInfo *SelName = 8050b57cec5SDimitry Andric OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName); 808*0fca6ea1SDimitry Andric const IdentifierInfo *SetterName = OCDS.getSetterName(); 8090b57cec5SDimitry Andric Selector SetterSel; 8100b57cec5SDimitry Andric if (SetterName) 8110b57cec5SDimitry Andric SetterSel = PP.getSelectorTable().getSelector(1, &SetterName); 8120b57cec5SDimitry Andric else 8130b57cec5SDimitry Andric SetterSel = SelectorTable::constructSetterSelector( 8140b57cec5SDimitry Andric PP.getIdentifierTable(), PP.getSelectorTable(), 8150b57cec5SDimitry Andric FD.D.getIdentifier()); 816*0fca6ea1SDimitry Andric Decl *Property = Actions.ObjC().ActOnProperty( 8170b57cec5SDimitry Andric getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, 8180b57cec5SDimitry Andric MethodImplKind); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric FD.complete(Property); 821*0fca6ea1SDimitry Andric return Property; 8220b57cec5SDimitry Andric }; 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // Parse all the comma separated declarators. 8250b57cec5SDimitry Andric ParsingDeclSpec DS(*this); 8260b57cec5SDimitry Andric ParseStructDeclaration(DS, ObjCPropertyCallback); 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); 8290b57cec5SDimitry Andric break; 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8335f757f3fSDimitry Andric // We break out of the big loop in 3 cases: when we see @end or when we see 8345f757f3fSDimitry Andric // top-level ObjC keyword or EOF. In the former case, eat the @end. In the 8355f757f3fSDimitry Andric // later cases, emit an error. 8365f757f3fSDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_end)) { 8370b57cec5SDimitry Andric ConsumeToken(); // the "end" identifier 8380b57cec5SDimitry Andric } else { 8390b57cec5SDimitry Andric Diag(Tok, diag::err_objc_missing_end) 8400b57cec5SDimitry Andric << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n"); 8410b57cec5SDimitry Andric Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) 842*0fca6ea1SDimitry Andric << (int)Actions.ObjC().getObjCContainerKind(); 8430b57cec5SDimitry Andric AtEnd.setBegin(Tok.getLocation()); 8440b57cec5SDimitry Andric AtEnd.setEnd(Tok.getLocation()); 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric // Insert collected methods declarations into the @interface object. 8480b57cec5SDimitry Andric // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. 849*0fca6ea1SDimitry Andric Actions.ObjC().ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric /// Diagnose redundant or conflicting nullability information. 8530b57cec5SDimitry Andric static void diagnoseRedundantPropertyNullability(Parser &P, 8540b57cec5SDimitry Andric ObjCDeclSpec &DS, 8550b57cec5SDimitry Andric NullabilityKind nullability, 8560b57cec5SDimitry Andric SourceLocation nullabilityLoc){ 8570b57cec5SDimitry Andric if (DS.getNullability() == nullability) { 8580b57cec5SDimitry Andric P.Diag(nullabilityLoc, diag::warn_nullability_duplicate) 8590b57cec5SDimitry Andric << DiagNullabilityKind(nullability, true) 8600b57cec5SDimitry Andric << SourceRange(DS.getNullabilityLoc()); 8610b57cec5SDimitry Andric return; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric P.Diag(nullabilityLoc, diag::err_nullability_conflicting) 8650b57cec5SDimitry Andric << DiagNullabilityKind(nullability, true) 8660b57cec5SDimitry Andric << DiagNullabilityKind(DS.getNullability(), true) 8670b57cec5SDimitry Andric << SourceRange(DS.getNullabilityLoc()); 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric /// Parse property attribute declarations. 8710b57cec5SDimitry Andric /// 8720b57cec5SDimitry Andric /// property-attr-decl: '(' property-attrlist ')' 8730b57cec5SDimitry Andric /// property-attrlist: 8740b57cec5SDimitry Andric /// property-attribute 8750b57cec5SDimitry Andric /// property-attrlist ',' property-attribute 8760b57cec5SDimitry Andric /// property-attribute: 8770b57cec5SDimitry Andric /// getter '=' identifier 8780b57cec5SDimitry Andric /// setter '=' identifier ':' 879480093f4SDimitry Andric /// direct 8800b57cec5SDimitry Andric /// readonly 8810b57cec5SDimitry Andric /// readwrite 8820b57cec5SDimitry Andric /// assign 8830b57cec5SDimitry Andric /// retain 8840b57cec5SDimitry Andric /// copy 8850b57cec5SDimitry Andric /// nonatomic 8860b57cec5SDimitry Andric /// atomic 8870b57cec5SDimitry Andric /// strong 8880b57cec5SDimitry Andric /// weak 8890b57cec5SDimitry Andric /// unsafe_unretained 8900b57cec5SDimitry Andric /// nonnull 8910b57cec5SDimitry Andric /// nullable 8920b57cec5SDimitry Andric /// null_unspecified 8930b57cec5SDimitry Andric /// null_resettable 8940b57cec5SDimitry Andric /// class 8950b57cec5SDimitry Andric /// 8960b57cec5SDimitry Andric void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { 8970b57cec5SDimitry Andric assert(Tok.getKind() == tok::l_paren); 8980b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 8990b57cec5SDimitry Andric T.consumeOpen(); 9000b57cec5SDimitry Andric 90104eeddc0SDimitry Andric while (true) { 9020b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 903fe6060f1SDimitry Andric cutOffParsing(); 904*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertyFlags(getCurScope(), DS); 905fe6060f1SDimitry Andric return; 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric const IdentifierInfo *II = Tok.getIdentifierInfo(); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric // If this is not an identifier at all, bail out early. 9100b57cec5SDimitry Andric if (!II) { 9110b57cec5SDimitry Andric T.consumeClose(); 9120b57cec5SDimitry Andric return; 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric SourceLocation AttrName = ConsumeToken(); // consume last attribute name 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric if (II->isStr("readonly")) 9185ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); 9190b57cec5SDimitry Andric else if (II->isStr("assign")) 9205ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_assign); 9210b57cec5SDimitry Andric else if (II->isStr("unsafe_unretained")) 9225ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained); 9230b57cec5SDimitry Andric else if (II->isStr("readwrite")) 9245ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite); 9250b57cec5SDimitry Andric else if (II->isStr("retain")) 9265ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_retain); 9270b57cec5SDimitry Andric else if (II->isStr("strong")) 9285ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_strong); 9290b57cec5SDimitry Andric else if (II->isStr("copy")) 9305ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_copy); 9310b57cec5SDimitry Andric else if (II->isStr("nonatomic")) 9325ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic); 9330b57cec5SDimitry Andric else if (II->isStr("atomic")) 9345ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_atomic); 9350b57cec5SDimitry Andric else if (II->isStr("weak")) 9365ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_weak); 9370b57cec5SDimitry Andric else if (II->isStr("getter") || II->isStr("setter")) { 9380b57cec5SDimitry Andric bool IsSetter = II->getNameStart()[0] == 's'; 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric // getter/setter require extra treatment. 9410b57cec5SDimitry Andric unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter : 9420b57cec5SDimitry Andric diag::err_objc_expected_equal_for_getter; 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric if (ExpectAndConsume(tok::equal, DiagID)) { 9450b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 9460b57cec5SDimitry Andric return; 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 950fe6060f1SDimitry Andric cutOffParsing(); 9510b57cec5SDimitry Andric if (IsSetter) 952*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertySetter( 953*0fca6ea1SDimitry Andric getCurScope()); 9540b57cec5SDimitry Andric else 955*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertyGetter( 956*0fca6ea1SDimitry Andric getCurScope()); 957fe6060f1SDimitry Andric return; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric SourceLocation SelLoc; 9610b57cec5SDimitry Andric IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc); 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric if (!SelIdent) { 9640b57cec5SDimitry Andric Diag(Tok, diag::err_objc_expected_selector_for_getter_setter) 9650b57cec5SDimitry Andric << IsSetter; 9660b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 9670b57cec5SDimitry Andric return; 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric if (IsSetter) { 9715ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_setter); 9720b57cec5SDimitry Andric DS.setSetterName(SelIdent, SelLoc); 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric if (ExpectAndConsume(tok::colon, 9750b57cec5SDimitry Andric diag::err_expected_colon_after_setter_name)) { 9760b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 9770b57cec5SDimitry Andric return; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric } else { 9805ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_getter); 9810b57cec5SDimitry Andric DS.setGetterName(SelIdent, SelLoc); 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric } else if (II->isStr("nonnull")) { 9845ffd83dbSDimitry Andric if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability) 9850b57cec5SDimitry Andric diagnoseRedundantPropertyNullability(*this, DS, 9860b57cec5SDimitry Andric NullabilityKind::NonNull, 9870b57cec5SDimitry Andric Tok.getLocation()); 9885ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability); 9890b57cec5SDimitry Andric DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull); 9900b57cec5SDimitry Andric } else if (II->isStr("nullable")) { 9915ffd83dbSDimitry Andric if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability) 9920b57cec5SDimitry Andric diagnoseRedundantPropertyNullability(*this, DS, 9930b57cec5SDimitry Andric NullabilityKind::Nullable, 9940b57cec5SDimitry Andric Tok.getLocation()); 9955ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability); 9960b57cec5SDimitry Andric DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable); 9970b57cec5SDimitry Andric } else if (II->isStr("null_unspecified")) { 9985ffd83dbSDimitry Andric if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability) 9990b57cec5SDimitry Andric diagnoseRedundantPropertyNullability(*this, DS, 10000b57cec5SDimitry Andric NullabilityKind::Unspecified, 10010b57cec5SDimitry Andric Tok.getLocation()); 10025ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability); 10030b57cec5SDimitry Andric DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); 10040b57cec5SDimitry Andric } else if (II->isStr("null_resettable")) { 10055ffd83dbSDimitry Andric if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability) 10060b57cec5SDimitry Andric diagnoseRedundantPropertyNullability(*this, DS, 10070b57cec5SDimitry Andric NullabilityKind::Unspecified, 10080b57cec5SDimitry Andric Tok.getLocation()); 10095ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability); 10100b57cec5SDimitry Andric DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric // Also set the null_resettable bit. 10135ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable); 10140b57cec5SDimitry Andric } else if (II->isStr("class")) { 10155ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_class); 1016480093f4SDimitry Andric } else if (II->isStr("direct")) { 10175ffd83dbSDimitry Andric DS.setPropertyAttributes(ObjCPropertyAttribute::kind_direct); 10180b57cec5SDimitry Andric } else { 10190b57cec5SDimitry Andric Diag(AttrName, diag::err_objc_expected_property_attr) << II; 10200b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 10210b57cec5SDimitry Andric return; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric if (Tok.isNot(tok::comma)) 10250b57cec5SDimitry Andric break; 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric ConsumeToken(); 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric T.consumeClose(); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric /// objc-method-proto: 10340b57cec5SDimitry Andric /// objc-instance-method objc-method-decl objc-method-attributes[opt] 10350b57cec5SDimitry Andric /// objc-class-method objc-method-decl objc-method-attributes[opt] 10360b57cec5SDimitry Andric /// 10370b57cec5SDimitry Andric /// objc-instance-method: '-' 10380b57cec5SDimitry Andric /// objc-class-method: '+' 10390b57cec5SDimitry Andric /// 10400b57cec5SDimitry Andric /// objc-method-attributes: [OBJC2] 10410b57cec5SDimitry Andric /// __attribute__((deprecated)) 10420b57cec5SDimitry Andric /// 10430b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, 10440b57cec5SDimitry Andric bool MethodDefinition) { 10450b57cec5SDimitry Andric assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-"); 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric tok::TokenKind methodType = Tok.getKind(); 10480b57cec5SDimitry Andric SourceLocation mLoc = ConsumeToken(); 10490b57cec5SDimitry Andric Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind, 10500b57cec5SDimitry Andric MethodDefinition); 10510b57cec5SDimitry Andric // Since this rule is used for both method declarations and definitions, 10520b57cec5SDimitry Andric // the caller is (optionally) responsible for consuming the ';'. 10530b57cec5SDimitry Andric return MDecl; 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric /// objc-selector: 10570b57cec5SDimitry Andric /// identifier 10580b57cec5SDimitry Andric /// one of 10590b57cec5SDimitry Andric /// enum struct union if else while do for switch case default 10600b57cec5SDimitry Andric /// break continue return goto asm sizeof typeof __alignof 10610b57cec5SDimitry Andric /// unsigned long const short volatile signed restrict _Complex 10620b57cec5SDimitry Andric /// in out inout bycopy byref oneway int char float double void _Bool 10630b57cec5SDimitry Andric /// 10640b57cec5SDimitry Andric IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric switch (Tok.getKind()) { 10670b57cec5SDimitry Andric default: 10680b57cec5SDimitry Andric return nullptr; 10690b57cec5SDimitry Andric case tok::colon: 10700b57cec5SDimitry Andric // Empty selector piece uses the location of the ':'. 10710b57cec5SDimitry Andric SelectorLoc = Tok.getLocation(); 10720b57cec5SDimitry Andric return nullptr; 10730b57cec5SDimitry Andric case tok::ampamp: 10740b57cec5SDimitry Andric case tok::ampequal: 10750b57cec5SDimitry Andric case tok::amp: 10760b57cec5SDimitry Andric case tok::pipe: 10770b57cec5SDimitry Andric case tok::tilde: 10780b57cec5SDimitry Andric case tok::exclaim: 10790b57cec5SDimitry Andric case tok::exclaimequal: 10800b57cec5SDimitry Andric case tok::pipepipe: 10810b57cec5SDimitry Andric case tok::pipeequal: 10820b57cec5SDimitry Andric case tok::caret: 10830b57cec5SDimitry Andric case tok::caretequal: { 10840b57cec5SDimitry Andric std::string ThisTok(PP.getSpelling(Tok)); 10850b57cec5SDimitry Andric if (isLetter(ThisTok[0])) { 10860b57cec5SDimitry Andric IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok); 10870b57cec5SDimitry Andric Tok.setKind(tok::identifier); 10880b57cec5SDimitry Andric SelectorLoc = ConsumeToken(); 10890b57cec5SDimitry Andric return II; 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric return nullptr; 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric case tok::identifier: 10950b57cec5SDimitry Andric case tok::kw_asm: 10960b57cec5SDimitry Andric case tok::kw_auto: 10970b57cec5SDimitry Andric case tok::kw_bool: 10980b57cec5SDimitry Andric case tok::kw_break: 10990b57cec5SDimitry Andric case tok::kw_case: 11000b57cec5SDimitry Andric case tok::kw_catch: 11010b57cec5SDimitry Andric case tok::kw_char: 11020b57cec5SDimitry Andric case tok::kw_class: 11030b57cec5SDimitry Andric case tok::kw_const: 11040b57cec5SDimitry Andric case tok::kw_const_cast: 11050b57cec5SDimitry Andric case tok::kw_continue: 11060b57cec5SDimitry Andric case tok::kw_default: 11070b57cec5SDimitry Andric case tok::kw_delete: 11080b57cec5SDimitry Andric case tok::kw_do: 11090b57cec5SDimitry Andric case tok::kw_double: 11100b57cec5SDimitry Andric case tok::kw_dynamic_cast: 11110b57cec5SDimitry Andric case tok::kw_else: 11120b57cec5SDimitry Andric case tok::kw_enum: 11130b57cec5SDimitry Andric case tok::kw_explicit: 11140b57cec5SDimitry Andric case tok::kw_export: 11150b57cec5SDimitry Andric case tok::kw_extern: 11160b57cec5SDimitry Andric case tok::kw_false: 11170b57cec5SDimitry Andric case tok::kw_float: 11180b57cec5SDimitry Andric case tok::kw_for: 11190b57cec5SDimitry Andric case tok::kw_friend: 11200b57cec5SDimitry Andric case tok::kw_goto: 11210b57cec5SDimitry Andric case tok::kw_if: 11220b57cec5SDimitry Andric case tok::kw_inline: 11230b57cec5SDimitry Andric case tok::kw_int: 11240b57cec5SDimitry Andric case tok::kw_long: 11250b57cec5SDimitry Andric case tok::kw_mutable: 11260b57cec5SDimitry Andric case tok::kw_namespace: 11270b57cec5SDimitry Andric case tok::kw_new: 11280b57cec5SDimitry Andric case tok::kw_operator: 11290b57cec5SDimitry Andric case tok::kw_private: 11300b57cec5SDimitry Andric case tok::kw_protected: 11310b57cec5SDimitry Andric case tok::kw_public: 11320b57cec5SDimitry Andric case tok::kw_register: 11330b57cec5SDimitry Andric case tok::kw_reinterpret_cast: 11340b57cec5SDimitry Andric case tok::kw_restrict: 11350b57cec5SDimitry Andric case tok::kw_return: 11360b57cec5SDimitry Andric case tok::kw_short: 11370b57cec5SDimitry Andric case tok::kw_signed: 11380b57cec5SDimitry Andric case tok::kw_sizeof: 11390b57cec5SDimitry Andric case tok::kw_static: 11400b57cec5SDimitry Andric case tok::kw_static_cast: 11410b57cec5SDimitry Andric case tok::kw_struct: 11420b57cec5SDimitry Andric case tok::kw_switch: 11430b57cec5SDimitry Andric case tok::kw_template: 11440b57cec5SDimitry Andric case tok::kw_this: 11450b57cec5SDimitry Andric case tok::kw_throw: 11460b57cec5SDimitry Andric case tok::kw_true: 11470b57cec5SDimitry Andric case tok::kw_try: 11480b57cec5SDimitry Andric case tok::kw_typedef: 11490b57cec5SDimitry Andric case tok::kw_typeid: 11500b57cec5SDimitry Andric case tok::kw_typename: 11510b57cec5SDimitry Andric case tok::kw_typeof: 11520b57cec5SDimitry Andric case tok::kw_union: 11530b57cec5SDimitry Andric case tok::kw_unsigned: 11540b57cec5SDimitry Andric case tok::kw_using: 11550b57cec5SDimitry Andric case tok::kw_virtual: 11560b57cec5SDimitry Andric case tok::kw_void: 11570b57cec5SDimitry Andric case tok::kw_volatile: 11580b57cec5SDimitry Andric case tok::kw_wchar_t: 11590b57cec5SDimitry Andric case tok::kw_while: 11600b57cec5SDimitry Andric case tok::kw__Bool: 11610b57cec5SDimitry Andric case tok::kw__Complex: 11620b57cec5SDimitry Andric case tok::kw___alignof: 11630b57cec5SDimitry Andric case tok::kw___auto_type: 11640b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo(); 11650b57cec5SDimitry Andric SelectorLoc = ConsumeToken(); 11660b57cec5SDimitry Andric return II; 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric /// objc-for-collection-in: 'in' 11710b57cec5SDimitry Andric /// 11720b57cec5SDimitry Andric bool Parser::isTokIdentifier_in() const { 11730b57cec5SDimitry Andric // FIXME: May have to do additional look-ahead to only allow for 11740b57cec5SDimitry Andric // valid tokens following an 'in'; such as an identifier, unary operators, 11750b57cec5SDimitry Andric // '[' etc. 11760b57cec5SDimitry Andric return (getLangOpts().ObjC && Tok.is(tok::identifier) && 11770b57cec5SDimitry Andric Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); 11780b57cec5SDimitry Andric } 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric /// ParseObjCTypeQualifierList - This routine parses the objective-c's type 11810b57cec5SDimitry Andric /// qualifier list and builds their bitmask representation in the input 11820b57cec5SDimitry Andric /// argument. 11830b57cec5SDimitry Andric /// 11840b57cec5SDimitry Andric /// objc-type-qualifiers: 11850b57cec5SDimitry Andric /// objc-type-qualifier 11860b57cec5SDimitry Andric /// objc-type-qualifiers objc-type-qualifier 11870b57cec5SDimitry Andric /// 11880b57cec5SDimitry Andric /// objc-type-qualifier: 11890b57cec5SDimitry Andric /// 'in' 11900b57cec5SDimitry Andric /// 'out' 11910b57cec5SDimitry Andric /// 'inout' 11920b57cec5SDimitry Andric /// 'oneway' 11930b57cec5SDimitry Andric /// 'bycopy' 11940b57cec5SDimitry Andric /// 'byref' 11950b57cec5SDimitry Andric /// 'nonnull' 11960b57cec5SDimitry Andric /// 'nullable' 11970b57cec5SDimitry Andric /// 'null_unspecified' 11980b57cec5SDimitry Andric /// 11990b57cec5SDimitry Andric void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, 12000b57cec5SDimitry Andric DeclaratorContext Context) { 1201e8d8bef9SDimitry Andric assert(Context == DeclaratorContext::ObjCParameter || 1202e8d8bef9SDimitry Andric Context == DeclaratorContext::ObjCResult); 12030b57cec5SDimitry Andric 120404eeddc0SDimitry Andric while (true) { 12050b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1206fe6060f1SDimitry Andric cutOffParsing(); 1207*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPassingType( 1208e8d8bef9SDimitry Andric getCurScope(), DS, Context == DeclaratorContext::ObjCParameter); 1209fe6060f1SDimitry Andric return; 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric 12120b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) 12130b57cec5SDimitry Andric return; 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric const IdentifierInfo *II = Tok.getIdentifierInfo(); 12160b57cec5SDimitry Andric for (unsigned i = 0; i != objc_NumQuals; ++i) { 12170b57cec5SDimitry Andric if (II != ObjCTypeQuals[i] || 12180b57cec5SDimitry Andric NextToken().is(tok::less) || 12190b57cec5SDimitry Andric NextToken().is(tok::coloncolon)) 12200b57cec5SDimitry Andric continue; 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric ObjCDeclSpec::ObjCDeclQualifier Qual; 12230b57cec5SDimitry Andric NullabilityKind Nullability; 12240b57cec5SDimitry Andric switch (i) { 12250b57cec5SDimitry Andric default: llvm_unreachable("Unknown decl qualifier"); 12260b57cec5SDimitry Andric case objc_in: Qual = ObjCDeclSpec::DQ_In; break; 12270b57cec5SDimitry Andric case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; 12280b57cec5SDimitry Andric case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; 12290b57cec5SDimitry Andric case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; 12300b57cec5SDimitry Andric case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; 12310b57cec5SDimitry Andric case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric case objc_nonnull: 12340b57cec5SDimitry Andric Qual = ObjCDeclSpec::DQ_CSNullability; 12350b57cec5SDimitry Andric Nullability = NullabilityKind::NonNull; 12360b57cec5SDimitry Andric break; 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric case objc_nullable: 12390b57cec5SDimitry Andric Qual = ObjCDeclSpec::DQ_CSNullability; 12400b57cec5SDimitry Andric Nullability = NullabilityKind::Nullable; 12410b57cec5SDimitry Andric break; 12420b57cec5SDimitry Andric 12430b57cec5SDimitry Andric case objc_null_unspecified: 12440b57cec5SDimitry Andric Qual = ObjCDeclSpec::DQ_CSNullability; 12450b57cec5SDimitry Andric Nullability = NullabilityKind::Unspecified; 12460b57cec5SDimitry Andric break; 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andric // FIXME: Diagnose redundant specifiers. 12500b57cec5SDimitry Andric DS.setObjCDeclQualifier(Qual); 12510b57cec5SDimitry Andric if (Qual == ObjCDeclSpec::DQ_CSNullability) 12520b57cec5SDimitry Andric DS.setNullability(Tok.getLocation(), Nullability); 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric ConsumeToken(); 12550b57cec5SDimitry Andric II = nullptr; 12560b57cec5SDimitry Andric break; 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric // If this wasn't a recognized qualifier, bail out. 12600b57cec5SDimitry Andric if (II) return; 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric /// Take all the decl attributes out of the given list and add 12650b57cec5SDimitry Andric /// them to the given attribute set. 12660b57cec5SDimitry Andric static void takeDeclAttributes(ParsedAttributesView &attrs, 12670b57cec5SDimitry Andric ParsedAttributesView &from) { 12680b57cec5SDimitry Andric for (auto &AL : llvm::reverse(from)) { 12690b57cec5SDimitry Andric if (!AL.isUsedAsTypeAttr()) { 12700b57cec5SDimitry Andric from.remove(&AL); 12710b57cec5SDimitry Andric attrs.addAtEnd(&AL); 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric } 12750b57cec5SDimitry Andric 12760b57cec5SDimitry Andric /// takeDeclAttributes - Take all the decl attributes from the given 12770b57cec5SDimitry Andric /// declarator and add them to the given list. 12780b57cec5SDimitry Andric static void takeDeclAttributes(ParsedAttributes &attrs, 12790b57cec5SDimitry Andric Declarator &D) { 128081ad6265SDimitry Andric // This gets called only from Parser::ParseObjCTypeName(), and that should 128181ad6265SDimitry Andric // never add declaration attributes to the Declarator. 128281ad6265SDimitry Andric assert(D.getDeclarationAttributes().empty()); 128381ad6265SDimitry Andric 12840b57cec5SDimitry Andric // First, take ownership of all attributes. 12850b57cec5SDimitry Andric attrs.getPool().takeAllFrom(D.getAttributePool()); 12860b57cec5SDimitry Andric attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); 12870b57cec5SDimitry Andric 12880b57cec5SDimitry Andric // Now actually move the attributes over. 12890b57cec5SDimitry Andric takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes()); 12900b57cec5SDimitry Andric takeDeclAttributes(attrs, D.getAttributes()); 12910b57cec5SDimitry Andric for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) 12920b57cec5SDimitry Andric takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs()); 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric /// objc-type-name: 12960b57cec5SDimitry Andric /// '(' objc-type-qualifiers[opt] type-name ')' 12970b57cec5SDimitry Andric /// '(' objc-type-qualifiers[opt] ')' 12980b57cec5SDimitry Andric /// 12990b57cec5SDimitry Andric ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, 13000b57cec5SDimitry Andric DeclaratorContext context, 13010b57cec5SDimitry Andric ParsedAttributes *paramAttrs) { 1302e8d8bef9SDimitry Andric assert(context == DeclaratorContext::ObjCParameter || 1303e8d8bef9SDimitry Andric context == DeclaratorContext::ObjCResult); 13040b57cec5SDimitry Andric assert((paramAttrs != nullptr) == 1305e8d8bef9SDimitry Andric (context == DeclaratorContext::ObjCParameter)); 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric assert(Tok.is(tok::l_paren) && "expected ("); 13080b57cec5SDimitry Andric 13090b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 13100b57cec5SDimitry Andric T.consumeOpen(); 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric ObjCDeclContextSwitch ObjCDC(*this); 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andric // Parse type qualifiers, in, inout, etc. 13150b57cec5SDimitry Andric ParseObjCTypeQualifierList(DS, context); 13160b57cec5SDimitry Andric SourceLocation TypeStartLoc = Tok.getLocation(); 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric ParsedType Ty; 13190b57cec5SDimitry Andric if (isTypeSpecifierQualifier() || isObjCInstancetype()) { 13200b57cec5SDimitry Andric // Parse an abstract declarator. 13210b57cec5SDimitry Andric DeclSpec declSpec(AttrFactory); 13220b57cec5SDimitry Andric declSpec.setObjCQualifiers(&DS); 13230b57cec5SDimitry Andric DeclSpecContext dsContext = DeclSpecContext::DSC_normal; 1324e8d8bef9SDimitry Andric if (context == DeclaratorContext::ObjCResult) 13250b57cec5SDimitry Andric dsContext = DeclSpecContext::DSC_objc_method_result; 13260b57cec5SDimitry Andric ParseSpecifierQualifierList(declSpec, AS_none, dsContext); 132781ad6265SDimitry Andric Declarator declarator(declSpec, ParsedAttributesView::none(), context); 13280b57cec5SDimitry Andric ParseDeclarator(declarator); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric // If that's not invalid, extract a type. 13310b57cec5SDimitry Andric if (!declarator.isInvalidType()) { 13320b57cec5SDimitry Andric // Map a nullability specifier to a context-sensitive keyword attribute. 13330b57cec5SDimitry Andric bool addedToDeclSpec = false; 13340b57cec5SDimitry Andric if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) 13350b57cec5SDimitry Andric addContextSensitiveTypeNullability(*this, declarator, 13360b57cec5SDimitry Andric DS.getNullability(), 13370b57cec5SDimitry Andric DS.getNullabilityLoc(), 13380b57cec5SDimitry Andric addedToDeclSpec); 13390b57cec5SDimitry Andric 13407a6dacacSDimitry Andric TypeResult type = Actions.ActOnTypeName(declarator); 13410b57cec5SDimitry Andric if (!type.isInvalid()) 13420b57cec5SDimitry Andric Ty = type.get(); 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric // If we're parsing a parameter, steal all the decl attributes 13450b57cec5SDimitry Andric // and add them to the decl spec. 1346e8d8bef9SDimitry Andric if (context == DeclaratorContext::ObjCParameter) 13470b57cec5SDimitry Andric takeDeclAttributes(*paramAttrs, declarator); 13480b57cec5SDimitry Andric } 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric if (Tok.is(tok::r_paren)) 13520b57cec5SDimitry Andric T.consumeClose(); 13530b57cec5SDimitry Andric else if (Tok.getLocation() == TypeStartLoc) { 13540b57cec5SDimitry Andric // If we didn't eat any tokens, then this isn't a type. 13550b57cec5SDimitry Andric Diag(Tok, diag::err_expected_type); 13560b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 13570b57cec5SDimitry Andric } else { 13580b57cec5SDimitry Andric // Otherwise, we found *something*, but didn't get a ')' in the right 13590b57cec5SDimitry Andric // place. Emit an error then return what we have as the type. 13600b57cec5SDimitry Andric T.consumeClose(); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric return Ty; 13630b57cec5SDimitry Andric } 13640b57cec5SDimitry Andric 13650b57cec5SDimitry Andric /// objc-method-decl: 13660b57cec5SDimitry Andric /// objc-selector 13670b57cec5SDimitry Andric /// objc-keyword-selector objc-parmlist[opt] 13680b57cec5SDimitry Andric /// objc-type-name objc-selector 13690b57cec5SDimitry Andric /// objc-type-name objc-keyword-selector objc-parmlist[opt] 13700b57cec5SDimitry Andric /// 13710b57cec5SDimitry Andric /// objc-keyword-selector: 13720b57cec5SDimitry Andric /// objc-keyword-decl 13730b57cec5SDimitry Andric /// objc-keyword-selector objc-keyword-decl 13740b57cec5SDimitry Andric /// 13750b57cec5SDimitry Andric /// objc-keyword-decl: 13760b57cec5SDimitry Andric /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier 13770b57cec5SDimitry Andric /// objc-selector ':' objc-keyword-attributes[opt] identifier 13780b57cec5SDimitry Andric /// ':' objc-type-name objc-keyword-attributes[opt] identifier 13790b57cec5SDimitry Andric /// ':' objc-keyword-attributes[opt] identifier 13800b57cec5SDimitry Andric /// 13810b57cec5SDimitry Andric /// objc-parmlist: 13820b57cec5SDimitry Andric /// objc-parms objc-ellipsis[opt] 13830b57cec5SDimitry Andric /// 13840b57cec5SDimitry Andric /// objc-parms: 13850b57cec5SDimitry Andric /// objc-parms , parameter-declaration 13860b57cec5SDimitry Andric /// 13870b57cec5SDimitry Andric /// objc-ellipsis: 13880b57cec5SDimitry Andric /// , ... 13890b57cec5SDimitry Andric /// 13900b57cec5SDimitry Andric /// objc-keyword-attributes: [OBJC2] 13910b57cec5SDimitry Andric /// __attribute__((unused)) 13920b57cec5SDimitry Andric /// 13930b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, 13940b57cec5SDimitry Andric tok::TokenKind mType, 13950b57cec5SDimitry Andric tok::ObjCKeywordKind MethodImplKind, 13960b57cec5SDimitry Andric bool MethodDefinition) { 13970b57cec5SDimitry Andric ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1400fe6060f1SDimitry Andric cutOffParsing(); 1401*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCMethodDecl(getCurScope(), 1402*0fca6ea1SDimitry Andric mType == tok::minus, 14030b57cec5SDimitry Andric /*ReturnType=*/nullptr); 14040b57cec5SDimitry Andric return nullptr; 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric // Parse the return type if present. 14080b57cec5SDimitry Andric ParsedType ReturnType; 14090b57cec5SDimitry Andric ObjCDeclSpec DSRet; 14100b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) 1411e8d8bef9SDimitry Andric ReturnType = 1412e8d8bef9SDimitry Andric ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResult, nullptr); 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric // If attributes exist before the method, parse them. 14150b57cec5SDimitry Andric ParsedAttributes methodAttrs(AttrFactory); 1416fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), 1417fe6060f1SDimitry Andric methodAttrs); 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1420fe6060f1SDimitry Andric cutOffParsing(); 1421*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCMethodDecl( 1422*0fca6ea1SDimitry Andric getCurScope(), mType == tok::minus, ReturnType); 14230b57cec5SDimitry Andric return nullptr; 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric // Now parse the selector. 14270b57cec5SDimitry Andric SourceLocation selLoc; 14280b57cec5SDimitry Andric IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc); 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric // An unnamed colon is valid. 14310b57cec5SDimitry Andric if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name. 14320b57cec5SDimitry Andric Diag(Tok, diag::err_expected_selector_for_method) 14330b57cec5SDimitry Andric << SourceRange(mLoc, Tok.getLocation()); 14340b57cec5SDimitry Andric // Skip until we get a ; or @. 14350b57cec5SDimitry Andric SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); 14360b57cec5SDimitry Andric return nullptr; 14370b57cec5SDimitry Andric } 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; 14400b57cec5SDimitry Andric if (Tok.isNot(tok::colon)) { 14410b57cec5SDimitry Andric // If attributes exist after the method, parse them. 1442fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), 1443fe6060f1SDimitry Andric methodAttrs); 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); 1446*0fca6ea1SDimitry Andric Decl *Result = Actions.ObjC().ActOnMethodDeclaration( 14470b57cec5SDimitry Andric getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, 14480b57cec5SDimitry Andric selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, 14490b57cec5SDimitry Andric MethodImplKind, false, MethodDefinition); 14500b57cec5SDimitry Andric PD.complete(Result); 14510b57cec5SDimitry Andric return Result; 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric 1454*0fca6ea1SDimitry Andric SmallVector<const IdentifierInfo *, 12> KeyIdents; 14550b57cec5SDimitry Andric SmallVector<SourceLocation, 12> KeyLocs; 1456*0fca6ea1SDimitry Andric SmallVector<SemaObjC::ObjCArgInfo, 12> ArgInfos; 14570b57cec5SDimitry Andric ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | 14580b57cec5SDimitry Andric Scope::FunctionDeclarationScope | Scope::DeclScope); 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric AttributePool allParamAttrs(AttrFactory); 146104eeddc0SDimitry Andric while (true) { 14620b57cec5SDimitry Andric ParsedAttributes paramAttrs(AttrFactory); 1463*0fca6ea1SDimitry Andric SemaObjC::ObjCArgInfo ArgInfo; 14640b57cec5SDimitry Andric 14650b57cec5SDimitry Andric // Each iteration parses a single keyword argument. 14660b57cec5SDimitry Andric if (ExpectAndConsume(tok::colon)) 14670b57cec5SDimitry Andric break; 14680b57cec5SDimitry Andric 14690b57cec5SDimitry Andric ArgInfo.Type = nullptr; 14700b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) // Parse the argument type if present. 1471e8d8bef9SDimitry Andric ArgInfo.Type = ParseObjCTypeName( 1472e8d8bef9SDimitry Andric ArgInfo.DeclSpec, DeclaratorContext::ObjCParameter, ¶mAttrs); 14730b57cec5SDimitry Andric 14740b57cec5SDimitry Andric // If attributes exist before the argument name, parse them. 14750b57cec5SDimitry Andric // Regardless, collect all the attributes we've parsed so far. 1476fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), 1477fe6060f1SDimitry Andric paramAttrs); 14780b57cec5SDimitry Andric ArgInfo.ArgAttrs = paramAttrs; 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric // Code completion for the next piece of the selector. 14810b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1482fe6060f1SDimitry Andric cutOffParsing(); 14830b57cec5SDimitry Andric KeyIdents.push_back(SelIdent); 1484*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector( 1485*0fca6ea1SDimitry Andric getCurScope(), mType == tok::minus, 1486*0fca6ea1SDimitry Andric /*AtParameterName=*/true, ReturnType, KeyIdents); 14870b57cec5SDimitry Andric return nullptr; 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric if (expectIdentifier()) 14910b57cec5SDimitry Andric break; // missing argument name. 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric ArgInfo.Name = Tok.getIdentifierInfo(); 14940b57cec5SDimitry Andric ArgInfo.NameLoc = Tok.getLocation(); 14950b57cec5SDimitry Andric ConsumeToken(); // Eat the identifier. 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric ArgInfos.push_back(ArgInfo); 14980b57cec5SDimitry Andric KeyIdents.push_back(SelIdent); 14990b57cec5SDimitry Andric KeyLocs.push_back(selLoc); 15000b57cec5SDimitry Andric 15010b57cec5SDimitry Andric // Make sure the attributes persist. 15020b57cec5SDimitry Andric allParamAttrs.takeAllFrom(paramAttrs.getPool()); 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric // Code completion for the next piece of the selector. 15050b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1506fe6060f1SDimitry Andric cutOffParsing(); 1507*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector( 1508*0fca6ea1SDimitry Andric getCurScope(), mType == tok::minus, 1509*0fca6ea1SDimitry Andric /*AtParameterName=*/false, ReturnType, KeyIdents); 15100b57cec5SDimitry Andric return nullptr; 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andric // Check for another keyword selector. 15140b57cec5SDimitry Andric SelIdent = ParseObjCSelectorPiece(selLoc); 15150b57cec5SDimitry Andric if (!SelIdent && Tok.isNot(tok::colon)) 15160b57cec5SDimitry Andric break; 15170b57cec5SDimitry Andric if (!SelIdent) { 15180b57cec5SDimitry Andric SourceLocation ColonLoc = Tok.getLocation(); 15190b57cec5SDimitry Andric if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) { 15200b57cec5SDimitry Andric Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name; 15210b57cec5SDimitry Andric Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name; 15220b57cec5SDimitry Andric Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name; 15230b57cec5SDimitry Andric } 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric // We have a selector or a colon, continue parsing. 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric bool isVariadic = false; 15290b57cec5SDimitry Andric bool cStyleParamWarned = false; 15300b57cec5SDimitry Andric // Parse the (optional) parameter list. 15310b57cec5SDimitry Andric while (Tok.is(tok::comma)) { 15320b57cec5SDimitry Andric ConsumeToken(); 15330b57cec5SDimitry Andric if (Tok.is(tok::ellipsis)) { 15340b57cec5SDimitry Andric isVariadic = true; 15350b57cec5SDimitry Andric ConsumeToken(); 15360b57cec5SDimitry Andric break; 15370b57cec5SDimitry Andric } 15380b57cec5SDimitry Andric if (!cStyleParamWarned) { 15390b57cec5SDimitry Andric Diag(Tok, diag::warn_cstyle_param); 15400b57cec5SDimitry Andric cStyleParamWarned = true; 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 1543*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo; 1544*0fca6ea1SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo); 15450b57cec5SDimitry Andric // Parse the declarator. 154681ad6265SDimitry Andric Declarator ParmDecl(DS, ParsedAttributesView::none(), 154781ad6265SDimitry Andric DeclaratorContext::Prototype); 15480b57cec5SDimitry Andric ParseDeclarator(ParmDecl); 1549*0fca6ea1SDimitry Andric const IdentifierInfo *ParmII = ParmDecl.getIdentifier(); 15500b57cec5SDimitry Andric Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); 15510b57cec5SDimitry Andric CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, 15520b57cec5SDimitry Andric ParmDecl.getIdentifierLoc(), 15530b57cec5SDimitry Andric Param, 15540b57cec5SDimitry Andric nullptr)); 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric // FIXME: Add support for optional parameter list... 15580b57cec5SDimitry Andric // If attributes exist after the method, parse them. 1559fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), 1560fe6060f1SDimitry Andric methodAttrs); 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andric if (KeyIdents.size() == 0) 15630b57cec5SDimitry Andric return nullptr; 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), 15660b57cec5SDimitry Andric &KeyIdents[0]); 1567*0fca6ea1SDimitry Andric Decl *Result = Actions.ObjC().ActOnMethodDeclaration( 15680b57cec5SDimitry Andric getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, 15690b57cec5SDimitry Andric Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, 15700b57cec5SDimitry Andric MethodImplKind, isVariadic, MethodDefinition); 15710b57cec5SDimitry Andric 15720b57cec5SDimitry Andric PD.complete(Result); 15730b57cec5SDimitry Andric return Result; 15740b57cec5SDimitry Andric } 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric /// objc-protocol-refs: 15770b57cec5SDimitry Andric /// '<' identifier-list '>' 15780b57cec5SDimitry Andric /// 15790b57cec5SDimitry Andric bool Parser:: 15800b57cec5SDimitry Andric ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, 15810b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &ProtocolLocs, 15820b57cec5SDimitry Andric bool WarnOnDeclarations, bool ForObjCContainer, 15830b57cec5SDimitry Andric SourceLocation &LAngleLoc, SourceLocation &EndLoc, 15840b57cec5SDimitry Andric bool consumeLastToken) { 15850b57cec5SDimitry Andric assert(Tok.is(tok::less) && "expected <"); 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric LAngleLoc = ConsumeToken(); // the "<" 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 8> ProtocolIdents; 15900b57cec5SDimitry Andric 159104eeddc0SDimitry Andric while (true) { 15920b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 15930b57cec5SDimitry Andric cutOffParsing(); 1594*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( 1595*0fca6ea1SDimitry Andric ProtocolIdents); 15960b57cec5SDimitry Andric return true; 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric if (expectIdentifier()) { 16000b57cec5SDimitry Andric SkipUntil(tok::greater, StopAtSemi); 16010b57cec5SDimitry Andric return true; 16020b57cec5SDimitry Andric } 16030b57cec5SDimitry Andric ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(), 16040b57cec5SDimitry Andric Tok.getLocation())); 16050b57cec5SDimitry Andric ProtocolLocs.push_back(Tok.getLocation()); 16060b57cec5SDimitry Andric ConsumeToken(); 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) 16090b57cec5SDimitry Andric break; 16100b57cec5SDimitry Andric } 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric // Consume the '>'. 16135ffd83dbSDimitry Andric if (ParseGreaterThanInTemplateList(LAngleLoc, EndLoc, consumeLastToken, 16140b57cec5SDimitry Andric /*ObjCGenericList=*/false)) 16150b57cec5SDimitry Andric return true; 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric // Convert the list of protocols identifiers into a list of protocol decls. 1618*0fca6ea1SDimitry Andric Actions.ObjC().FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, 16190b57cec5SDimitry Andric ProtocolIdents, Protocols); 16200b57cec5SDimitry Andric return false; 16210b57cec5SDimitry Andric } 16220b57cec5SDimitry Andric 16230b57cec5SDimitry Andric TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) { 16240b57cec5SDimitry Andric assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'"); 16250b57cec5SDimitry Andric assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C"); 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric SourceLocation lAngleLoc; 16280b57cec5SDimitry Andric SmallVector<Decl *, 8> protocols; 16290b57cec5SDimitry Andric SmallVector<SourceLocation, 8> protocolLocs; 16300b57cec5SDimitry Andric (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false, 16310b57cec5SDimitry Andric lAngleLoc, rAngleLoc, 16320b57cec5SDimitry Andric /*consumeLastToken=*/true); 1633*0fca6ea1SDimitry Andric TypeResult result = Actions.ObjC().actOnObjCProtocolQualifierType( 1634*0fca6ea1SDimitry Andric lAngleLoc, protocols, protocolLocs, rAngleLoc); 16350b57cec5SDimitry Andric if (result.isUsable()) { 16360b57cec5SDimitry Andric Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id) 16370b57cec5SDimitry Andric << FixItHint::CreateInsertion(lAngleLoc, "id") 16380b57cec5SDimitry Andric << SourceRange(lAngleLoc, rAngleLoc); 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric return result; 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric /// Parse Objective-C type arguments or protocol qualifiers. 16450b57cec5SDimitry Andric /// 16460b57cec5SDimitry Andric /// objc-type-arguments: 16470b57cec5SDimitry Andric /// '<' type-name '...'[opt] (',' type-name '...'[opt])* '>' 16480b57cec5SDimitry Andric /// 16490b57cec5SDimitry Andric void Parser::parseObjCTypeArgsOrProtocolQualifiers( 16500b57cec5SDimitry Andric ParsedType baseType, 16510b57cec5SDimitry Andric SourceLocation &typeArgsLAngleLoc, 16520b57cec5SDimitry Andric SmallVectorImpl<ParsedType> &typeArgs, 16530b57cec5SDimitry Andric SourceLocation &typeArgsRAngleLoc, 16540b57cec5SDimitry Andric SourceLocation &protocolLAngleLoc, 16550b57cec5SDimitry Andric SmallVectorImpl<Decl *> &protocols, 16560b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &protocolLocs, 16570b57cec5SDimitry Andric SourceLocation &protocolRAngleLoc, 16580b57cec5SDimitry Andric bool consumeLastToken, 16590b57cec5SDimitry Andric bool warnOnIncompleteProtocols) { 16600b57cec5SDimitry Andric assert(Tok.is(tok::less) && "Not at the start of type args or protocols"); 16610b57cec5SDimitry Andric SourceLocation lAngleLoc = ConsumeToken(); 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric // Whether all of the elements we've parsed thus far are single 16640b57cec5SDimitry Andric // identifiers, which might be types or might be protocols. 16650b57cec5SDimitry Andric bool allSingleIdentifiers = true; 16660b57cec5SDimitry Andric SmallVector<IdentifierInfo *, 4> identifiers; 16670b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs; 16680b57cec5SDimitry Andric 16690b57cec5SDimitry Andric // Parse a list of comma-separated identifiers, bailing out if we 16700b57cec5SDimitry Andric // see something different. 16710b57cec5SDimitry Andric do { 16720b57cec5SDimitry Andric // Parse a single identifier. 16730b57cec5SDimitry Andric if (Tok.is(tok::identifier) && 16740b57cec5SDimitry Andric (NextToken().is(tok::comma) || 16750b57cec5SDimitry Andric NextToken().is(tok::greater) || 16760b57cec5SDimitry Andric NextToken().is(tok::greatergreater))) { 16770b57cec5SDimitry Andric identifiers.push_back(Tok.getIdentifierInfo()); 16780b57cec5SDimitry Andric identifierLocs.push_back(ConsumeToken()); 16790b57cec5SDimitry Andric continue; 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 16830b57cec5SDimitry Andric // FIXME: Also include types here. 16840b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 4> identifierLocPairs; 16850b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 16860b57cec5SDimitry Andric identifierLocPairs.push_back(IdentifierLocPair(identifiers[i], 16870b57cec5SDimitry Andric identifierLocs[i])); 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric QualType BaseT = Actions.GetTypeFromParser(baseType); 1691fe6060f1SDimitry Andric cutOffParsing(); 16920b57cec5SDimitry Andric if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) { 1693*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteOrdinaryName( 1694*0fca6ea1SDimitry Andric getCurScope(), SemaCodeCompletion::PCC_Type); 16950b57cec5SDimitry Andric } else { 1696*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( 1697*0fca6ea1SDimitry Andric identifierLocPairs); 16980b57cec5SDimitry Andric } 16990b57cec5SDimitry Andric return; 17000b57cec5SDimitry Andric } 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric allSingleIdentifiers = false; 17030b57cec5SDimitry Andric break; 17040b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma)); 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric // If we parsed an identifier list, semantic analysis sorts out 17070b57cec5SDimitry Andric // whether it refers to protocols or to type arguments. 17080b57cec5SDimitry Andric if (allSingleIdentifiers) { 17090b57cec5SDimitry Andric // Parse the closing '>'. 17100b57cec5SDimitry Andric SourceLocation rAngleLoc; 17115ffd83dbSDimitry Andric (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken, 17120b57cec5SDimitry Andric /*ObjCGenericList=*/true); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric // Let Sema figure out what we parsed. 1715*0fca6ea1SDimitry Andric Actions.ObjC().actOnObjCTypeArgsOrProtocolQualifiers( 1716*0fca6ea1SDimitry Andric getCurScope(), baseType, lAngleLoc, identifiers, identifierLocs, 1717*0fca6ea1SDimitry Andric rAngleLoc, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, 1718*0fca6ea1SDimitry Andric protocolLAngleLoc, protocols, protocolRAngleLoc, 17190b57cec5SDimitry Andric warnOnIncompleteProtocols); 17200b57cec5SDimitry Andric return; 17210b57cec5SDimitry Andric } 17220b57cec5SDimitry Andric 17230b57cec5SDimitry Andric // We parsed an identifier list but stumbled into non single identifiers, this 17240b57cec5SDimitry Andric // means we might (a) check that what we already parsed is a legitimate type 17250b57cec5SDimitry Andric // (not a protocol or unknown type) and (b) parse the remaining ones, which 17260b57cec5SDimitry Andric // must all be type args. 17270b57cec5SDimitry Andric 17280b57cec5SDimitry Andric // Convert the identifiers into type arguments. 17290b57cec5SDimitry Andric bool invalid = false; 17300b57cec5SDimitry Andric IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr; 17310b57cec5SDimitry Andric SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc; 17320b57cec5SDimitry Andric SmallVector<IdentifierInfo *, 2> unknownTypeArgs; 17330b57cec5SDimitry Andric SmallVector<SourceLocation, 2> unknownTypeArgsLoc; 17340b57cec5SDimitry Andric 17350b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 17360b57cec5SDimitry Andric ParsedType typeArg 17370b57cec5SDimitry Andric = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope()); 17380b57cec5SDimitry Andric if (typeArg) { 17390b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 17400b57cec5SDimitry Andric const char *prevSpec = nullptr; 17410b57cec5SDimitry Andric unsigned diagID; 17420b57cec5SDimitry Andric DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID, 17430b57cec5SDimitry Andric typeArg, Actions.getASTContext().getPrintingPolicy()); 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric // Form a declarator to turn this into a type. 174681ad6265SDimitry Andric Declarator D(DS, ParsedAttributesView::none(), 174781ad6265SDimitry Andric DeclaratorContext::TypeName); 17487a6dacacSDimitry Andric TypeResult fullTypeArg = Actions.ActOnTypeName(D); 17490b57cec5SDimitry Andric if (fullTypeArg.isUsable()) { 17500b57cec5SDimitry Andric typeArgs.push_back(fullTypeArg.get()); 17510b57cec5SDimitry Andric if (!foundValidTypeId) { 17520b57cec5SDimitry Andric foundValidTypeId = identifiers[i]; 17530b57cec5SDimitry Andric foundValidTypeSrcLoc = identifierLocs[i]; 17540b57cec5SDimitry Andric } 17550b57cec5SDimitry Andric } else { 17560b57cec5SDimitry Andric invalid = true; 17570b57cec5SDimitry Andric unknownTypeArgs.push_back(identifiers[i]); 17580b57cec5SDimitry Andric unknownTypeArgsLoc.push_back(identifierLocs[i]); 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric } else { 17610b57cec5SDimitry Andric invalid = true; 1762*0fca6ea1SDimitry Andric if (!Actions.ObjC().LookupProtocol(identifiers[i], identifierLocs[i])) { 17630b57cec5SDimitry Andric unknownTypeArgs.push_back(identifiers[i]); 17640b57cec5SDimitry Andric unknownTypeArgsLoc.push_back(identifierLocs[i]); 17650b57cec5SDimitry Andric } else if (!foundProtocolId) { 17660b57cec5SDimitry Andric foundProtocolId = identifiers[i]; 17670b57cec5SDimitry Andric foundProtocolSrcLoc = identifierLocs[i]; 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric } 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric // Continue parsing type-names. 17730b57cec5SDimitry Andric do { 17740b57cec5SDimitry Andric Token CurTypeTok = Tok; 17750b57cec5SDimitry Andric TypeResult typeArg = ParseTypeName(); 17760b57cec5SDimitry Andric 17770b57cec5SDimitry Andric // Consume the '...' for a pack expansion. 17780b57cec5SDimitry Andric SourceLocation ellipsisLoc; 17790b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, ellipsisLoc); 17800b57cec5SDimitry Andric if (typeArg.isUsable() && ellipsisLoc.isValid()) { 17810b57cec5SDimitry Andric typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc); 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric if (typeArg.isUsable()) { 17850b57cec5SDimitry Andric typeArgs.push_back(typeArg.get()); 17860b57cec5SDimitry Andric if (!foundValidTypeId) { 17870b57cec5SDimitry Andric foundValidTypeId = CurTypeTok.getIdentifierInfo(); 17880b57cec5SDimitry Andric foundValidTypeSrcLoc = CurTypeTok.getLocation(); 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric } else { 17910b57cec5SDimitry Andric invalid = true; 17920b57cec5SDimitry Andric } 17930b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma)); 17940b57cec5SDimitry Andric 17950b57cec5SDimitry Andric // Diagnose the mix between type args and protocols. 17960b57cec5SDimitry Andric if (foundProtocolId && foundValidTypeId) 1797*0fca6ea1SDimitry Andric Actions.ObjC().DiagnoseTypeArgsAndProtocols( 1798*0fca6ea1SDimitry Andric foundProtocolId, foundProtocolSrcLoc, foundValidTypeId, 17990b57cec5SDimitry Andric foundValidTypeSrcLoc); 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric // Diagnose unknown arg types. 18020b57cec5SDimitry Andric ParsedType T; 18030b57cec5SDimitry Andric if (unknownTypeArgs.size()) 18040b57cec5SDimitry Andric for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i) 18050b57cec5SDimitry Andric Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i], 18060b57cec5SDimitry Andric getCurScope(), nullptr, T); 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric // Parse the closing '>'. 18090b57cec5SDimitry Andric SourceLocation rAngleLoc; 18105ffd83dbSDimitry Andric (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken, 18110b57cec5SDimitry Andric /*ObjCGenericList=*/true); 18120b57cec5SDimitry Andric 18130b57cec5SDimitry Andric if (invalid) { 18140b57cec5SDimitry Andric typeArgs.clear(); 18150b57cec5SDimitry Andric return; 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric // Record left/right angle locations. 18190b57cec5SDimitry Andric typeArgsLAngleLoc = lAngleLoc; 18200b57cec5SDimitry Andric typeArgsRAngleLoc = rAngleLoc; 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 18230b57cec5SDimitry Andric void Parser::parseObjCTypeArgsAndProtocolQualifiers( 18240b57cec5SDimitry Andric ParsedType baseType, 18250b57cec5SDimitry Andric SourceLocation &typeArgsLAngleLoc, 18260b57cec5SDimitry Andric SmallVectorImpl<ParsedType> &typeArgs, 18270b57cec5SDimitry Andric SourceLocation &typeArgsRAngleLoc, 18280b57cec5SDimitry Andric SourceLocation &protocolLAngleLoc, 18290b57cec5SDimitry Andric SmallVectorImpl<Decl *> &protocols, 18300b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &protocolLocs, 18310b57cec5SDimitry Andric SourceLocation &protocolRAngleLoc, 18320b57cec5SDimitry Andric bool consumeLastToken) { 18330b57cec5SDimitry Andric assert(Tok.is(tok::less)); 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric // Parse the first angle-bracket-delimited clause. 18360b57cec5SDimitry Andric parseObjCTypeArgsOrProtocolQualifiers(baseType, 18370b57cec5SDimitry Andric typeArgsLAngleLoc, 18380b57cec5SDimitry Andric typeArgs, 18390b57cec5SDimitry Andric typeArgsRAngleLoc, 18400b57cec5SDimitry Andric protocolLAngleLoc, 18410b57cec5SDimitry Andric protocols, 18420b57cec5SDimitry Andric protocolLocs, 18430b57cec5SDimitry Andric protocolRAngleLoc, 18440b57cec5SDimitry Andric consumeLastToken, 18450b57cec5SDimitry Andric /*warnOnIncompleteProtocols=*/false); 18460b57cec5SDimitry Andric if (Tok.is(tok::eof)) // Nothing else to do here... 18470b57cec5SDimitry Andric return; 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric // An Objective-C object pointer followed by type arguments 18500b57cec5SDimitry Andric // can then be followed again by a set of protocol references, e.g., 18510b57cec5SDimitry Andric // \c NSArray<NSView><NSTextDelegate> 18520b57cec5SDimitry Andric if ((consumeLastToken && Tok.is(tok::less)) || 18530b57cec5SDimitry Andric (!consumeLastToken && NextToken().is(tok::less))) { 18540b57cec5SDimitry Andric // If we aren't consuming the last token, the prior '>' is still hanging 18550b57cec5SDimitry Andric // there. Consume it before we parse the protocol qualifiers. 18560b57cec5SDimitry Andric if (!consumeLastToken) 18570b57cec5SDimitry Andric ConsumeToken(); 18580b57cec5SDimitry Andric 18590b57cec5SDimitry Andric if (!protocols.empty()) { 18600b57cec5SDimitry Andric SkipUntilFlags skipFlags = SkipUntilFlags(); 18610b57cec5SDimitry Andric if (!consumeLastToken) 18620b57cec5SDimitry Andric skipFlags = skipFlags | StopBeforeMatch; 18630b57cec5SDimitry Andric Diag(Tok, diag::err_objc_type_args_after_protocols) 18640b57cec5SDimitry Andric << SourceRange(protocolLAngleLoc, protocolRAngleLoc); 18650b57cec5SDimitry Andric SkipUntil(tok::greater, tok::greatergreater, skipFlags); 18660b57cec5SDimitry Andric } else { 18670b57cec5SDimitry Andric ParseObjCProtocolReferences(protocols, protocolLocs, 18680b57cec5SDimitry Andric /*WarnOnDeclarations=*/false, 18690b57cec5SDimitry Andric /*ForObjCContainer=*/false, 18700b57cec5SDimitry Andric protocolLAngleLoc, protocolRAngleLoc, 18710b57cec5SDimitry Andric consumeLastToken); 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric } 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers( 18770b57cec5SDimitry Andric SourceLocation loc, 18780b57cec5SDimitry Andric ParsedType type, 18790b57cec5SDimitry Andric bool consumeLastToken, 18800b57cec5SDimitry Andric SourceLocation &endLoc) { 18810b57cec5SDimitry Andric assert(Tok.is(tok::less)); 18820b57cec5SDimitry Andric SourceLocation typeArgsLAngleLoc; 18830b57cec5SDimitry Andric SmallVector<ParsedType, 4> typeArgs; 18840b57cec5SDimitry Andric SourceLocation typeArgsRAngleLoc; 18850b57cec5SDimitry Andric SourceLocation protocolLAngleLoc; 18860b57cec5SDimitry Andric SmallVector<Decl *, 4> protocols; 18870b57cec5SDimitry Andric SmallVector<SourceLocation, 4> protocolLocs; 18880b57cec5SDimitry Andric SourceLocation protocolRAngleLoc; 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric // Parse type arguments and protocol qualifiers. 18910b57cec5SDimitry Andric parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs, 18920b57cec5SDimitry Andric typeArgsRAngleLoc, protocolLAngleLoc, 18930b57cec5SDimitry Andric protocols, protocolLocs, 18940b57cec5SDimitry Andric protocolRAngleLoc, consumeLastToken); 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric if (Tok.is(tok::eof)) 18970b57cec5SDimitry Andric return true; // Invalid type result. 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric // Compute the location of the last token. 19000b57cec5SDimitry Andric if (consumeLastToken) 19010b57cec5SDimitry Andric endLoc = PrevTokLocation; 19020b57cec5SDimitry Andric else 19030b57cec5SDimitry Andric endLoc = Tok.getLocation(); 19040b57cec5SDimitry Andric 1905*0fca6ea1SDimitry Andric return Actions.ObjC().actOnObjCTypeArgsAndProtocolQualifiers( 1906*0fca6ea1SDimitry Andric getCurScope(), loc, type, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, 1907*0fca6ea1SDimitry Andric protocolLAngleLoc, protocols, protocolLocs, protocolRAngleLoc); 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 191081ad6265SDimitry Andric void Parser::HelperActionsForIvarDeclarations( 191181ad6265SDimitry Andric ObjCContainerDecl *interfaceDecl, SourceLocation atLoc, 191281ad6265SDimitry Andric BalancedDelimiterTracker &T, SmallVectorImpl<Decl *> &AllIvarDecls, 19130b57cec5SDimitry Andric bool RBraceMissing) { 19140b57cec5SDimitry Andric if (!RBraceMissing) 19150b57cec5SDimitry Andric T.consumeClose(); 19160b57cec5SDimitry Andric 191781ad6265SDimitry Andric assert(getObjCDeclContext() == interfaceDecl && 191881ad6265SDimitry Andric "Ivars should have interfaceDecl as their decl context"); 19190b57cec5SDimitry Andric Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); 19200b57cec5SDimitry Andric // Call ActOnFields() even if we don't have any decls. This is useful 19210b57cec5SDimitry Andric // for code rewriting tools that need to be aware of the empty list. 19220b57cec5SDimitry Andric Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, 19230b57cec5SDimitry Andric T.getOpenLocation(), T.getCloseLocation(), 19240b57cec5SDimitry Andric ParsedAttributesView()); 19250b57cec5SDimitry Andric } 19260b57cec5SDimitry Andric 19270b57cec5SDimitry Andric /// objc-class-instance-variables: 19280b57cec5SDimitry Andric /// '{' objc-instance-variable-decl-list[opt] '}' 19290b57cec5SDimitry Andric /// 19300b57cec5SDimitry Andric /// objc-instance-variable-decl-list: 19310b57cec5SDimitry Andric /// objc-visibility-spec 19320b57cec5SDimitry Andric /// objc-instance-variable-decl ';' 19330b57cec5SDimitry Andric /// ';' 19340b57cec5SDimitry Andric /// objc-instance-variable-decl-list objc-visibility-spec 19350b57cec5SDimitry Andric /// objc-instance-variable-decl-list objc-instance-variable-decl ';' 19360b57cec5SDimitry Andric /// objc-instance-variable-decl-list static_assert-declaration 19370b57cec5SDimitry Andric /// objc-instance-variable-decl-list ';' 19380b57cec5SDimitry Andric /// 19390b57cec5SDimitry Andric /// objc-visibility-spec: 19400b57cec5SDimitry Andric /// @private 19410b57cec5SDimitry Andric /// @protected 19420b57cec5SDimitry Andric /// @public 19430b57cec5SDimitry Andric /// @package [OBJC2] 19440b57cec5SDimitry Andric /// 19450b57cec5SDimitry Andric /// objc-instance-variable-decl: 19460b57cec5SDimitry Andric /// struct-declaration 19470b57cec5SDimitry Andric /// 194881ad6265SDimitry Andric void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, 19490b57cec5SDimitry Andric tok::ObjCKeywordKind visibility, 19500b57cec5SDimitry Andric SourceLocation atLoc) { 19510b57cec5SDimitry Andric assert(Tok.is(tok::l_brace) && "expected {"); 19520b57cec5SDimitry Andric SmallVector<Decl *, 32> AllIvarDecls; 19530b57cec5SDimitry Andric 19540b57cec5SDimitry Andric ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope); 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 19570b57cec5SDimitry Andric T.consumeOpen(); 19580b57cec5SDimitry Andric // While we still have something to read, read the instance variables. 19590b57cec5SDimitry Andric while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 19600b57cec5SDimitry Andric // Each iteration of this loop reads one objc-instance-variable-decl. 19610b57cec5SDimitry Andric 19620b57cec5SDimitry Andric // Check for extraneous top-level semicolon. 19630b57cec5SDimitry Andric if (Tok.is(tok::semi)) { 19640b57cec5SDimitry Andric ConsumeExtraSemi(InstanceVariableList); 19650b57cec5SDimitry Andric continue; 19660b57cec5SDimitry Andric } 19670b57cec5SDimitry Andric 19680b57cec5SDimitry Andric // Set the default visibility to private. 19690b57cec5SDimitry Andric if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec 19700b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 1971fe6060f1SDimitry Andric cutOffParsing(); 1972*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCAtVisibility(getCurScope()); 1973fe6060f1SDimitry Andric return; 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric switch (Tok.getObjCKeywordID()) { 19770b57cec5SDimitry Andric case tok::objc_private: 19780b57cec5SDimitry Andric case tok::objc_public: 19790b57cec5SDimitry Andric case tok::objc_protected: 19800b57cec5SDimitry Andric case tok::objc_package: 19810b57cec5SDimitry Andric visibility = Tok.getObjCKeywordID(); 19820b57cec5SDimitry Andric ConsumeToken(); 19830b57cec5SDimitry Andric continue; 19840b57cec5SDimitry Andric 19850b57cec5SDimitry Andric case tok::objc_end: 19860b57cec5SDimitry Andric Diag(Tok, diag::err_objc_unexpected_atend); 19870b57cec5SDimitry Andric Tok.setLocation(Tok.getLocation().getLocWithOffset(-1)); 19880b57cec5SDimitry Andric Tok.setKind(tok::at); 19890b57cec5SDimitry Andric Tok.setLength(1); 19900b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/true); 19910b57cec5SDimitry Andric HelperActionsForIvarDeclarations(interfaceDecl, atLoc, 19920b57cec5SDimitry Andric T, AllIvarDecls, true); 19930b57cec5SDimitry Andric return; 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric default: 19960b57cec5SDimitry Andric Diag(Tok, diag::err_objc_illegal_visibility_spec); 19970b57cec5SDimitry Andric continue; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 2002fe6060f1SDimitry Andric cutOffParsing(); 2003*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteOrdinaryName( 2004*0fca6ea1SDimitry Andric getCurScope(), SemaCodeCompletion::PCC_ObjCInstanceVariableList); 2005fe6060f1SDimitry Andric return; 20060b57cec5SDimitry Andric } 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric // This needs to duplicate a small amount of code from 20090b57cec5SDimitry Andric // ParseStructUnionBody() for things that should work in both 20100b57cec5SDimitry Andric // C struct and in Objective-C class instance variables. 20110b57cec5SDimitry Andric if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { 20120b57cec5SDimitry Andric SourceLocation DeclEnd; 20130b57cec5SDimitry Andric ParseStaticAssertDeclaration(DeclEnd); 20140b57cec5SDimitry Andric continue; 20150b57cec5SDimitry Andric } 20160b57cec5SDimitry Andric 2017*0fca6ea1SDimitry Andric auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) -> Decl * { 201881ad6265SDimitry Andric assert(getObjCDeclContext() == interfaceDecl && 201981ad6265SDimitry Andric "Ivar should have interfaceDecl as its decl context"); 20200b57cec5SDimitry Andric // Install the declarator into the interface decl. 20210b57cec5SDimitry Andric FD.D.setObjCIvar(true); 2022*0fca6ea1SDimitry Andric Decl *Field = Actions.ObjC().ActOnIvar( 20230b57cec5SDimitry Andric getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, 20240b57cec5SDimitry Andric FD.BitfieldSize, visibility); 20250b57cec5SDimitry Andric if (Field) 20260b57cec5SDimitry Andric AllIvarDecls.push_back(Field); 20270b57cec5SDimitry Andric FD.complete(Field); 2028*0fca6ea1SDimitry Andric return Field; 20290b57cec5SDimitry Andric }; 20300b57cec5SDimitry Andric 20310b57cec5SDimitry Andric // Parse all the comma separated declarators. 20320b57cec5SDimitry Andric ParsingDeclSpec DS(*this); 20330b57cec5SDimitry Andric ParseStructDeclaration(DS, ObjCIvarCallback); 20340b57cec5SDimitry Andric 20350b57cec5SDimitry Andric if (Tok.is(tok::semi)) { 20360b57cec5SDimitry Andric ConsumeToken(); 20370b57cec5SDimitry Andric } else { 20380b57cec5SDimitry Andric Diag(Tok, diag::err_expected_semi_decl_list); 20390b57cec5SDimitry Andric // Skip to end of block or statement 20400b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric } 20430b57cec5SDimitry Andric HelperActionsForIvarDeclarations(interfaceDecl, atLoc, 20440b57cec5SDimitry Andric T, AllIvarDecls, false); 20450b57cec5SDimitry Andric } 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric /// objc-protocol-declaration: 20480b57cec5SDimitry Andric /// objc-protocol-definition 20490b57cec5SDimitry Andric /// objc-protocol-forward-reference 20500b57cec5SDimitry Andric /// 20510b57cec5SDimitry Andric /// objc-protocol-definition: 20520b57cec5SDimitry Andric /// \@protocol identifier 20530b57cec5SDimitry Andric /// objc-protocol-refs[opt] 20540b57cec5SDimitry Andric /// objc-interface-decl-list 20550b57cec5SDimitry Andric /// \@end 20560b57cec5SDimitry Andric /// 20570b57cec5SDimitry Andric /// objc-protocol-forward-reference: 20580b57cec5SDimitry Andric /// \@protocol identifier-list ';' 20590b57cec5SDimitry Andric /// 20600b57cec5SDimitry Andric /// "\@protocol identifier ;" should be resolved as "\@protocol 20610b57cec5SDimitry Andric /// identifier-list ;": objc-interface-decl-list may not start with a 20620b57cec5SDimitry Andric /// semicolon in the first alternative if objc-protocol-refs are omitted. 20630b57cec5SDimitry Andric Parser::DeclGroupPtrTy 20640b57cec5SDimitry Andric Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, 20650b57cec5SDimitry Andric ParsedAttributes &attrs) { 20660b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_protocol) && 20670b57cec5SDimitry Andric "ParseObjCAtProtocolDeclaration(): Expected @protocol"); 20680b57cec5SDimitry Andric ConsumeToken(); // the "protocol" identifier 20690b57cec5SDimitry Andric 20700b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 20710b57cec5SDimitry Andric cutOffParsing(); 2072*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCProtocolDecl(getCurScope()); 20730b57cec5SDimitry Andric return nullptr; 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric MaybeSkipAttributes(tok::objc_protocol); 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric if (expectIdentifier()) 20790b57cec5SDimitry Andric return nullptr; // missing protocol name. 20800b57cec5SDimitry Andric // Save the protocol name, then consume it. 20810b57cec5SDimitry Andric IdentifierInfo *protocolName = Tok.getIdentifierInfo(); 20820b57cec5SDimitry Andric SourceLocation nameLoc = ConsumeToken(); 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. 20850b57cec5SDimitry Andric IdentifierLocPair ProtoInfo(protocolName, nameLoc); 2086*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, 2087*0fca6ea1SDimitry Andric attrs); 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric CheckNestedObjCContexts(AtLoc); 20910b57cec5SDimitry Andric 20920b57cec5SDimitry Andric if (Tok.is(tok::comma)) { // list of forward declarations. 20930b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 8> ProtocolRefs; 20940b57cec5SDimitry Andric ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); 20950b57cec5SDimitry Andric 20960b57cec5SDimitry Andric // Parse the list of forward declarations. 209704eeddc0SDimitry Andric while (true) { 20980b57cec5SDimitry Andric ConsumeToken(); // the ',' 20990b57cec5SDimitry Andric if (expectIdentifier()) { 21000b57cec5SDimitry Andric SkipUntil(tok::semi); 21010b57cec5SDimitry Andric return nullptr; 21020b57cec5SDimitry Andric } 21030b57cec5SDimitry Andric ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(), 21040b57cec5SDimitry Andric Tok.getLocation())); 21050b57cec5SDimitry Andric ConsumeToken(); // the identifier 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric if (Tok.isNot(tok::comma)) 21080b57cec5SDimitry Andric break; 21090b57cec5SDimitry Andric } 21100b57cec5SDimitry Andric // Consume the ';'. 21110b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) 21120b57cec5SDimitry Andric return nullptr; 21130b57cec5SDimitry Andric 2114*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, 2115*0fca6ea1SDimitry Andric attrs); 21160b57cec5SDimitry Andric } 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric // Last, and definitely not least, parse a protocol declaration. 21190b57cec5SDimitry Andric SourceLocation LAngleLoc, EndProtoLoc; 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric SmallVector<Decl *, 8> ProtocolRefs; 21220b57cec5SDimitry Andric SmallVector<SourceLocation, 8> ProtocolLocs; 21230b57cec5SDimitry Andric if (Tok.is(tok::less) && 21240b57cec5SDimitry Andric ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true, 21250b57cec5SDimitry Andric LAngleLoc, EndProtoLoc, 21260b57cec5SDimitry Andric /*consumeLastToken=*/true)) 21270b57cec5SDimitry Andric return nullptr; 21280b57cec5SDimitry Andric 2129*0fca6ea1SDimitry Andric SkipBodyInfo SkipBody; 2130*0fca6ea1SDimitry Andric ObjCProtocolDecl *ProtoType = Actions.ObjC().ActOnStartProtocolInterface( 21310b57cec5SDimitry Andric AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), 2132bdd1243dSDimitry Andric ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody); 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); 2135bdd1243dSDimitry Andric if (SkipBody.CheckSameAsPrevious) { 2136bdd1243dSDimitry Andric auto *PreviousDef = cast<ObjCProtocolDecl>(SkipBody.Previous); 2137bdd1243dSDimitry Andric if (Actions.ActOnDuplicateODRHashDefinition(ProtoType, PreviousDef)) { 2138bdd1243dSDimitry Andric ProtoType->mergeDuplicateDefinitionWithCommon( 2139bdd1243dSDimitry Andric PreviousDef->getDefinition()); 2140bdd1243dSDimitry Andric } else { 2141bdd1243dSDimitry Andric ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(), 2142bdd1243dSDimitry Andric getPreprocessor().getLangOpts()); 2143bdd1243dSDimitry Andric DiagsEmitter.diagnoseMismatch(PreviousDef, ProtoType); 2144bdd1243dSDimitry Andric } 2145bdd1243dSDimitry Andric } 21460b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(ProtoType); 21470b57cec5SDimitry Andric } 21480b57cec5SDimitry Andric 21490b57cec5SDimitry Andric /// objc-implementation: 21500b57cec5SDimitry Andric /// objc-class-implementation-prologue 21510b57cec5SDimitry Andric /// objc-category-implementation-prologue 21520b57cec5SDimitry Andric /// 21530b57cec5SDimitry Andric /// objc-class-implementation-prologue: 21540b57cec5SDimitry Andric /// @implementation identifier objc-superclass[opt] 21550b57cec5SDimitry Andric /// objc-class-instance-variables[opt] 21560b57cec5SDimitry Andric /// 21570b57cec5SDimitry Andric /// objc-category-implementation-prologue: 21580b57cec5SDimitry Andric /// @implementation identifier ( identifier ) 21590b57cec5SDimitry Andric Parser::DeclGroupPtrTy 21600b57cec5SDimitry Andric Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, 21610b57cec5SDimitry Andric ParsedAttributes &Attrs) { 21620b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_implementation) && 21630b57cec5SDimitry Andric "ParseObjCAtImplementationDeclaration(): Expected @implementation"); 21640b57cec5SDimitry Andric CheckNestedObjCContexts(AtLoc); 21650b57cec5SDimitry Andric ConsumeToken(); // the "implementation" identifier 21660b57cec5SDimitry Andric 21670b57cec5SDimitry Andric // Code completion after '@implementation'. 21680b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 21690b57cec5SDimitry Andric cutOffParsing(); 2170*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCImplementationDecl(getCurScope()); 21710b57cec5SDimitry Andric return nullptr; 21720b57cec5SDimitry Andric } 21730b57cec5SDimitry Andric 21740b57cec5SDimitry Andric MaybeSkipAttributes(tok::objc_implementation); 21750b57cec5SDimitry Andric 21760b57cec5SDimitry Andric if (expectIdentifier()) 21770b57cec5SDimitry Andric return nullptr; // missing class or category name. 21780b57cec5SDimitry Andric // We have a class or category name - consume it. 21790b57cec5SDimitry Andric IdentifierInfo *nameId = Tok.getIdentifierInfo(); 21800b57cec5SDimitry Andric SourceLocation nameLoc = ConsumeToken(); // consume class or category name 218181ad6265SDimitry Andric ObjCImplDecl *ObjCImpDecl = nullptr; 21820b57cec5SDimitry Andric 21830b57cec5SDimitry Andric // Neither a type parameter list nor a list of protocol references is 21840b57cec5SDimitry Andric // permitted here. Parse and diagnose them. 21850b57cec5SDimitry Andric if (Tok.is(tok::less)) { 21860b57cec5SDimitry Andric SourceLocation lAngleLoc, rAngleLoc; 21870b57cec5SDimitry Andric SmallVector<IdentifierLocPair, 8> protocolIdents; 21880b57cec5SDimitry Andric SourceLocation diagLoc = Tok.getLocation(); 21890b57cec5SDimitry Andric ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); 21900b57cec5SDimitry Andric if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc, 21910b57cec5SDimitry Andric protocolIdents, rAngleLoc)) { 21920b57cec5SDimitry Andric Diag(diagLoc, diag::err_objc_parameterized_implementation) 21930b57cec5SDimitry Andric << SourceRange(diagLoc, PrevTokLocation); 21940b57cec5SDimitry Andric } else if (lAngleLoc.isValid()) { 21950b57cec5SDimitry Andric Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier) 21960b57cec5SDimitry Andric << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc)); 21970b57cec5SDimitry Andric } 21980b57cec5SDimitry Andric } 21990b57cec5SDimitry Andric 22000b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 22010b57cec5SDimitry Andric // we have a category implementation. 22020b57cec5SDimitry Andric ConsumeParen(); 22030b57cec5SDimitry Andric SourceLocation categoryLoc, rparenLoc; 22040b57cec5SDimitry Andric IdentifierInfo *categoryId = nullptr; 22050b57cec5SDimitry Andric 22060b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 22070b57cec5SDimitry Andric cutOffParsing(); 2208*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCImplementationCategory( 2209*0fca6ea1SDimitry Andric getCurScope(), nameId, nameLoc); 22100b57cec5SDimitry Andric return nullptr; 22110b57cec5SDimitry Andric } 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 22140b57cec5SDimitry Andric categoryId = Tok.getIdentifierInfo(); 22150b57cec5SDimitry Andric categoryLoc = ConsumeToken(); 22160b57cec5SDimitry Andric } else { 22170b57cec5SDimitry Andric Diag(Tok, diag::err_expected) 22180b57cec5SDimitry Andric << tok::identifier; // missing category name. 22190b57cec5SDimitry Andric return nullptr; 22200b57cec5SDimitry Andric } 22210b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) { 22220b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::r_paren; 22230b57cec5SDimitry Andric SkipUntil(tok::r_paren); // don't stop at ';' 22240b57cec5SDimitry Andric return nullptr; 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric rparenLoc = ConsumeParen(); 22270b57cec5SDimitry Andric if (Tok.is(tok::less)) { // we have illegal '<' try to recover 22280b57cec5SDimitry Andric Diag(Tok, diag::err_unexpected_protocol_qualifier); 22290b57cec5SDimitry Andric SourceLocation protocolLAngleLoc, protocolRAngleLoc; 22300b57cec5SDimitry Andric SmallVector<Decl *, 4> protocols; 22310b57cec5SDimitry Andric SmallVector<SourceLocation, 4> protocolLocs; 22320b57cec5SDimitry Andric (void)ParseObjCProtocolReferences(protocols, protocolLocs, 22330b57cec5SDimitry Andric /*warnOnIncompleteProtocols=*/false, 22340b57cec5SDimitry Andric /*ForObjCContainer=*/false, 22350b57cec5SDimitry Andric protocolLAngleLoc, protocolRAngleLoc, 22360b57cec5SDimitry Andric /*consumeLastToken=*/true); 22370b57cec5SDimitry Andric } 2238*0fca6ea1SDimitry Andric ObjCImpDecl = Actions.ObjC().ActOnStartCategoryImplementation( 22390b57cec5SDimitry Andric AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs); 22400b57cec5SDimitry Andric 22410b57cec5SDimitry Andric } else { 22420b57cec5SDimitry Andric // We have a class implementation 22430b57cec5SDimitry Andric SourceLocation superClassLoc; 22440b57cec5SDimitry Andric IdentifierInfo *superClassId = nullptr; 22450b57cec5SDimitry Andric if (TryConsumeToken(tok::colon)) { 22460b57cec5SDimitry Andric // We have a super class 22470b57cec5SDimitry Andric if (expectIdentifier()) 22480b57cec5SDimitry Andric return nullptr; // missing super class name. 22490b57cec5SDimitry Andric superClassId = Tok.getIdentifierInfo(); 22500b57cec5SDimitry Andric superClassLoc = ConsumeToken(); // Consume super class name 22510b57cec5SDimitry Andric } 2252*0fca6ea1SDimitry Andric ObjCImpDecl = Actions.ObjC().ActOnStartClassImplementation( 22530b57cec5SDimitry Andric AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs); 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) // we have ivars 22560b57cec5SDimitry Andric ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc); 22570b57cec5SDimitry Andric else if (Tok.is(tok::less)) { // we have illegal '<' try to recover 22580b57cec5SDimitry Andric Diag(Tok, diag::err_unexpected_protocol_qualifier); 22590b57cec5SDimitry Andric 22600b57cec5SDimitry Andric SourceLocation protocolLAngleLoc, protocolRAngleLoc; 22610b57cec5SDimitry Andric SmallVector<Decl *, 4> protocols; 22620b57cec5SDimitry Andric SmallVector<SourceLocation, 4> protocolLocs; 22630b57cec5SDimitry Andric (void)ParseObjCProtocolReferences(protocols, protocolLocs, 22640b57cec5SDimitry Andric /*warnOnIncompleteProtocols=*/false, 22650b57cec5SDimitry Andric /*ForObjCContainer=*/false, 22660b57cec5SDimitry Andric protocolLAngleLoc, protocolRAngleLoc, 22670b57cec5SDimitry Andric /*consumeLastToken=*/true); 22680b57cec5SDimitry Andric } 22690b57cec5SDimitry Andric } 22700b57cec5SDimitry Andric assert(ObjCImpDecl); 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup; 22730b57cec5SDimitry Andric 22740b57cec5SDimitry Andric { 22750b57cec5SDimitry Andric ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); 22760b57cec5SDimitry Andric while (!ObjCImplParsing.isFinished() && !isEofOrEom()) { 2277bdd1243dSDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 2278bdd1243dSDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 2279bdd1243dSDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 2280bdd1243dSDimitry Andric if (DeclGroupPtrTy DGP = 2281bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs)) { 22820b57cec5SDimitry Andric DeclGroupRef DG = DGP.get(); 22830b57cec5SDimitry Andric DeclsInGroup.append(DG.begin(), DG.end()); 22840b57cec5SDimitry Andric } 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric } 22870b57cec5SDimitry Andric 2288*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnFinishObjCImplementation(ObjCImpDecl, 2289*0fca6ea1SDimitry Andric DeclsInGroup); 22900b57cec5SDimitry Andric } 22910b57cec5SDimitry Andric 22920b57cec5SDimitry Andric Parser::DeclGroupPtrTy 22930b57cec5SDimitry Andric Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { 22940b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_end) && 22950b57cec5SDimitry Andric "ParseObjCAtEndDeclaration(): Expected @end"); 22960b57cec5SDimitry Andric ConsumeToken(); // the "end" identifier 22970b57cec5SDimitry Andric if (CurParsedObjCImpl) 22980b57cec5SDimitry Andric CurParsedObjCImpl->finish(atEnd); 22990b57cec5SDimitry Andric else 23000b57cec5SDimitry Andric // missing @implementation 23010b57cec5SDimitry Andric Diag(atEnd.getBegin(), diag::err_expected_objc_container); 23020b57cec5SDimitry Andric return nullptr; 23030b57cec5SDimitry Andric } 23040b57cec5SDimitry Andric 23050b57cec5SDimitry Andric Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { 23060b57cec5SDimitry Andric if (!Finished) { 23070b57cec5SDimitry Andric finish(P.Tok.getLocation()); 23080b57cec5SDimitry Andric if (P.isEofOrEom()) { 23090b57cec5SDimitry Andric P.Diag(P.Tok, diag::err_objc_missing_end) 23100b57cec5SDimitry Andric << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); 23110b57cec5SDimitry Andric P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start) 2312*0fca6ea1SDimitry Andric << SemaObjC::OCK_Implementation; 23130b57cec5SDimitry Andric } 23140b57cec5SDimitry Andric } 23150b57cec5SDimitry Andric P.CurParsedObjCImpl = nullptr; 23160b57cec5SDimitry Andric assert(LateParsedObjCMethods.empty()); 23170b57cec5SDimitry Andric } 23180b57cec5SDimitry Andric 23190b57cec5SDimitry Andric void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { 23200b57cec5SDimitry Andric assert(!Finished); 2321*0fca6ea1SDimitry Andric P.Actions.ObjC().DefaultSynthesizeProperties(P.getCurScope(), Dcl, 2322*0fca6ea1SDimitry Andric AtEnd.getBegin()); 23230b57cec5SDimitry Andric for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) 23240b57cec5SDimitry Andric P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 23250b57cec5SDimitry Andric true/*Methods*/); 23260b57cec5SDimitry Andric 2327*0fca6ea1SDimitry Andric P.Actions.ObjC().ActOnAtEnd(P.getCurScope(), AtEnd); 23280b57cec5SDimitry Andric 23290b57cec5SDimitry Andric if (HasCFunction) 23300b57cec5SDimitry Andric for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) 23310b57cec5SDimitry Andric P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 23320b57cec5SDimitry Andric false/*c-functions*/); 23330b57cec5SDimitry Andric 23340b57cec5SDimitry Andric /// Clear and free the cached objc methods. 23350b57cec5SDimitry Andric for (LateParsedObjCMethodContainer::iterator 23360b57cec5SDimitry Andric I = LateParsedObjCMethods.begin(), 23370b57cec5SDimitry Andric E = LateParsedObjCMethods.end(); I != E; ++I) 23380b57cec5SDimitry Andric delete *I; 23390b57cec5SDimitry Andric LateParsedObjCMethods.clear(); 23400b57cec5SDimitry Andric 23410b57cec5SDimitry Andric Finished = true; 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric /// compatibility-alias-decl: 23450b57cec5SDimitry Andric /// @compatibility_alias alias-name class-name ';' 23460b57cec5SDimitry Andric /// 23470b57cec5SDimitry Andric Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { 23480b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && 23490b57cec5SDimitry Andric "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); 23500b57cec5SDimitry Andric ConsumeToken(); // consume compatibility_alias 23510b57cec5SDimitry Andric if (expectIdentifier()) 23520b57cec5SDimitry Andric return nullptr; 23530b57cec5SDimitry Andric IdentifierInfo *aliasId = Tok.getIdentifierInfo(); 23540b57cec5SDimitry Andric SourceLocation aliasLoc = ConsumeToken(); // consume alias-name 23550b57cec5SDimitry Andric if (expectIdentifier()) 23560b57cec5SDimitry Andric return nullptr; 23570b57cec5SDimitry Andric IdentifierInfo *classId = Tok.getIdentifierInfo(); 23580b57cec5SDimitry Andric SourceLocation classLoc = ConsumeToken(); // consume class-name; 23590b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias"); 2360*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, 23610b57cec5SDimitry Andric classId, classLoc); 23620b57cec5SDimitry Andric } 23630b57cec5SDimitry Andric 23640b57cec5SDimitry Andric /// property-synthesis: 23650b57cec5SDimitry Andric /// @synthesize property-ivar-list ';' 23660b57cec5SDimitry Andric /// 23670b57cec5SDimitry Andric /// property-ivar-list: 23680b57cec5SDimitry Andric /// property-ivar 23690b57cec5SDimitry Andric /// property-ivar-list ',' property-ivar 23700b57cec5SDimitry Andric /// 23710b57cec5SDimitry Andric /// property-ivar: 23720b57cec5SDimitry Andric /// identifier 23730b57cec5SDimitry Andric /// identifier '=' identifier 23740b57cec5SDimitry Andric /// 23750b57cec5SDimitry Andric Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { 23760b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && 23770b57cec5SDimitry Andric "ParseObjCPropertySynthesize(): Expected '@synthesize'"); 23780b57cec5SDimitry Andric ConsumeToken(); // consume synthesize 23790b57cec5SDimitry Andric 23800b57cec5SDimitry Andric while (true) { 23810b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 23820b57cec5SDimitry Andric cutOffParsing(); 2383*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition( 2384*0fca6ea1SDimitry Andric getCurScope()); 23850b57cec5SDimitry Andric return nullptr; 23860b57cec5SDimitry Andric } 23870b57cec5SDimitry Andric 23880b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) { 23890b57cec5SDimitry Andric Diag(Tok, diag::err_synthesized_property_name); 23900b57cec5SDimitry Andric SkipUntil(tok::semi); 23910b57cec5SDimitry Andric return nullptr; 23920b57cec5SDimitry Andric } 23930b57cec5SDimitry Andric 23940b57cec5SDimitry Andric IdentifierInfo *propertyIvar = nullptr; 23950b57cec5SDimitry Andric IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 23960b57cec5SDimitry Andric SourceLocation propertyLoc = ConsumeToken(); // consume property name 23970b57cec5SDimitry Andric SourceLocation propertyIvarLoc; 23980b57cec5SDimitry Andric if (TryConsumeToken(tok::equal)) { 23990b57cec5SDimitry Andric // property '=' ivar-name 24000b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 24010b57cec5SDimitry Andric cutOffParsing(); 2402*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertySynthesizeIvar( 2403*0fca6ea1SDimitry Andric getCurScope(), propertyId); 24040b57cec5SDimitry Andric return nullptr; 24050b57cec5SDimitry Andric } 24060b57cec5SDimitry Andric 24070b57cec5SDimitry Andric if (expectIdentifier()) 24080b57cec5SDimitry Andric break; 24090b57cec5SDimitry Andric propertyIvar = Tok.getIdentifierInfo(); 24100b57cec5SDimitry Andric propertyIvarLoc = ConsumeToken(); // consume ivar-name 24110b57cec5SDimitry Andric } 2412*0fca6ea1SDimitry Andric Actions.ObjC().ActOnPropertyImplDecl( 2413*0fca6ea1SDimitry Andric getCurScope(), atLoc, propertyLoc, true, propertyId, propertyIvar, 2414*0fca6ea1SDimitry Andric propertyIvarLoc, ObjCPropertyQueryKind::OBJC_PR_query_unknown); 24150b57cec5SDimitry Andric if (Tok.isNot(tok::comma)) 24160b57cec5SDimitry Andric break; 24170b57cec5SDimitry Andric ConsumeToken(); // consume ',' 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize"); 24200b57cec5SDimitry Andric return nullptr; 24210b57cec5SDimitry Andric } 24220b57cec5SDimitry Andric 24230b57cec5SDimitry Andric /// property-dynamic: 24240b57cec5SDimitry Andric /// @dynamic property-list 24250b57cec5SDimitry Andric /// 24260b57cec5SDimitry Andric /// property-list: 24270b57cec5SDimitry Andric /// identifier 24280b57cec5SDimitry Andric /// property-list ',' identifier 24290b57cec5SDimitry Andric /// 24300b57cec5SDimitry Andric Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { 24310b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && 24320b57cec5SDimitry Andric "ParseObjCPropertyDynamic(): Expected '@dynamic'"); 24330b57cec5SDimitry Andric ConsumeToken(); // consume dynamic 24340b57cec5SDimitry Andric 24350b57cec5SDimitry Andric bool isClassProperty = false; 24360b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 24370b57cec5SDimitry Andric ConsumeParen(); 24380b57cec5SDimitry Andric const IdentifierInfo *II = Tok.getIdentifierInfo(); 24390b57cec5SDimitry Andric 24400b57cec5SDimitry Andric if (!II) { 24410b57cec5SDimitry Andric Diag(Tok, diag::err_objc_expected_property_attr) << II; 24420b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 24430b57cec5SDimitry Andric } else { 24440b57cec5SDimitry Andric SourceLocation AttrName = ConsumeToken(); // consume attribute name 24450b57cec5SDimitry Andric if (II->isStr("class")) { 24460b57cec5SDimitry Andric isClassProperty = true; 24470b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) { 24480b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::r_paren; 24490b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 24500b57cec5SDimitry Andric } else 24510b57cec5SDimitry Andric ConsumeParen(); 24520b57cec5SDimitry Andric } else { 24530b57cec5SDimitry Andric Diag(AttrName, diag::err_objc_expected_property_attr) << II; 24540b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 24550b57cec5SDimitry Andric } 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric } 24580b57cec5SDimitry Andric 24590b57cec5SDimitry Andric while (true) { 24600b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 24610b57cec5SDimitry Andric cutOffParsing(); 2462*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition( 2463*0fca6ea1SDimitry Andric getCurScope()); 24640b57cec5SDimitry Andric return nullptr; 24650b57cec5SDimitry Andric } 24660b57cec5SDimitry Andric 24670b57cec5SDimitry Andric if (expectIdentifier()) { 24680b57cec5SDimitry Andric SkipUntil(tok::semi); 24690b57cec5SDimitry Andric return nullptr; 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 24730b57cec5SDimitry Andric SourceLocation propertyLoc = ConsumeToken(); // consume property name 2474*0fca6ea1SDimitry Andric Actions.ObjC().ActOnPropertyImplDecl( 2475*0fca6ea1SDimitry Andric getCurScope(), atLoc, propertyLoc, false, propertyId, nullptr, 2476*0fca6ea1SDimitry Andric SourceLocation(), 2477*0fca6ea1SDimitry Andric isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class 2478*0fca6ea1SDimitry Andric : ObjCPropertyQueryKind::OBJC_PR_query_unknown); 24790b57cec5SDimitry Andric 24800b57cec5SDimitry Andric if (Tok.isNot(tok::comma)) 24810b57cec5SDimitry Andric break; 24820b57cec5SDimitry Andric ConsumeToken(); // consume ',' 24830b57cec5SDimitry Andric } 24840b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic"); 24850b57cec5SDimitry Andric return nullptr; 24860b57cec5SDimitry Andric } 24870b57cec5SDimitry Andric 24880b57cec5SDimitry Andric /// objc-throw-statement: 24890b57cec5SDimitry Andric /// throw expression[opt]; 24900b57cec5SDimitry Andric /// 24910b57cec5SDimitry Andric StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { 24920b57cec5SDimitry Andric ExprResult Res; 24930b57cec5SDimitry Andric ConsumeToken(); // consume throw 24940b57cec5SDimitry Andric if (Tok.isNot(tok::semi)) { 24950b57cec5SDimitry Andric Res = ParseExpression(); 24960b57cec5SDimitry Andric if (Res.isInvalid()) { 24970b57cec5SDimitry Andric SkipUntil(tok::semi); 24980b57cec5SDimitry Andric return StmtError(); 24990b57cec5SDimitry Andric } 25000b57cec5SDimitry Andric } 25010b57cec5SDimitry Andric // consume ';' 25020b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw"); 2503*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope()); 25040b57cec5SDimitry Andric } 25050b57cec5SDimitry Andric 25060b57cec5SDimitry Andric /// objc-synchronized-statement: 25070b57cec5SDimitry Andric /// @synchronized '(' expression ')' compound-statement 25080b57cec5SDimitry Andric /// 25090b57cec5SDimitry Andric StmtResult 25100b57cec5SDimitry Andric Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { 25110b57cec5SDimitry Andric ConsumeToken(); // consume synchronized 25120b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) { 25130b57cec5SDimitry Andric Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; 25140b57cec5SDimitry Andric return StmtError(); 25150b57cec5SDimitry Andric } 25160b57cec5SDimitry Andric 25170b57cec5SDimitry Andric // The operand is surrounded with parentheses. 25180b57cec5SDimitry Andric ConsumeParen(); // '(' 25190b57cec5SDimitry Andric ExprResult operand(ParseExpression()); 25200b57cec5SDimitry Andric 25210b57cec5SDimitry Andric if (Tok.is(tok::r_paren)) { 25220b57cec5SDimitry Andric ConsumeParen(); // ')' 25230b57cec5SDimitry Andric } else { 25240b57cec5SDimitry Andric if (!operand.isInvalid()) 25250b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::r_paren; 25260b57cec5SDimitry Andric 25270b57cec5SDimitry Andric // Skip forward until we see a left brace, but don't consume it. 25280b57cec5SDimitry Andric SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); 25290b57cec5SDimitry Andric } 25300b57cec5SDimitry Andric 25310b57cec5SDimitry Andric // Require a compound statement. 25320b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 25330b57cec5SDimitry Andric if (!operand.isInvalid()) 25340b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 25350b57cec5SDimitry Andric return StmtError(); 25360b57cec5SDimitry Andric } 25370b57cec5SDimitry Andric 25380b57cec5SDimitry Andric // Check the @synchronized operand now. 25390b57cec5SDimitry Andric if (!operand.isInvalid()) 2540*0fca6ea1SDimitry Andric operand = 2541*0fca6ea1SDimitry Andric Actions.ObjC().ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric // Parse the compound statement within a new scope. 25440b57cec5SDimitry Andric ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); 25450b57cec5SDimitry Andric StmtResult body(ParseCompoundStatementBody()); 25460b57cec5SDimitry Andric bodyScope.Exit(); 25470b57cec5SDimitry Andric 25480b57cec5SDimitry Andric // If there was a semantic or parse error earlier with the 25490b57cec5SDimitry Andric // operand, fail now. 25500b57cec5SDimitry Andric if (operand.isInvalid()) 25510b57cec5SDimitry Andric return StmtError(); 25520b57cec5SDimitry Andric 25530b57cec5SDimitry Andric if (body.isInvalid()) 25540b57cec5SDimitry Andric body = Actions.ActOnNullStmt(Tok.getLocation()); 25550b57cec5SDimitry Andric 2556*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), 2557*0fca6ea1SDimitry Andric body.get()); 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric 25600b57cec5SDimitry Andric /// objc-try-catch-statement: 25610b57cec5SDimitry Andric /// @try compound-statement objc-catch-list[opt] 25620b57cec5SDimitry Andric /// @try compound-statement objc-catch-list[opt] @finally compound-statement 25630b57cec5SDimitry Andric /// 25640b57cec5SDimitry Andric /// objc-catch-list: 25650b57cec5SDimitry Andric /// @catch ( parameter-declaration ) compound-statement 25660b57cec5SDimitry Andric /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement 25670b57cec5SDimitry Andric /// catch-parameter-declaration: 25680b57cec5SDimitry Andric /// parameter-declaration 25690b57cec5SDimitry Andric /// '...' [OBJC2] 25700b57cec5SDimitry Andric /// 25710b57cec5SDimitry Andric StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { 25720b57cec5SDimitry Andric bool catch_or_finally_seen = false; 25730b57cec5SDimitry Andric 25740b57cec5SDimitry Andric ConsumeToken(); // consume try 25750b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 25760b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 25770b57cec5SDimitry Andric return StmtError(); 25780b57cec5SDimitry Andric } 25790b57cec5SDimitry Andric StmtVector CatchStmts; 25800b57cec5SDimitry Andric StmtResult FinallyStmt; 25810b57cec5SDimitry Andric ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope); 25820b57cec5SDimitry Andric StmtResult TryBody(ParseCompoundStatementBody()); 25830b57cec5SDimitry Andric TryScope.Exit(); 25840b57cec5SDimitry Andric if (TryBody.isInvalid()) 25850b57cec5SDimitry Andric TryBody = Actions.ActOnNullStmt(Tok.getLocation()); 25860b57cec5SDimitry Andric 25870b57cec5SDimitry Andric while (Tok.is(tok::at)) { 25880b57cec5SDimitry Andric // At this point, we need to lookahead to determine if this @ is the start 25890b57cec5SDimitry Andric // of an @catch or @finally. We don't want to consume the @ token if this 25900b57cec5SDimitry Andric // is an @try or @encode or something else. 25910b57cec5SDimitry Andric Token AfterAt = GetLookAheadToken(1); 25920b57cec5SDimitry Andric if (!AfterAt.isObjCAtKeyword(tok::objc_catch) && 25930b57cec5SDimitry Andric !AfterAt.isObjCAtKeyword(tok::objc_finally)) 25940b57cec5SDimitry Andric break; 25950b57cec5SDimitry Andric 25960b57cec5SDimitry Andric SourceLocation AtCatchFinallyLoc = ConsumeToken(); 25970b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_catch)) { 25980b57cec5SDimitry Andric Decl *FirstPart = nullptr; 25990b57cec5SDimitry Andric ConsumeToken(); // consume catch 26000b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 26010b57cec5SDimitry Andric ConsumeParen(); 26020b57cec5SDimitry Andric ParseScope CatchScope(this, Scope::DeclScope | 26030b57cec5SDimitry Andric Scope::CompoundStmtScope | 26040b57cec5SDimitry Andric Scope::AtCatchScope); 26050b57cec5SDimitry Andric if (Tok.isNot(tok::ellipsis)) { 26060b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 2607*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo; 2608*0fca6ea1SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo); 260981ad6265SDimitry Andric Declarator ParmDecl(DS, ParsedAttributesView::none(), 261081ad6265SDimitry Andric DeclaratorContext::ObjCCatch); 26110b57cec5SDimitry Andric ParseDeclarator(ParmDecl); 26120b57cec5SDimitry Andric 26130b57cec5SDimitry Andric // Inform the actions module about the declarator, so it 26140b57cec5SDimitry Andric // gets added to the current scope. 2615*0fca6ea1SDimitry Andric FirstPart = 2616*0fca6ea1SDimitry Andric Actions.ObjC().ActOnObjCExceptionDecl(getCurScope(), ParmDecl); 26170b57cec5SDimitry Andric } else 26180b57cec5SDimitry Andric ConsumeToken(); // consume '...' 26190b57cec5SDimitry Andric 26200b57cec5SDimitry Andric SourceLocation RParenLoc; 26210b57cec5SDimitry Andric 26220b57cec5SDimitry Andric if (Tok.is(tok::r_paren)) 26230b57cec5SDimitry Andric RParenLoc = ConsumeParen(); 26240b57cec5SDimitry Andric else // Skip over garbage, until we get to ')'. Eat the ')'. 26250b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 26260b57cec5SDimitry Andric 26270b57cec5SDimitry Andric StmtResult CatchBody(true); 26280b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) 26290b57cec5SDimitry Andric CatchBody = ParseCompoundStatementBody(); 26300b57cec5SDimitry Andric else 26310b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 26320b57cec5SDimitry Andric if (CatchBody.isInvalid()) 26330b57cec5SDimitry Andric CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); 26340b57cec5SDimitry Andric 2635*0fca6ea1SDimitry Andric StmtResult Catch = Actions.ObjC().ActOnObjCAtCatchStmt( 2636*0fca6ea1SDimitry Andric AtCatchFinallyLoc, RParenLoc, FirstPart, CatchBody.get()); 26370b57cec5SDimitry Andric if (!Catch.isInvalid()) 26380b57cec5SDimitry Andric CatchStmts.push_back(Catch.get()); 26390b57cec5SDimitry Andric 26400b57cec5SDimitry Andric } else { 26410b57cec5SDimitry Andric Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) 26420b57cec5SDimitry Andric << "@catch clause"; 26430b57cec5SDimitry Andric return StmtError(); 26440b57cec5SDimitry Andric } 26450b57cec5SDimitry Andric catch_or_finally_seen = true; 26460b57cec5SDimitry Andric } else { 26470b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); 26480b57cec5SDimitry Andric ConsumeToken(); // consume finally 26490b57cec5SDimitry Andric ParseScope FinallyScope(this, 26500b57cec5SDimitry Andric Scope::DeclScope | Scope::CompoundStmtScope); 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric bool ShouldCapture = 26530b57cec5SDimitry Andric getTargetInfo().getTriple().isWindowsMSVCEnvironment(); 26540b57cec5SDimitry Andric if (ShouldCapture) 26550b57cec5SDimitry Andric Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), 26560b57cec5SDimitry Andric CR_ObjCAtFinally, 1); 26570b57cec5SDimitry Andric 26580b57cec5SDimitry Andric StmtResult FinallyBody(true); 26590b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) 26600b57cec5SDimitry Andric FinallyBody = ParseCompoundStatementBody(); 26610b57cec5SDimitry Andric else 26620b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 26630b57cec5SDimitry Andric 26640b57cec5SDimitry Andric if (FinallyBody.isInvalid()) { 26650b57cec5SDimitry Andric FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); 26660b57cec5SDimitry Andric if (ShouldCapture) 26670b57cec5SDimitry Andric Actions.ActOnCapturedRegionError(); 26680b57cec5SDimitry Andric } else if (ShouldCapture) { 26690b57cec5SDimitry Andric FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); 26700b57cec5SDimitry Andric } 26710b57cec5SDimitry Andric 2672*0fca6ea1SDimitry Andric FinallyStmt = Actions.ObjC().ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, 26730b57cec5SDimitry Andric FinallyBody.get()); 26740b57cec5SDimitry Andric catch_or_finally_seen = true; 26750b57cec5SDimitry Andric break; 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric } 26780b57cec5SDimitry Andric if (!catch_or_finally_seen) { 26790b57cec5SDimitry Andric Diag(atLoc, diag::err_missing_catch_finally); 26800b57cec5SDimitry Andric return StmtError(); 26810b57cec5SDimitry Andric } 26820b57cec5SDimitry Andric 2683*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnObjCAtTryStmt(atLoc, TryBody.get(), CatchStmts, 26840b57cec5SDimitry Andric FinallyStmt.get()); 26850b57cec5SDimitry Andric } 26860b57cec5SDimitry Andric 26870b57cec5SDimitry Andric /// objc-autoreleasepool-statement: 26880b57cec5SDimitry Andric /// @autoreleasepool compound-statement 26890b57cec5SDimitry Andric /// 26900b57cec5SDimitry Andric StmtResult 26910b57cec5SDimitry Andric Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { 26920b57cec5SDimitry Andric ConsumeToken(); // consume autoreleasepool 26930b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 26940b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 26950b57cec5SDimitry Andric return StmtError(); 26960b57cec5SDimitry Andric } 26970b57cec5SDimitry Andric // Enter a scope to hold everything within the compound stmt. Compound 26980b57cec5SDimitry Andric // statements can always hold declarations. 26990b57cec5SDimitry Andric ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); 27000b57cec5SDimitry Andric 27010b57cec5SDimitry Andric StmtResult AutoreleasePoolBody(ParseCompoundStatementBody()); 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric BodyScope.Exit(); 27040b57cec5SDimitry Andric if (AutoreleasePoolBody.isInvalid()) 27050b57cec5SDimitry Andric AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation()); 2706*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnObjCAutoreleasePoolStmt(atLoc, 27070b57cec5SDimitry Andric AutoreleasePoolBody.get()); 27080b57cec5SDimitry Andric } 27090b57cec5SDimitry Andric 27100b57cec5SDimitry Andric /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them 27110b57cec5SDimitry Andric /// for later parsing. 27120b57cec5SDimitry Andric void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { 27130b57cec5SDimitry Andric if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) && 27140b57cec5SDimitry Andric trySkippingFunctionBody()) { 27150b57cec5SDimitry Andric Actions.ActOnSkippedFunctionBody(MDecl); 27160b57cec5SDimitry Andric return; 27170b57cec5SDimitry Andric } 27180b57cec5SDimitry Andric 27190b57cec5SDimitry Andric LexedMethod* LM = new LexedMethod(this, MDecl); 27200b57cec5SDimitry Andric CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); 27210b57cec5SDimitry Andric CachedTokens &Toks = LM->Toks; 27220b57cec5SDimitry Andric // Begin by storing the '{' or 'try' or ':' token. 27230b57cec5SDimitry Andric Toks.push_back(Tok); 27240b57cec5SDimitry Andric if (Tok.is(tok::kw_try)) { 27250b57cec5SDimitry Andric ConsumeToken(); 27260b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 27270b57cec5SDimitry Andric Toks.push_back(Tok); 27280b57cec5SDimitry Andric ConsumeToken(); 27290b57cec5SDimitry Andric while (Tok.isNot(tok::l_brace)) { 27300b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); 27310b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 27320b57cec5SDimitry Andric } 27330b57cec5SDimitry Andric } 27340b57cec5SDimitry Andric Toks.push_back(Tok); // also store '{' 27350b57cec5SDimitry Andric } 27360b57cec5SDimitry Andric else if (Tok.is(tok::colon)) { 27370b57cec5SDimitry Andric ConsumeToken(); 27380b57cec5SDimitry Andric // FIXME: This is wrong, due to C++11 braced initialization. 27390b57cec5SDimitry Andric while (Tok.isNot(tok::l_brace)) { 27400b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); 27410b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 27420b57cec5SDimitry Andric } 27430b57cec5SDimitry Andric Toks.push_back(Tok); // also store '{' 27440b57cec5SDimitry Andric } 27450b57cec5SDimitry Andric ConsumeBrace(); 27460b57cec5SDimitry Andric // Consume everything up to (and including) the matching right brace. 27470b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 27480b57cec5SDimitry Andric while (Tok.is(tok::kw_catch)) { 27490b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 27500b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 27510b57cec5SDimitry Andric } 27520b57cec5SDimitry Andric } 27530b57cec5SDimitry Andric 27540b57cec5SDimitry Andric /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' 27550b57cec5SDimitry Andric /// 27560b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodDefinition() { 27570b57cec5SDimitry Andric Decl *MDecl = ParseObjCMethodPrototype(); 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(), 27600b57cec5SDimitry Andric "parsing Objective-C method"); 27610b57cec5SDimitry Andric 27620b57cec5SDimitry Andric // parse optional ';' 27630b57cec5SDimitry Andric if (Tok.is(tok::semi)) { 27640b57cec5SDimitry Andric if (CurParsedObjCImpl) { 27650b57cec5SDimitry Andric Diag(Tok, diag::warn_semicolon_before_method_body) 27660b57cec5SDimitry Andric << FixItHint::CreateRemoval(Tok.getLocation()); 27670b57cec5SDimitry Andric } 27680b57cec5SDimitry Andric ConsumeToken(); 27690b57cec5SDimitry Andric } 27700b57cec5SDimitry Andric 27710b57cec5SDimitry Andric // We should have an opening brace now. 27720b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 27730b57cec5SDimitry Andric Diag(Tok, diag::err_expected_method_body); 27740b57cec5SDimitry Andric 27750b57cec5SDimitry Andric // Skip over garbage, until we get to '{'. Don't eat the '{'. 27760b57cec5SDimitry Andric SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); 27770b57cec5SDimitry Andric 27780b57cec5SDimitry Andric // If we didn't find the '{', bail out. 27790b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) 27800b57cec5SDimitry Andric return nullptr; 27810b57cec5SDimitry Andric } 27820b57cec5SDimitry Andric 27830b57cec5SDimitry Andric if (!MDecl) { 27840b57cec5SDimitry Andric ConsumeBrace(); 27850b57cec5SDimitry Andric SkipUntil(tok::r_brace); 27860b57cec5SDimitry Andric return nullptr; 27870b57cec5SDimitry Andric } 27880b57cec5SDimitry Andric 27890b57cec5SDimitry Andric // Allow the rest of sema to find private method decl implementations. 2790*0fca6ea1SDimitry Andric Actions.ObjC().AddAnyMethodToGlobalPool(MDecl); 27910b57cec5SDimitry Andric assert (CurParsedObjCImpl 27920b57cec5SDimitry Andric && "ParseObjCMethodDefinition - Method out of @implementation"); 27930b57cec5SDimitry Andric // Consume the tokens and store them for later parsing. 27940b57cec5SDimitry Andric StashAwayMethodOrFunctionBodyTokens(MDecl); 27950b57cec5SDimitry Andric return MDecl; 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric 27980b57cec5SDimitry Andric StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, 27990b57cec5SDimitry Andric ParsedStmtContext StmtCtx) { 28000b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 28010b57cec5SDimitry Andric cutOffParsing(); 2802*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCAtStatement(getCurScope()); 28030b57cec5SDimitry Andric return StmtError(); 28040b57cec5SDimitry Andric } 28050b57cec5SDimitry Andric 28060b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_try)) 28070b57cec5SDimitry Andric return ParseObjCTryStmt(AtLoc); 28080b57cec5SDimitry Andric 28090b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_throw)) 28100b57cec5SDimitry Andric return ParseObjCThrowStmt(AtLoc); 28110b57cec5SDimitry Andric 28120b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_synchronized)) 28130b57cec5SDimitry Andric return ParseObjCSynchronizedStmt(AtLoc); 28140b57cec5SDimitry Andric 28150b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool)) 28160b57cec5SDimitry Andric return ParseObjCAutoreleasePoolStmt(AtLoc); 28170b57cec5SDimitry Andric 28180b57cec5SDimitry Andric if (Tok.isObjCAtKeyword(tok::objc_import) && 28190b57cec5SDimitry Andric getLangOpts().DebuggerSupport) { 28200b57cec5SDimitry Andric SkipUntil(tok::semi); 28210b57cec5SDimitry Andric return Actions.ActOnNullStmt(Tok.getLocation()); 28220b57cec5SDimitry Andric } 28230b57cec5SDimitry Andric 28240b57cec5SDimitry Andric ExprStatementTokLoc = AtLoc; 28250b57cec5SDimitry Andric ExprResult Res(ParseExpressionWithLeadingAt(AtLoc)); 28260b57cec5SDimitry Andric if (Res.isInvalid()) { 28270b57cec5SDimitry Andric // If the expression is invalid, skip ahead to the next semicolon. Not 28280b57cec5SDimitry Andric // doing this opens us up to the possibility of infinite loops if 28290b57cec5SDimitry Andric // ParseExpression does not consume any tokens. 28300b57cec5SDimitry Andric SkipUntil(tok::semi); 28310b57cec5SDimitry Andric return StmtError(); 28320b57cec5SDimitry Andric } 28330b57cec5SDimitry Andric 28340b57cec5SDimitry Andric // Otherwise, eat the semicolon. 28350b57cec5SDimitry Andric ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); 28360b57cec5SDimitry Andric return handleExprStmt(Res, StmtCtx); 28370b57cec5SDimitry Andric } 28380b57cec5SDimitry Andric 28390b57cec5SDimitry Andric ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { 28400b57cec5SDimitry Andric switch (Tok.getKind()) { 28410b57cec5SDimitry Andric case tok::code_completion: 28420b57cec5SDimitry Andric cutOffParsing(); 2843*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCAtExpression(getCurScope()); 28440b57cec5SDimitry Andric return ExprError(); 28450b57cec5SDimitry Andric 28460b57cec5SDimitry Andric case tok::minus: 28470b57cec5SDimitry Andric case tok::plus: { 28480b57cec5SDimitry Andric tok::TokenKind Kind = Tok.getKind(); 28490b57cec5SDimitry Andric SourceLocation OpLoc = ConsumeToken(); 28500b57cec5SDimitry Andric 28510b57cec5SDimitry Andric if (!Tok.is(tok::numeric_constant)) { 28520b57cec5SDimitry Andric const char *Symbol = nullptr; 28530b57cec5SDimitry Andric switch (Kind) { 28540b57cec5SDimitry Andric case tok::minus: Symbol = "-"; break; 28550b57cec5SDimitry Andric case tok::plus: Symbol = "+"; break; 28560b57cec5SDimitry Andric default: llvm_unreachable("missing unary operator case"); 28570b57cec5SDimitry Andric } 28580b57cec5SDimitry Andric Diag(Tok, diag::err_nsnumber_nonliteral_unary) 28590b57cec5SDimitry Andric << Symbol; 28600b57cec5SDimitry Andric return ExprError(); 28610b57cec5SDimitry Andric } 28620b57cec5SDimitry Andric 28630b57cec5SDimitry Andric ExprResult Lit(Actions.ActOnNumericConstant(Tok)); 28640b57cec5SDimitry Andric if (Lit.isInvalid()) { 28650b57cec5SDimitry Andric return Lit; 28660b57cec5SDimitry Andric } 28670b57cec5SDimitry Andric ConsumeToken(); // Consume the literal token. 28680b57cec5SDimitry Andric 28690b57cec5SDimitry Andric Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get()); 28700b57cec5SDimitry Andric if (Lit.isInvalid()) 28710b57cec5SDimitry Andric return Lit; 28720b57cec5SDimitry Andric 28730b57cec5SDimitry Andric return ParsePostfixExpressionSuffix( 2874*0fca6ea1SDimitry Andric Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get())); 28750b57cec5SDimitry Andric } 28760b57cec5SDimitry Andric 28770b57cec5SDimitry Andric case tok::string_literal: // primary-expression: string-literal 28780b57cec5SDimitry Andric case tok::wide_string_literal: 28790b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc)); 28800b57cec5SDimitry Andric 28810b57cec5SDimitry Andric case tok::char_constant: 28820b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc)); 28830b57cec5SDimitry Andric 28840b57cec5SDimitry Andric case tok::numeric_constant: 28850b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc)); 28860b57cec5SDimitry Andric 28870b57cec5SDimitry Andric case tok::kw_true: // Objective-C++, etc. 28880b57cec5SDimitry Andric case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes 28890b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true)); 28900b57cec5SDimitry Andric case tok::kw_false: // Objective-C++, etc. 28910b57cec5SDimitry Andric case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no 28920b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false)); 28930b57cec5SDimitry Andric 28940b57cec5SDimitry Andric case tok::l_square: 28950b57cec5SDimitry Andric // Objective-C array literal 28960b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc)); 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric case tok::l_brace: 28990b57cec5SDimitry Andric // Objective-C dictionary literal 29000b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc)); 29010b57cec5SDimitry Andric 29020b57cec5SDimitry Andric case tok::l_paren: 29030b57cec5SDimitry Andric // Objective-C boxed expression 29040b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc)); 29050b57cec5SDimitry Andric 29060b57cec5SDimitry Andric default: 29070b57cec5SDimitry Andric if (Tok.getIdentifierInfo() == nullptr) 29080b57cec5SDimitry Andric return ExprError(Diag(AtLoc, diag::err_unexpected_at)); 29090b57cec5SDimitry Andric 29100b57cec5SDimitry Andric switch (Tok.getIdentifierInfo()->getObjCKeywordID()) { 29110b57cec5SDimitry Andric case tok::objc_encode: 29120b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc)); 29130b57cec5SDimitry Andric case tok::objc_protocol: 29140b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc)); 29150b57cec5SDimitry Andric case tok::objc_selector: 29160b57cec5SDimitry Andric return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); 29170b57cec5SDimitry Andric case tok::objc_available: 29180b57cec5SDimitry Andric return ParseAvailabilityCheckExpr(AtLoc); 29190b57cec5SDimitry Andric default: { 29200b57cec5SDimitry Andric const char *str = nullptr; 29210b57cec5SDimitry Andric // Only provide the @try/@finally/@autoreleasepool fixit when we're sure 29220b57cec5SDimitry Andric // that this is a proper statement where such directives could actually 29230b57cec5SDimitry Andric // occur. 29240b57cec5SDimitry Andric if (GetLookAheadToken(1).is(tok::l_brace) && 29250b57cec5SDimitry Andric ExprStatementTokLoc == AtLoc) { 29260b57cec5SDimitry Andric char ch = Tok.getIdentifierInfo()->getNameStart()[0]; 29270b57cec5SDimitry Andric str = 29280b57cec5SDimitry Andric ch == 't' ? "try" 29290b57cec5SDimitry Andric : (ch == 'f' ? "finally" 29300b57cec5SDimitry Andric : (ch == 'a' ? "autoreleasepool" : nullptr)); 29310b57cec5SDimitry Andric } 29320b57cec5SDimitry Andric if (str) { 29330b57cec5SDimitry Andric SourceLocation kwLoc = Tok.getLocation(); 29340b57cec5SDimitry Andric return ExprError(Diag(AtLoc, diag::err_unexpected_at) << 29350b57cec5SDimitry Andric FixItHint::CreateReplacement(kwLoc, str)); 29360b57cec5SDimitry Andric } 29370b57cec5SDimitry Andric else 29380b57cec5SDimitry Andric return ExprError(Diag(AtLoc, diag::err_unexpected_at)); 29390b57cec5SDimitry Andric } 29400b57cec5SDimitry Andric } 29410b57cec5SDimitry Andric } 29420b57cec5SDimitry Andric } 29430b57cec5SDimitry Andric 29440b57cec5SDimitry Andric /// Parse the receiver of an Objective-C++ message send. 29450b57cec5SDimitry Andric /// 29460b57cec5SDimitry Andric /// This routine parses the receiver of a message send in 29470b57cec5SDimitry Andric /// Objective-C++ either as a type or as an expression. Note that this 29480b57cec5SDimitry Andric /// routine must not be called to parse a send to 'super', since it 29490b57cec5SDimitry Andric /// has no way to return such a result. 29500b57cec5SDimitry Andric /// 29510b57cec5SDimitry Andric /// \param IsExpr Whether the receiver was parsed as an expression. 29520b57cec5SDimitry Andric /// 29530b57cec5SDimitry Andric /// \param TypeOrExpr If the receiver was parsed as an expression (\c 29540b57cec5SDimitry Andric /// IsExpr is true), the parsed expression. If the receiver was parsed 29550b57cec5SDimitry Andric /// as a type (\c IsExpr is false), the parsed type. 29560b57cec5SDimitry Andric /// 29570b57cec5SDimitry Andric /// \returns True if an error occurred during parsing or semantic 29580b57cec5SDimitry Andric /// analysis, in which case the arguments do not have valid 29590b57cec5SDimitry Andric /// values. Otherwise, returns false for a successful parse. 29600b57cec5SDimitry Andric /// 29610b57cec5SDimitry Andric /// objc-receiver: [C++] 29620b57cec5SDimitry Andric /// 'super' [not parsed here] 29630b57cec5SDimitry Andric /// expression 29640b57cec5SDimitry Andric /// simple-type-specifier 29650b57cec5SDimitry Andric /// typename-specifier 29660b57cec5SDimitry Andric bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { 29670b57cec5SDimitry Andric InMessageExpressionRAIIObject InMessage(*this, true); 29680b57cec5SDimitry Andric 29690b57cec5SDimitry Andric if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename, 29700b57cec5SDimitry Andric tok::annot_cxxscope)) 29710b57cec5SDimitry Andric TryAnnotateTypeOrScopeToken(); 29720b57cec5SDimitry Andric 2973*0fca6ea1SDimitry Andric if (!Tok.isSimpleTypeSpecifier(getLangOpts())) { 29740b57cec5SDimitry Andric // objc-receiver: 29750b57cec5SDimitry Andric // expression 29760b57cec5SDimitry Andric // Make sure any typos in the receiver are corrected or diagnosed, so that 29770b57cec5SDimitry Andric // proper recovery can happen. FIXME: Perhaps filter the corrected expr to 29780b57cec5SDimitry Andric // only the things that are valid ObjC receivers? 29790b57cec5SDimitry Andric ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression()); 29800b57cec5SDimitry Andric if (Receiver.isInvalid()) 29810b57cec5SDimitry Andric return true; 29820b57cec5SDimitry Andric 29830b57cec5SDimitry Andric IsExpr = true; 29840b57cec5SDimitry Andric TypeOrExpr = Receiver.get(); 29850b57cec5SDimitry Andric return false; 29860b57cec5SDimitry Andric } 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric // objc-receiver: 29890b57cec5SDimitry Andric // typename-specifier 29900b57cec5SDimitry Andric // simple-type-specifier 29910b57cec5SDimitry Andric // expression (that starts with one of the above) 29920b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 29930b57cec5SDimitry Andric ParseCXXSimpleTypeSpecifier(DS); 29940b57cec5SDimitry Andric 29950b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 29960b57cec5SDimitry Andric // If we see an opening parentheses at this point, we are 29970b57cec5SDimitry Andric // actually parsing an expression that starts with a 29980b57cec5SDimitry Andric // function-style cast, e.g., 29990b57cec5SDimitry Andric // 30000b57cec5SDimitry Andric // postfix-expression: 30010b57cec5SDimitry Andric // simple-type-specifier ( expression-list [opt] ) 30020b57cec5SDimitry Andric // typename-specifier ( expression-list [opt] ) 30030b57cec5SDimitry Andric // 30040b57cec5SDimitry Andric // Parse the remainder of this case, then the (optional) 30050b57cec5SDimitry Andric // postfix-expression suffix, followed by the (optional) 30060b57cec5SDimitry Andric // right-hand side of the binary expression. We have an 30070b57cec5SDimitry Andric // instance method. 30080b57cec5SDimitry Andric ExprResult Receiver = ParseCXXTypeConstructExpression(DS); 30090b57cec5SDimitry Andric if (!Receiver.isInvalid()) 30100b57cec5SDimitry Andric Receiver = ParsePostfixExpressionSuffix(Receiver.get()); 30110b57cec5SDimitry Andric if (!Receiver.isInvalid()) 30120b57cec5SDimitry Andric Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma); 30130b57cec5SDimitry Andric if (Receiver.isInvalid()) 30140b57cec5SDimitry Andric return true; 30150b57cec5SDimitry Andric 30160b57cec5SDimitry Andric IsExpr = true; 30170b57cec5SDimitry Andric TypeOrExpr = Receiver.get(); 30180b57cec5SDimitry Andric return false; 30190b57cec5SDimitry Andric } 30200b57cec5SDimitry Andric 30210b57cec5SDimitry Andric // We have a class message. Turn the simple-type-specifier or 30220b57cec5SDimitry Andric // typename-specifier we parsed into a type and parse the 30230b57cec5SDimitry Andric // remainder of the class message. 302481ad6265SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), 302581ad6265SDimitry Andric DeclaratorContext::TypeName); 30267a6dacacSDimitry Andric TypeResult Type = Actions.ActOnTypeName(DeclaratorInfo); 30270b57cec5SDimitry Andric if (Type.isInvalid()) 30280b57cec5SDimitry Andric return true; 30290b57cec5SDimitry Andric 30300b57cec5SDimitry Andric IsExpr = false; 30310b57cec5SDimitry Andric TypeOrExpr = Type.get().getAsOpaquePtr(); 30320b57cec5SDimitry Andric return false; 30330b57cec5SDimitry Andric } 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric /// Determine whether the parser is currently referring to a an 30360b57cec5SDimitry Andric /// Objective-C message send, using a simplified heuristic to avoid overhead. 30370b57cec5SDimitry Andric /// 30380b57cec5SDimitry Andric /// This routine will only return true for a subset of valid message-send 30390b57cec5SDimitry Andric /// expressions. 30400b57cec5SDimitry Andric bool Parser::isSimpleObjCMessageExpression() { 30410b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && getLangOpts().ObjC && 30420b57cec5SDimitry Andric "Incorrect start for isSimpleObjCMessageExpression"); 30430b57cec5SDimitry Andric return GetLookAheadToken(1).is(tok::identifier) && 30440b57cec5SDimitry Andric GetLookAheadToken(2).is(tok::identifier); 30450b57cec5SDimitry Andric } 30460b57cec5SDimitry Andric 30470b57cec5SDimitry Andric bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { 30480b57cec5SDimitry Andric if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) || 30490b57cec5SDimitry Andric InMessageExpression) 30500b57cec5SDimitry Andric return false; 30510b57cec5SDimitry Andric 30525ffd83dbSDimitry Andric TypeResult Type; 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric if (Tok.is(tok::annot_typename)) 30550b57cec5SDimitry Andric Type = getTypeAnnotation(Tok); 30560b57cec5SDimitry Andric else if (Tok.is(tok::identifier)) 30570b57cec5SDimitry Andric Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), 30580b57cec5SDimitry Andric getCurScope()); 30590b57cec5SDimitry Andric else 30600b57cec5SDimitry Andric return false; 30610b57cec5SDimitry Andric 30625ffd83dbSDimitry Andric // FIXME: Should not be querying properties of types from the parser. 30635ffd83dbSDimitry Andric if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) { 30640b57cec5SDimitry Andric const Token &AfterNext = GetLookAheadToken(2); 30650b57cec5SDimitry Andric if (AfterNext.isOneOf(tok::colon, tok::r_square)) { 30660b57cec5SDimitry Andric if (Tok.is(tok::identifier)) 30670b57cec5SDimitry Andric TryAnnotateTypeOrScopeToken(); 30680b57cec5SDimitry Andric 30690b57cec5SDimitry Andric return Tok.is(tok::annot_typename); 30700b57cec5SDimitry Andric } 30710b57cec5SDimitry Andric } 30720b57cec5SDimitry Andric 30730b57cec5SDimitry Andric return false; 30740b57cec5SDimitry Andric } 30750b57cec5SDimitry Andric 30760b57cec5SDimitry Andric /// objc-message-expr: 30770b57cec5SDimitry Andric /// '[' objc-receiver objc-message-args ']' 30780b57cec5SDimitry Andric /// 30790b57cec5SDimitry Andric /// objc-receiver: [C] 30800b57cec5SDimitry Andric /// 'super' 30810b57cec5SDimitry Andric /// expression 30820b57cec5SDimitry Andric /// class-name 30830b57cec5SDimitry Andric /// type-name 30840b57cec5SDimitry Andric /// 30850b57cec5SDimitry Andric ExprResult Parser::ParseObjCMessageExpression() { 30860b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && "'[' expected"); 30870b57cec5SDimitry Andric SourceLocation LBracLoc = ConsumeBracket(); // consume '[' 30880b57cec5SDimitry Andric 30890b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 30900b57cec5SDimitry Andric cutOffParsing(); 3091*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope()); 30920b57cec5SDimitry Andric return ExprError(); 30930b57cec5SDimitry Andric } 30940b57cec5SDimitry Andric 30950b57cec5SDimitry Andric InMessageExpressionRAIIObject InMessage(*this, true); 30960b57cec5SDimitry Andric 30970b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) { 30980b57cec5SDimitry Andric // We completely separate the C and C++ cases because C++ requires 30990b57cec5SDimitry Andric // more complicated (read: slower) parsing. 31000b57cec5SDimitry Andric 31010b57cec5SDimitry Andric // Handle send to super. 31020b57cec5SDimitry Andric // FIXME: This doesn't benefit from the same typo-correction we 31030b57cec5SDimitry Andric // get in Objective-C. 31040b57cec5SDimitry Andric if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && 31050b57cec5SDimitry Andric NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) 31060b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr, 31070b57cec5SDimitry Andric nullptr); 31080b57cec5SDimitry Andric 31090b57cec5SDimitry Andric // Parse the receiver, which is either a type or an expression. 31100b57cec5SDimitry Andric bool IsExpr; 31110b57cec5SDimitry Andric void *TypeOrExpr = nullptr; 31120b57cec5SDimitry Andric if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { 31130b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 31140b57cec5SDimitry Andric return ExprError(); 31150b57cec5SDimitry Andric } 31160b57cec5SDimitry Andric 31170b57cec5SDimitry Andric if (IsExpr) 31180b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr, 31190b57cec5SDimitry Andric static_cast<Expr *>(TypeOrExpr)); 31200b57cec5SDimitry Andric 31210b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 31220b57cec5SDimitry Andric ParsedType::getFromOpaquePtr(TypeOrExpr), 31230b57cec5SDimitry Andric nullptr); 31240b57cec5SDimitry Andric } 31250b57cec5SDimitry Andric 31260b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 31270b57cec5SDimitry Andric IdentifierInfo *Name = Tok.getIdentifierInfo(); 31280b57cec5SDimitry Andric SourceLocation NameLoc = Tok.getLocation(); 31290b57cec5SDimitry Andric ParsedType ReceiverType; 3130*0fca6ea1SDimitry Andric switch (Actions.ObjC().getObjCMessageKind( 3131*0fca6ea1SDimitry Andric getCurScope(), Name, NameLoc, Name == Ident_super, 3132*0fca6ea1SDimitry Andric NextToken().is(tok::period), ReceiverType)) { 3133*0fca6ea1SDimitry Andric case SemaObjC::ObjCSuperMessage: 31340b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr, 31350b57cec5SDimitry Andric nullptr); 31360b57cec5SDimitry Andric 3137*0fca6ea1SDimitry Andric case SemaObjC::ObjCClassMessage: 31380b57cec5SDimitry Andric if (!ReceiverType) { 31390b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 31400b57cec5SDimitry Andric return ExprError(); 31410b57cec5SDimitry Andric } 31420b57cec5SDimitry Andric 31430b57cec5SDimitry Andric ConsumeToken(); // the type name 31440b57cec5SDimitry Andric 31450b57cec5SDimitry Andric // Parse type arguments and protocol qualifiers. 31460b57cec5SDimitry Andric if (Tok.is(tok::less)) { 31470b57cec5SDimitry Andric SourceLocation NewEndLoc; 31480b57cec5SDimitry Andric TypeResult NewReceiverType 31490b57cec5SDimitry Andric = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType, 31500b57cec5SDimitry Andric /*consumeLastToken=*/true, 31510b57cec5SDimitry Andric NewEndLoc); 31520b57cec5SDimitry Andric if (!NewReceiverType.isUsable()) { 31530b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 31540b57cec5SDimitry Andric return ExprError(); 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric 31570b57cec5SDimitry Andric ReceiverType = NewReceiverType.get(); 31580b57cec5SDimitry Andric } 31590b57cec5SDimitry Andric 31600b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 31610b57cec5SDimitry Andric ReceiverType, nullptr); 31620b57cec5SDimitry Andric 3163*0fca6ea1SDimitry Andric case SemaObjC::ObjCInstanceMessage: 31640b57cec5SDimitry Andric // Fall through to parse an expression. 31650b57cec5SDimitry Andric break; 31660b57cec5SDimitry Andric } 31670b57cec5SDimitry Andric } 31680b57cec5SDimitry Andric 31690b57cec5SDimitry Andric // Otherwise, an arbitrary expression can be the receiver of a send. 31700b57cec5SDimitry Andric ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); 31710b57cec5SDimitry Andric if (Res.isInvalid()) { 31720b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 31730b57cec5SDimitry Andric return Res; 31740b57cec5SDimitry Andric } 31750b57cec5SDimitry Andric 31760b57cec5SDimitry Andric return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr, 31770b57cec5SDimitry Andric Res.get()); 31780b57cec5SDimitry Andric } 31790b57cec5SDimitry Andric 31800b57cec5SDimitry Andric /// Parse the remainder of an Objective-C message following the 31810b57cec5SDimitry Andric /// '[' objc-receiver. 31820b57cec5SDimitry Andric /// 31830b57cec5SDimitry Andric /// This routine handles sends to super, class messages (sent to a 31840b57cec5SDimitry Andric /// class name), and instance messages (sent to an object), and the 31850b57cec5SDimitry Andric /// target is represented by \p SuperLoc, \p ReceiverType, or \p 31860b57cec5SDimitry Andric /// ReceiverExpr, respectively. Only one of these parameters may have 31870b57cec5SDimitry Andric /// a valid value. 31880b57cec5SDimitry Andric /// 31890b57cec5SDimitry Andric /// \param LBracLoc The location of the opening '['. 31900b57cec5SDimitry Andric /// 31910b57cec5SDimitry Andric /// \param SuperLoc If this is a send to 'super', the location of the 31920b57cec5SDimitry Andric /// 'super' keyword that indicates a send to the superclass. 31930b57cec5SDimitry Andric /// 31940b57cec5SDimitry Andric /// \param ReceiverType If this is a class message, the type of the 31950b57cec5SDimitry Andric /// class we are sending a message to. 31960b57cec5SDimitry Andric /// 31970b57cec5SDimitry Andric /// \param ReceiverExpr If this is an instance message, the expression 31980b57cec5SDimitry Andric /// used to compute the receiver object. 31990b57cec5SDimitry Andric /// 32000b57cec5SDimitry Andric /// objc-message-args: 32010b57cec5SDimitry Andric /// objc-selector 32020b57cec5SDimitry Andric /// objc-keywordarg-list 32030b57cec5SDimitry Andric /// 32040b57cec5SDimitry Andric /// objc-keywordarg-list: 32050b57cec5SDimitry Andric /// objc-keywordarg 32060b57cec5SDimitry Andric /// objc-keywordarg-list objc-keywordarg 32070b57cec5SDimitry Andric /// 32080b57cec5SDimitry Andric /// objc-keywordarg: 32090b57cec5SDimitry Andric /// selector-name[opt] ':' objc-keywordexpr 32100b57cec5SDimitry Andric /// 32110b57cec5SDimitry Andric /// objc-keywordexpr: 32120b57cec5SDimitry Andric /// nonempty-expr-list 32130b57cec5SDimitry Andric /// 32140b57cec5SDimitry Andric /// nonempty-expr-list: 32150b57cec5SDimitry Andric /// assignment-expression 32160b57cec5SDimitry Andric /// nonempty-expr-list , assignment-expression 32170b57cec5SDimitry Andric /// 32180b57cec5SDimitry Andric ExprResult 32190b57cec5SDimitry Andric Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, 32200b57cec5SDimitry Andric SourceLocation SuperLoc, 32210b57cec5SDimitry Andric ParsedType ReceiverType, 32220b57cec5SDimitry Andric Expr *ReceiverExpr) { 32230b57cec5SDimitry Andric InMessageExpressionRAIIObject InMessage(*this, true); 32240b57cec5SDimitry Andric 32250b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3226fe6060f1SDimitry Andric cutOffParsing(); 32270b57cec5SDimitry Andric if (SuperLoc.isValid()) 3228*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSuperMessage( 3229*0fca6ea1SDimitry Andric getCurScope(), SuperLoc, std::nullopt, false); 32300b57cec5SDimitry Andric else if (ReceiverType) 3231*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCClassMessage( 3232*0fca6ea1SDimitry Andric getCurScope(), ReceiverType, std::nullopt, false); 32330b57cec5SDimitry Andric else 3234*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( 3235*0fca6ea1SDimitry Andric getCurScope(), ReceiverExpr, std::nullopt, false); 32360b57cec5SDimitry Andric return ExprError(); 32370b57cec5SDimitry Andric } 32380b57cec5SDimitry Andric 32390b57cec5SDimitry Andric // Parse objc-selector 32400b57cec5SDimitry Andric SourceLocation Loc; 32410b57cec5SDimitry Andric IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); 32420b57cec5SDimitry Andric 3243*0fca6ea1SDimitry Andric SmallVector<const IdentifierInfo *, 12> KeyIdents; 32440b57cec5SDimitry Andric SmallVector<SourceLocation, 12> KeyLocs; 32450b57cec5SDimitry Andric ExprVector KeyExprs; 32460b57cec5SDimitry Andric 32470b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 324804eeddc0SDimitry Andric while (true) { 32490b57cec5SDimitry Andric // Each iteration parses a single keyword argument. 32500b57cec5SDimitry Andric KeyIdents.push_back(selIdent); 32510b57cec5SDimitry Andric KeyLocs.push_back(Loc); 32520b57cec5SDimitry Andric 32530b57cec5SDimitry Andric if (ExpectAndConsume(tok::colon)) { 32540b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 32550b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 32560b57cec5SDimitry Andric // the enclosing expression. 32570b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 32580b57cec5SDimitry Andric return ExprError(); 32590b57cec5SDimitry Andric } 32600b57cec5SDimitry Andric 32610b57cec5SDimitry Andric /// Parse the expression after ':' 32620b57cec5SDimitry Andric 32630b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3264fe6060f1SDimitry Andric cutOffParsing(); 32650b57cec5SDimitry Andric if (SuperLoc.isValid()) 3266*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSuperMessage( 3267*0fca6ea1SDimitry Andric getCurScope(), SuperLoc, KeyIdents, 32680b57cec5SDimitry Andric /*AtArgumentExpression=*/true); 32690b57cec5SDimitry Andric else if (ReceiverType) 3270*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCClassMessage( 3271*0fca6ea1SDimitry Andric getCurScope(), ReceiverType, KeyIdents, 32720b57cec5SDimitry Andric /*AtArgumentExpression=*/true); 32730b57cec5SDimitry Andric else 3274*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( 3275*0fca6ea1SDimitry Andric getCurScope(), ReceiverExpr, KeyIdents, 32760b57cec5SDimitry Andric /*AtArgumentExpression=*/true); 32770b57cec5SDimitry Andric 32780b57cec5SDimitry Andric return ExprError(); 32790b57cec5SDimitry Andric } 32800b57cec5SDimitry Andric 32810b57cec5SDimitry Andric ExprResult Expr; 32820b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 32830b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 32840b57cec5SDimitry Andric Expr = ParseBraceInitializer(); 32850b57cec5SDimitry Andric } else 32860b57cec5SDimitry Andric Expr = ParseAssignmentExpression(); 32870b57cec5SDimitry Andric 32880b57cec5SDimitry Andric ExprResult Res(Expr); 32890b57cec5SDimitry Andric if (Res.isInvalid()) { 32900b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 32910b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 32920b57cec5SDimitry Andric // the enclosing expression. 32930b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 32940b57cec5SDimitry Andric return Res; 32950b57cec5SDimitry Andric } 32960b57cec5SDimitry Andric 32970b57cec5SDimitry Andric // We have a valid expression. 32980b57cec5SDimitry Andric KeyExprs.push_back(Res.get()); 32990b57cec5SDimitry Andric 33000b57cec5SDimitry Andric // Code completion after each argument. 33010b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3302fe6060f1SDimitry Andric cutOffParsing(); 33030b57cec5SDimitry Andric if (SuperLoc.isValid()) 3304*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSuperMessage( 3305*0fca6ea1SDimitry Andric getCurScope(), SuperLoc, KeyIdents, 33060b57cec5SDimitry Andric /*AtArgumentExpression=*/false); 33070b57cec5SDimitry Andric else if (ReceiverType) 3308*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCClassMessage( 3309*0fca6ea1SDimitry Andric getCurScope(), ReceiverType, KeyIdents, 33100b57cec5SDimitry Andric /*AtArgumentExpression=*/false); 33110b57cec5SDimitry Andric else 3312*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( 3313*0fca6ea1SDimitry Andric getCurScope(), ReceiverExpr, KeyIdents, 33140b57cec5SDimitry Andric /*AtArgumentExpression=*/false); 33150b57cec5SDimitry Andric return ExprError(); 33160b57cec5SDimitry Andric } 33170b57cec5SDimitry Andric 33180b57cec5SDimitry Andric // Check for another keyword selector. 33190b57cec5SDimitry Andric selIdent = ParseObjCSelectorPiece(Loc); 33200b57cec5SDimitry Andric if (!selIdent && Tok.isNot(tok::colon)) 33210b57cec5SDimitry Andric break; 33220b57cec5SDimitry Andric // We have a selector or a colon, continue parsing. 33230b57cec5SDimitry Andric } 33240b57cec5SDimitry Andric // Parse the, optional, argument list, comma separated. 33250b57cec5SDimitry Andric while (Tok.is(tok::comma)) { 33260b57cec5SDimitry Andric SourceLocation commaLoc = ConsumeToken(); // Eat the ','. 33270b57cec5SDimitry Andric /// Parse the expression after ',' 33280b57cec5SDimitry Andric ExprResult Res(ParseAssignmentExpression()); 33290b57cec5SDimitry Andric if (Tok.is(tok::colon)) 33300b57cec5SDimitry Andric Res = Actions.CorrectDelayedTyposInExpr(Res); 33310b57cec5SDimitry Andric if (Res.isInvalid()) { 33320b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 33330b57cec5SDimitry Andric Diag(commaLoc, diag::note_extra_comma_message_arg) << 33340b57cec5SDimitry Andric FixItHint::CreateRemoval(commaLoc); 33350b57cec5SDimitry Andric } 33360b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 33370b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 33380b57cec5SDimitry Andric // the enclosing expression. 33390b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 33400b57cec5SDimitry Andric return Res; 33410b57cec5SDimitry Andric } 33420b57cec5SDimitry Andric 33430b57cec5SDimitry Andric // We have a valid expression. 33440b57cec5SDimitry Andric KeyExprs.push_back(Res.get()); 33450b57cec5SDimitry Andric } 33460b57cec5SDimitry Andric } else if (!selIdent) { 33470b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name. 33480b57cec5SDimitry Andric 33490b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 33500b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 33510b57cec5SDimitry Andric // the enclosing expression. 33520b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 33530b57cec5SDimitry Andric return ExprError(); 33540b57cec5SDimitry Andric } 33550b57cec5SDimitry Andric 33560b57cec5SDimitry Andric if (Tok.isNot(tok::r_square)) { 33570b57cec5SDimitry Andric Diag(Tok, diag::err_expected) 33580b57cec5SDimitry Andric << (Tok.is(tok::identifier) ? tok::colon : tok::r_square); 33590b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 33600b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 33610b57cec5SDimitry Andric // the enclosing expression. 33620b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 33630b57cec5SDimitry Andric return ExprError(); 33640b57cec5SDimitry Andric } 33650b57cec5SDimitry Andric 33660b57cec5SDimitry Andric SourceLocation RBracLoc = ConsumeBracket(); // consume ']' 33670b57cec5SDimitry Andric 33680b57cec5SDimitry Andric unsigned nKeys = KeyIdents.size(); 33690b57cec5SDimitry Andric if (nKeys == 0) { 33700b57cec5SDimitry Andric KeyIdents.push_back(selIdent); 33710b57cec5SDimitry Andric KeyLocs.push_back(Loc); 33720b57cec5SDimitry Andric } 33730b57cec5SDimitry Andric Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); 33740b57cec5SDimitry Andric 33750b57cec5SDimitry Andric if (SuperLoc.isValid()) 3376*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnSuperMessage( 3377*0fca6ea1SDimitry Andric getCurScope(), SuperLoc, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs); 33780b57cec5SDimitry Andric else if (ReceiverType) 3379*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnClassMessage(getCurScope(), ReceiverType, Sel, 3380*0fca6ea1SDimitry Andric LBracLoc, KeyLocs, RBracLoc, 3381*0fca6ea1SDimitry Andric KeyExprs); 3382*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnInstanceMessage( 3383*0fca6ea1SDimitry Andric getCurScope(), ReceiverExpr, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs); 33840b57cec5SDimitry Andric } 33850b57cec5SDimitry Andric 33860b57cec5SDimitry Andric ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { 33870b57cec5SDimitry Andric ExprResult Res(ParseStringLiteralExpression()); 33880b57cec5SDimitry Andric if (Res.isInvalid()) return Res; 33890b57cec5SDimitry Andric 33900b57cec5SDimitry Andric // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string 33910b57cec5SDimitry Andric // expressions. At this point, we know that the only valid thing that starts 33920b57cec5SDimitry Andric // with '@' is an @"". 33930b57cec5SDimitry Andric SmallVector<SourceLocation, 4> AtLocs; 33940b57cec5SDimitry Andric ExprVector AtStrings; 33950b57cec5SDimitry Andric AtLocs.push_back(AtLoc); 33960b57cec5SDimitry Andric AtStrings.push_back(Res.get()); 33970b57cec5SDimitry Andric 33980b57cec5SDimitry Andric while (Tok.is(tok::at)) { 33990b57cec5SDimitry Andric AtLocs.push_back(ConsumeToken()); // eat the @. 34000b57cec5SDimitry Andric 34010b57cec5SDimitry Andric // Invalid unless there is a string literal. 34020b57cec5SDimitry Andric if (!isTokenStringLiteral()) 34030b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_objc_concat_string)); 34040b57cec5SDimitry Andric 34050b57cec5SDimitry Andric ExprResult Lit(ParseStringLiteralExpression()); 34060b57cec5SDimitry Andric if (Lit.isInvalid()) 34070b57cec5SDimitry Andric return Lit; 34080b57cec5SDimitry Andric 34090b57cec5SDimitry Andric AtStrings.push_back(Lit.get()); 34100b57cec5SDimitry Andric } 34110b57cec5SDimitry Andric 3412*0fca6ea1SDimitry Andric return Actions.ObjC().ParseObjCStringLiteral(AtLocs.data(), AtStrings); 34130b57cec5SDimitry Andric } 34140b57cec5SDimitry Andric 34150b57cec5SDimitry Andric /// ParseObjCBooleanLiteral - 34160b57cec5SDimitry Andric /// objc-scalar-literal : '@' boolean-keyword 34170b57cec5SDimitry Andric /// ; 34180b57cec5SDimitry Andric /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no' 34190b57cec5SDimitry Andric /// ; 34200b57cec5SDimitry Andric ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, 34210b57cec5SDimitry Andric bool ArgValue) { 34220b57cec5SDimitry Andric SourceLocation EndLoc = ConsumeToken(); // consume the keyword. 3423*0fca6ea1SDimitry Andric return Actions.ObjC().ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue); 34240b57cec5SDimitry Andric } 34250b57cec5SDimitry Andric 34260b57cec5SDimitry Andric /// ParseObjCCharacterLiteral - 34270b57cec5SDimitry Andric /// objc-scalar-literal : '@' character-literal 34280b57cec5SDimitry Andric /// ; 34290b57cec5SDimitry Andric ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { 34300b57cec5SDimitry Andric ExprResult Lit(Actions.ActOnCharacterConstant(Tok)); 34310b57cec5SDimitry Andric if (Lit.isInvalid()) { 34320b57cec5SDimitry Andric return Lit; 34330b57cec5SDimitry Andric } 34340b57cec5SDimitry Andric ConsumeToken(); // Consume the literal token. 3435*0fca6ea1SDimitry Andric return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()); 34360b57cec5SDimitry Andric } 34370b57cec5SDimitry Andric 34380b57cec5SDimitry Andric /// ParseObjCNumericLiteral - 34390b57cec5SDimitry Andric /// objc-scalar-literal : '@' scalar-literal 34400b57cec5SDimitry Andric /// ; 34410b57cec5SDimitry Andric /// scalar-literal : | numeric-constant /* any numeric constant. */ 34420b57cec5SDimitry Andric /// ; 34430b57cec5SDimitry Andric ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { 34440b57cec5SDimitry Andric ExprResult Lit(Actions.ActOnNumericConstant(Tok)); 34450b57cec5SDimitry Andric if (Lit.isInvalid()) { 34460b57cec5SDimitry Andric return Lit; 34470b57cec5SDimitry Andric } 34480b57cec5SDimitry Andric ConsumeToken(); // Consume the literal token. 3449*0fca6ea1SDimitry Andric return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()); 34500b57cec5SDimitry Andric } 34510b57cec5SDimitry Andric 34520b57cec5SDimitry Andric /// ParseObjCBoxedExpr - 34530b57cec5SDimitry Andric /// objc-box-expression: 34540b57cec5SDimitry Andric /// @( assignment-expression ) 34550b57cec5SDimitry Andric ExprResult 34560b57cec5SDimitry Andric Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { 34570b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) 34580b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@"); 34590b57cec5SDimitry Andric 34600b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 34610b57cec5SDimitry Andric T.consumeOpen(); 34620b57cec5SDimitry Andric ExprResult ValueExpr(ParseAssignmentExpression()); 34630b57cec5SDimitry Andric if (T.consumeClose()) 34640b57cec5SDimitry Andric return ExprError(); 34650b57cec5SDimitry Andric 34660b57cec5SDimitry Andric if (ValueExpr.isInvalid()) 34670b57cec5SDimitry Andric return ExprError(); 34680b57cec5SDimitry Andric 34690b57cec5SDimitry Andric // Wrap the sub-expression in a parenthesized expression, to distinguish 34700b57cec5SDimitry Andric // a boxed expression from a literal. 34710b57cec5SDimitry Andric SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); 34720b57cec5SDimitry Andric ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get()); 3473*0fca6ea1SDimitry Andric return Actions.ObjC().BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), 34740b57cec5SDimitry Andric ValueExpr.get()); 34750b57cec5SDimitry Andric } 34760b57cec5SDimitry Andric 34770b57cec5SDimitry Andric ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { 34780b57cec5SDimitry Andric ExprVector ElementExprs; // array elements. 34790b57cec5SDimitry Andric ConsumeBracket(); // consume the l_square. 34800b57cec5SDimitry Andric 34810b57cec5SDimitry Andric bool HasInvalidEltExpr = false; 34820b57cec5SDimitry Andric while (Tok.isNot(tok::r_square)) { 34830b57cec5SDimitry Andric // Parse list of array element expressions (all must be id types). 34840b57cec5SDimitry Andric ExprResult Res(ParseAssignmentExpression()); 34850b57cec5SDimitry Andric if (Res.isInvalid()) { 34860b57cec5SDimitry Andric // We must manually skip to a ']', otherwise the expression skipper will 34870b57cec5SDimitry Andric // stop at the ']' when it skips to the ';'. We want it to skip beyond 34880b57cec5SDimitry Andric // the enclosing expression. 34890b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi); 34900b57cec5SDimitry Andric return Res; 34910b57cec5SDimitry Andric } 34920b57cec5SDimitry Andric 34930b57cec5SDimitry Andric Res = Actions.CorrectDelayedTyposInExpr(Res.get()); 34940b57cec5SDimitry Andric if (Res.isInvalid()) 34950b57cec5SDimitry Andric HasInvalidEltExpr = true; 34960b57cec5SDimitry Andric 34970b57cec5SDimitry Andric // Parse the ellipsis that indicates a pack expansion. 34980b57cec5SDimitry Andric if (Tok.is(tok::ellipsis)) 34990b57cec5SDimitry Andric Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken()); 35000b57cec5SDimitry Andric if (Res.isInvalid()) 35010b57cec5SDimitry Andric HasInvalidEltExpr = true; 35020b57cec5SDimitry Andric 35030b57cec5SDimitry Andric ElementExprs.push_back(Res.get()); 35040b57cec5SDimitry Andric 35050b57cec5SDimitry Andric if (Tok.is(tok::comma)) 35060b57cec5SDimitry Andric ConsumeToken(); // Eat the ','. 35070b57cec5SDimitry Andric else if (Tok.isNot(tok::r_square)) 35080b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square 35090b57cec5SDimitry Andric << tok::comma); 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric SourceLocation EndLoc = ConsumeBracket(); // location of ']' 35120b57cec5SDimitry Andric 35130b57cec5SDimitry Andric if (HasInvalidEltExpr) 35140b57cec5SDimitry Andric return ExprError(); 35150b57cec5SDimitry Andric 35160b57cec5SDimitry Andric MultiExprArg Args(ElementExprs); 3517*0fca6ea1SDimitry Andric return Actions.ObjC().BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); 35180b57cec5SDimitry Andric } 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { 35210b57cec5SDimitry Andric SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements. 35220b57cec5SDimitry Andric ConsumeBrace(); // consume the l_square. 35230b57cec5SDimitry Andric bool HasInvalidEltExpr = false; 35240b57cec5SDimitry Andric while (Tok.isNot(tok::r_brace)) { 35250b57cec5SDimitry Andric // Parse the comma separated key : value expressions. 35260b57cec5SDimitry Andric ExprResult KeyExpr; 35270b57cec5SDimitry Andric { 35280b57cec5SDimitry Andric ColonProtectionRAIIObject X(*this); 35290b57cec5SDimitry Andric KeyExpr = ParseAssignmentExpression(); 35300b57cec5SDimitry Andric if (KeyExpr.isInvalid()) { 35310b57cec5SDimitry Andric // We must manually skip to a '}', otherwise the expression skipper will 35320b57cec5SDimitry Andric // stop at the '}' when it skips to the ';'. We want it to skip beyond 35330b57cec5SDimitry Andric // the enclosing expression. 35340b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi); 35350b57cec5SDimitry Andric return KeyExpr; 35360b57cec5SDimitry Andric } 35370b57cec5SDimitry Andric } 35380b57cec5SDimitry Andric 35390b57cec5SDimitry Andric if (ExpectAndConsume(tok::colon)) { 35400b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi); 35410b57cec5SDimitry Andric return ExprError(); 35420b57cec5SDimitry Andric } 35430b57cec5SDimitry Andric 35440b57cec5SDimitry Andric ExprResult ValueExpr(ParseAssignmentExpression()); 35450b57cec5SDimitry Andric if (ValueExpr.isInvalid()) { 35460b57cec5SDimitry Andric // We must manually skip to a '}', otherwise the expression skipper will 35470b57cec5SDimitry Andric // stop at the '}' when it skips to the ';'. We want it to skip beyond 35480b57cec5SDimitry Andric // the enclosing expression. 35490b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi); 35500b57cec5SDimitry Andric return ValueExpr; 35510b57cec5SDimitry Andric } 35520b57cec5SDimitry Andric 35530b57cec5SDimitry Andric // Check the key and value for possible typos 35540b57cec5SDimitry Andric KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get()); 35550b57cec5SDimitry Andric ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get()); 35560b57cec5SDimitry Andric if (KeyExpr.isInvalid() || ValueExpr.isInvalid()) 35570b57cec5SDimitry Andric HasInvalidEltExpr = true; 35580b57cec5SDimitry Andric 35590b57cec5SDimitry Andric // Parse the ellipsis that designates this as a pack expansion. Do not 35600b57cec5SDimitry Andric // ActOnPackExpansion here, leave it to template instantiation time where 35610b57cec5SDimitry Andric // we can get better diagnostics. 35620b57cec5SDimitry Andric SourceLocation EllipsisLoc; 35630b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) 35640b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, EllipsisLoc); 35650b57cec5SDimitry Andric 35660b57cec5SDimitry Andric // We have a valid expression. Collect it in a vector so we can 35670b57cec5SDimitry Andric // build the argument list. 3568bdd1243dSDimitry Andric ObjCDictionaryElement Element = {KeyExpr.get(), ValueExpr.get(), 3569bdd1243dSDimitry Andric EllipsisLoc, std::nullopt}; 35700b57cec5SDimitry Andric Elements.push_back(Element); 35710b57cec5SDimitry Andric 35720b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) 35730b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace 35740b57cec5SDimitry Andric << tok::comma); 35750b57cec5SDimitry Andric } 35760b57cec5SDimitry Andric SourceLocation EndLoc = ConsumeBrace(); 35770b57cec5SDimitry Andric 35780b57cec5SDimitry Andric if (HasInvalidEltExpr) 35790b57cec5SDimitry Andric return ExprError(); 35800b57cec5SDimitry Andric 35810b57cec5SDimitry Andric // Create the ObjCDictionaryLiteral. 3582*0fca6ea1SDimitry Andric return Actions.ObjC().BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), 35830b57cec5SDimitry Andric Elements); 35840b57cec5SDimitry Andric } 35850b57cec5SDimitry Andric 35860b57cec5SDimitry Andric /// objc-encode-expression: 35870b57cec5SDimitry Andric /// \@encode ( type-name ) 35880b57cec5SDimitry Andric ExprResult 35890b57cec5SDimitry Andric Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { 35900b57cec5SDimitry Andric assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!"); 35910b57cec5SDimitry Andric 35920b57cec5SDimitry Andric SourceLocation EncLoc = ConsumeToken(); 35930b57cec5SDimitry Andric 35940b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) 35950b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode"); 35960b57cec5SDimitry Andric 35970b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 35980b57cec5SDimitry Andric T.consumeOpen(); 35990b57cec5SDimitry Andric 36000b57cec5SDimitry Andric TypeResult Ty = ParseTypeName(); 36010b57cec5SDimitry Andric 36020b57cec5SDimitry Andric T.consumeClose(); 36030b57cec5SDimitry Andric 36040b57cec5SDimitry Andric if (Ty.isInvalid()) 36050b57cec5SDimitry Andric return ExprError(); 36060b57cec5SDimitry Andric 3607*0fca6ea1SDimitry Andric return Actions.ObjC().ParseObjCEncodeExpression( 3608*0fca6ea1SDimitry Andric AtLoc, EncLoc, T.getOpenLocation(), Ty.get(), T.getCloseLocation()); 36090b57cec5SDimitry Andric } 36100b57cec5SDimitry Andric 36110b57cec5SDimitry Andric /// objc-protocol-expression 36120b57cec5SDimitry Andric /// \@protocol ( protocol-name ) 36130b57cec5SDimitry Andric ExprResult 36140b57cec5SDimitry Andric Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { 36150b57cec5SDimitry Andric SourceLocation ProtoLoc = ConsumeToken(); 36160b57cec5SDimitry Andric 36170b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) 36180b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol"); 36190b57cec5SDimitry Andric 36200b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 36210b57cec5SDimitry Andric T.consumeOpen(); 36220b57cec5SDimitry Andric 36230b57cec5SDimitry Andric if (expectIdentifier()) 36240b57cec5SDimitry Andric return ExprError(); 36250b57cec5SDimitry Andric 36260b57cec5SDimitry Andric IdentifierInfo *protocolId = Tok.getIdentifierInfo(); 36270b57cec5SDimitry Andric SourceLocation ProtoIdLoc = ConsumeToken(); 36280b57cec5SDimitry Andric 36290b57cec5SDimitry Andric T.consumeClose(); 36300b57cec5SDimitry Andric 3631*0fca6ea1SDimitry Andric return Actions.ObjC().ParseObjCProtocolExpression( 3632*0fca6ea1SDimitry Andric protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), ProtoIdLoc, 36330b57cec5SDimitry Andric T.getCloseLocation()); 36340b57cec5SDimitry Andric } 36350b57cec5SDimitry Andric 36360b57cec5SDimitry Andric /// objc-selector-expression 36370b57cec5SDimitry Andric /// @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')' 36380b57cec5SDimitry Andric ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { 36390b57cec5SDimitry Andric SourceLocation SelectorLoc = ConsumeToken(); 36400b57cec5SDimitry Andric 36410b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) 36420b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector"); 36430b57cec5SDimitry Andric 3644*0fca6ea1SDimitry Andric SmallVector<const IdentifierInfo *, 12> KeyIdents; 36450b57cec5SDimitry Andric SourceLocation sLoc; 36460b57cec5SDimitry Andric 36470b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 36480b57cec5SDimitry Andric T.consumeOpen(); 36490b57cec5SDimitry Andric bool HasOptionalParen = Tok.is(tok::l_paren); 36500b57cec5SDimitry Andric if (HasOptionalParen) 36510b57cec5SDimitry Andric ConsumeParen(); 36520b57cec5SDimitry Andric 36530b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 36540b57cec5SDimitry Andric cutOffParsing(); 3655*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), KeyIdents); 36560b57cec5SDimitry Andric return ExprError(); 36570b57cec5SDimitry Andric } 36580b57cec5SDimitry Andric 36590b57cec5SDimitry Andric IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc); 36600b57cec5SDimitry Andric if (!SelIdent && // missing selector name. 36610b57cec5SDimitry Andric Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) 36620b57cec5SDimitry Andric return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); 36630b57cec5SDimitry Andric 36640b57cec5SDimitry Andric KeyIdents.push_back(SelIdent); 36650b57cec5SDimitry Andric 36660b57cec5SDimitry Andric unsigned nColons = 0; 36670b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) { 366804eeddc0SDimitry Andric while (true) { 36690b57cec5SDimitry Andric if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++. 36700b57cec5SDimitry Andric ++nColons; 36710b57cec5SDimitry Andric KeyIdents.push_back(nullptr); 36720b57cec5SDimitry Andric } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'. 36730b57cec5SDimitry Andric return ExprError(); 36740b57cec5SDimitry Andric ++nColons; 36750b57cec5SDimitry Andric 36760b57cec5SDimitry Andric if (Tok.is(tok::r_paren)) 36770b57cec5SDimitry Andric break; 36780b57cec5SDimitry Andric 36790b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 36800b57cec5SDimitry Andric cutOffParsing(); 3681*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), 3682*0fca6ea1SDimitry Andric KeyIdents); 36830b57cec5SDimitry Andric return ExprError(); 36840b57cec5SDimitry Andric } 36850b57cec5SDimitry Andric 36860b57cec5SDimitry Andric // Check for another keyword selector. 36870b57cec5SDimitry Andric SourceLocation Loc; 36880b57cec5SDimitry Andric SelIdent = ParseObjCSelectorPiece(Loc); 36890b57cec5SDimitry Andric KeyIdents.push_back(SelIdent); 36900b57cec5SDimitry Andric if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) 36910b57cec5SDimitry Andric break; 36920b57cec5SDimitry Andric } 36930b57cec5SDimitry Andric } 36940b57cec5SDimitry Andric if (HasOptionalParen && Tok.is(tok::r_paren)) 36950b57cec5SDimitry Andric ConsumeParen(); // ')' 36960b57cec5SDimitry Andric T.consumeClose(); 36970b57cec5SDimitry Andric Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); 3698*0fca6ea1SDimitry Andric return Actions.ObjC().ParseObjCSelectorExpression( 3699*0fca6ea1SDimitry Andric Sel, AtLoc, SelectorLoc, T.getOpenLocation(), T.getCloseLocation(), 37000b57cec5SDimitry Andric !HasOptionalParen); 37010b57cec5SDimitry Andric } 37020b57cec5SDimitry Andric 37030b57cec5SDimitry Andric void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { 37040b57cec5SDimitry Andric // MCDecl might be null due to error in method or c-function prototype, etc. 37050b57cec5SDimitry Andric Decl *MCDecl = LM.D; 3706*0fca6ea1SDimitry Andric bool skip = 3707*0fca6ea1SDimitry Andric MCDecl && ((parseMethod && !Actions.ObjC().isObjCMethodDecl(MCDecl)) || 3708*0fca6ea1SDimitry Andric (!parseMethod && Actions.ObjC().isObjCMethodDecl(MCDecl))); 37090b57cec5SDimitry Andric if (skip) 37100b57cec5SDimitry Andric return; 37110b57cec5SDimitry Andric 37120b57cec5SDimitry Andric // Save the current token position. 37130b57cec5SDimitry Andric SourceLocation OrigLoc = Tok.getLocation(); 37140b57cec5SDimitry Andric 37150b57cec5SDimitry Andric assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); 37160b57cec5SDimitry Andric // Store an artificial EOF token to ensure that we don't run off the end of 37170b57cec5SDimitry Andric // the method's body when we come to parse it. 37180b57cec5SDimitry Andric Token Eof; 37190b57cec5SDimitry Andric Eof.startToken(); 37200b57cec5SDimitry Andric Eof.setKind(tok::eof); 37210b57cec5SDimitry Andric Eof.setEofData(MCDecl); 37220b57cec5SDimitry Andric Eof.setLocation(OrigLoc); 37230b57cec5SDimitry Andric LM.Toks.push_back(Eof); 37240b57cec5SDimitry Andric // Append the current token at the end of the new token stream so that it 37250b57cec5SDimitry Andric // doesn't get lost. 37260b57cec5SDimitry Andric LM.Toks.push_back(Tok); 37270b57cec5SDimitry Andric PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true); 37280b57cec5SDimitry Andric 37290b57cec5SDimitry Andric // Consume the previously pushed token. 37300b57cec5SDimitry Andric ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 37310b57cec5SDimitry Andric 37320b57cec5SDimitry Andric assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) && 37330b57cec5SDimitry Andric "Inline objective-c method not starting with '{' or 'try' or ':'"); 37340b57cec5SDimitry Andric // Enter a scope for the method or c-function body. 37350b57cec5SDimitry Andric ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) | 37360b57cec5SDimitry Andric Scope::FnScope | Scope::DeclScope | 37370b57cec5SDimitry Andric Scope::CompoundStmtScope); 3738*0fca6ea1SDimitry Andric Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); 37390b57cec5SDimitry Andric 37400b57cec5SDimitry Andric // Tell the actions module that we have entered a method or c-function definition 37410b57cec5SDimitry Andric // with the specified Declarator for the method/function. 37420b57cec5SDimitry Andric if (parseMethod) 3743*0fca6ea1SDimitry Andric Actions.ObjC().ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); 37440b57cec5SDimitry Andric else 37450b57cec5SDimitry Andric Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); 37460b57cec5SDimitry Andric if (Tok.is(tok::kw_try)) 37470b57cec5SDimitry Andric ParseFunctionTryBlock(MCDecl, BodyScope); 37480b57cec5SDimitry Andric else { 37490b57cec5SDimitry Andric if (Tok.is(tok::colon)) 37500b57cec5SDimitry Andric ParseConstructorInitializer(MCDecl); 37510b57cec5SDimitry Andric else 37520b57cec5SDimitry Andric Actions.ActOnDefaultCtorInitializers(MCDecl); 37530b57cec5SDimitry Andric ParseFunctionStatementBody(MCDecl, BodyScope); 37540b57cec5SDimitry Andric } 37550b57cec5SDimitry Andric 37560b57cec5SDimitry Andric if (Tok.getLocation() != OrigLoc) { 37570b57cec5SDimitry Andric // Due to parsing error, we either went over the cached tokens or 37580b57cec5SDimitry Andric // there are still cached tokens left. If it's the latter case skip the 37590b57cec5SDimitry Andric // leftover tokens. 37600b57cec5SDimitry Andric // Since this is an uncommon situation that should be avoided, use the 37610b57cec5SDimitry Andric // expensive isBeforeInTranslationUnit call. 37620b57cec5SDimitry Andric if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 37630b57cec5SDimitry Andric OrigLoc)) 37640b57cec5SDimitry Andric while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) 37650b57cec5SDimitry Andric ConsumeAnyToken(); 37660b57cec5SDimitry Andric } 37675f757f3fSDimitry Andric // Clean up the remaining EOF token, only if it's inserted by us. Otherwise 37685f757f3fSDimitry Andric // this might be code-completion token, which must be propagated to callers. 37695f757f3fSDimitry Andric if (Tok.is(tok::eof) && Tok.getEofData() == MCDecl) 37700b57cec5SDimitry Andric ConsumeAnyToken(); 37710b57cec5SDimitry Andric } 3772