3335 lines · cpp
1//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Objective-C portions of the Parser interface.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/ExprObjC.h"15#include "clang/AST/ODRDiagsEmitter.h"16#include "clang/AST/PrettyDeclStackTrace.h"17#include "clang/Basic/CharInfo.h"18#include "clang/Basic/DiagnosticParse.h"19#include "clang/Basic/TargetInfo.h"20#include "clang/Parse/Parser.h"21#include "clang/Parse/RAIIObjectsForParser.h"22#include "clang/Sema/DeclSpec.h"23#include "clang/Sema/Scope.h"24#include "clang/Sema/SemaCodeCompletion.h"25#include "clang/Sema/SemaObjC.h"26#include "llvm/ADT/STLForwardCompat.h"27#include "llvm/ADT/SmallVector.h"28 29using namespace clang;30 31void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {32 ParsedAttributes attrs(AttrFactory);33 if (Tok.is(tok::kw___attribute)) {34 if (Kind == tok::objc_interface || Kind == tok::objc_protocol)35 Diag(Tok, diag::err_objc_postfix_attribute_hint)36 << (Kind == tok::objc_protocol);37 else38 Diag(Tok, diag::err_objc_postfix_attribute);39 ParseGNUAttributes(attrs);40 }41}42 43Parser::DeclGroupPtrTy44Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs,45 ParsedAttributes &DeclSpecAttrs) {46 DeclAttrs.takeAllPrependingFrom(DeclSpecAttrs);47 48 SourceLocation AtLoc = ConsumeToken(); // the "@"49 50 if (Tok.is(tok::code_completion)) {51 cutOffParsing();52 Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope());53 return nullptr;54 }55 56 switch (Tok.getObjCKeywordID()) {57 case tok::objc_interface:58 case tok::objc_protocol:59 case tok::objc_implementation:60 break;61 default:62 for (const auto &Attr : DeclAttrs) {63 if (Attr.isGNUAttribute())64 Diag(Tok.getLocation(), diag::err_objc_unexpected_attr);65 }66 }67 68 Decl *SingleDecl = nullptr;69 switch (Tok.getObjCKeywordID()) {70 case tok::objc_class:71 return ParseObjCAtClassDeclaration(AtLoc);72 case tok::objc_interface:73 SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DeclAttrs);74 break;75 case tok::objc_protocol:76 return ParseObjCAtProtocolDeclaration(AtLoc, DeclAttrs);77 case tok::objc_implementation:78 return ParseObjCAtImplementationDeclaration(AtLoc, DeclAttrs);79 case tok::objc_end:80 return ParseObjCAtEndDeclaration(AtLoc);81 case tok::objc_compatibility_alias:82 SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);83 break;84 case tok::objc_synthesize:85 SingleDecl = ParseObjCPropertySynthesize(AtLoc);86 break;87 case tok::objc_dynamic:88 SingleDecl = ParseObjCPropertyDynamic(AtLoc);89 break;90 case tok::objc_import:91 if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {92 Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module;93 SingleDecl = ParseModuleImport(AtLoc, IS);94 break;95 }96 Diag(AtLoc, diag::err_atimport);97 SkipUntil(tok::semi);98 return Actions.ConvertDeclToDeclGroup(nullptr);99 default:100 Diag(AtLoc, diag::err_unexpected_at);101 SkipUntil(tok::semi);102 SingleDecl = nullptr;103 break;104 }105 return Actions.ConvertDeclToDeclGroup(SingleDecl);106}107 108class Parser::ObjCTypeParamListScope {109 Sema &Actions;110 Scope *S;111 ObjCTypeParamList *Params;112 113public:114 ObjCTypeParamListScope(Sema &Actions, Scope *S)115 : Actions(Actions), S(S), Params(nullptr) {}116 117 ~ObjCTypeParamListScope() {118 leave();119 }120 121 void enter(ObjCTypeParamList *P) {122 assert(!Params);123 Params = P;124 }125 126 void leave() {127 if (Params)128 Actions.ObjC().popObjCTypeParamList(S, Params);129 Params = nullptr;130 }131};132 133Parser::DeclGroupPtrTy134Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {135 ConsumeToken(); // the identifier "class"136 SmallVector<IdentifierInfo *, 8> ClassNames;137 SmallVector<SourceLocation, 8> ClassLocs;138 SmallVector<ObjCTypeParamList *, 8> ClassTypeParams;139 140 while (true) {141 MaybeSkipAttributes(tok::objc_class);142 if (Tok.is(tok::code_completion)) {143 cutOffParsing();144 Actions.CodeCompletion().CodeCompleteObjCClassForwardDecl(getCurScope());145 return Actions.ConvertDeclToDeclGroup(nullptr);146 }147 if (expectIdentifier()) {148 SkipUntil(tok::semi);149 return Actions.ConvertDeclToDeclGroup(nullptr);150 }151 ClassNames.push_back(Tok.getIdentifierInfo());152 ClassLocs.push_back(Tok.getLocation());153 ConsumeToken();154 155 // Parse the optional objc-type-parameter-list.156 ObjCTypeParamList *TypeParams = nullptr;157 if (Tok.is(tok::less))158 TypeParams = parseObjCTypeParamList();159 ClassTypeParams.push_back(TypeParams);160 if (!TryConsumeToken(tok::comma))161 break;162 }163 164 // Consume the ';'.165 if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))166 return Actions.ConvertDeclToDeclGroup(nullptr);167 168 return Actions.ObjC().ActOnForwardClassDeclaration(169 atLoc, ClassNames.data(), ClassLocs.data(), ClassTypeParams,170 ClassNames.size());171}172 173void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)174{175 SemaObjC::ObjCContainerKind ock = Actions.ObjC().getObjCContainerKind();176 if (ock == SemaObjC::OCK_None)177 return;178 179 Decl *Decl = Actions.ObjC().getObjCDeclContext();180 if (CurParsedObjCImpl) {181 CurParsedObjCImpl->finish(AtLoc);182 } else {183 Actions.ObjC().ActOnAtEnd(getCurScope(), AtLoc);184 }185 Diag(AtLoc, diag::err_objc_missing_end)186 << FixItHint::CreateInsertion(AtLoc, "@end\n");187 if (Decl)188 Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock;189}190 191Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,192 ParsedAttributes &attrs) {193 assert(Tok.isObjCAtKeyword(tok::objc_interface) &&194 "ParseObjCAtInterfaceDeclaration(): Expected @interface");195 CheckNestedObjCContexts(AtLoc);196 ConsumeToken(); // the "interface" identifier197 198 // Code completion after '@interface'.199 if (Tok.is(tok::code_completion)) {200 cutOffParsing();201 Actions.CodeCompletion().CodeCompleteObjCInterfaceDecl(getCurScope());202 return nullptr;203 }204 205 MaybeSkipAttributes(tok::objc_interface);206 207 if (expectIdentifier())208 return nullptr; // missing class or category name.209 210 // We have a class or category name - consume it.211 IdentifierInfo *nameId = Tok.getIdentifierInfo();212 SourceLocation nameLoc = ConsumeToken();213 214 // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter215 // case, LAngleLoc will be valid and ProtocolIdents will capture the216 // protocol references (that have not yet been resolved).217 SourceLocation LAngleLoc, EndProtoLoc;218 SmallVector<IdentifierLoc, 8> ProtocolIdents;219 ObjCTypeParamList *typeParameterList = nullptr;220 ObjCTypeParamListScope typeParamScope(Actions, getCurScope());221 if (Tok.is(tok::less))222 typeParameterList = parseObjCTypeParamListOrProtocolRefs(223 typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc);224 225 if (Tok.is(tok::l_paren) &&226 !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.227 228 BalancedDelimiterTracker T(*this, tok::l_paren);229 T.consumeOpen();230 231 SourceLocation categoryLoc;232 IdentifierInfo *categoryId = nullptr;233 if (Tok.is(tok::code_completion)) {234 cutOffParsing();235 Actions.CodeCompletion().CodeCompleteObjCInterfaceCategory(236 getCurScope(), nameId, nameLoc);237 return nullptr;238 }239 240 // For ObjC2, the category name is optional (not an error).241 if (Tok.is(tok::identifier)) {242 categoryId = Tok.getIdentifierInfo();243 categoryLoc = ConsumeToken();244 }245 else if (!getLangOpts().ObjC) {246 Diag(Tok, diag::err_expected)247 << tok::identifier; // missing category name.248 return nullptr;249 }250 251 T.consumeClose();252 if (T.getCloseLocation().isInvalid())253 return nullptr;254 255 // Next, we need to check for any protocol references.256 assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");257 SmallVector<Decl *, 8> ProtocolRefs;258 SmallVector<SourceLocation, 8> ProtocolLocs;259 if (Tok.is(tok::less) &&260 ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,261 LAngleLoc, EndProtoLoc,262 /*consumeLastToken=*/true))263 return nullptr;264 265 ObjCCategoryDecl *CategoryType = Actions.ObjC().ActOnStartCategoryInterface(266 AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,267 ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),268 EndProtoLoc, attrs);269 270 if (Tok.is(tok::l_brace))271 ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);272 273 ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);274 275 return CategoryType;276 }277 // Parse a class interface.278 IdentifierInfo *superClassId = nullptr;279 SourceLocation superClassLoc;280 SourceLocation typeArgsLAngleLoc;281 SmallVector<ParsedType, 4> typeArgs;282 SourceLocation typeArgsRAngleLoc;283 SmallVector<Decl *, 4> protocols;284 SmallVector<SourceLocation, 4> protocolLocs;285 if (Tok.is(tok::colon)) { // a super class is specified.286 ConsumeToken();287 288 // Code completion of superclass names.289 if (Tok.is(tok::code_completion)) {290 cutOffParsing();291 Actions.CodeCompletion().CodeCompleteObjCSuperclass(getCurScope(), nameId,292 nameLoc);293 return nullptr;294 }295 296 if (expectIdentifier())297 return nullptr; // missing super class name.298 superClassId = Tok.getIdentifierInfo();299 superClassLoc = ConsumeToken();300 301 // Type arguments for the superclass or protocol conformances.302 if (Tok.is(tok::less)) {303 parseObjCTypeArgsOrProtocolQualifiers(304 nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc,305 protocols, protocolLocs, EndProtoLoc,306 /*consumeLastToken=*/true,307 /*warnOnIncompleteProtocols=*/true);308 if (Tok.is(tok::eof))309 return nullptr;310 }311 }312 313 // Next, we need to check for any protocol references.314 if (LAngleLoc.isValid()) {315 if (!ProtocolIdents.empty()) {316 // We already parsed the protocols named when we thought we had a317 // type parameter list. Translate them into actual protocol references.318 for (const auto &Loc : ProtocolIdents) {319 protocolLocs.push_back(Loc.getLoc());320 }321 Actions.ObjC().FindProtocolDeclaration(/*WarnOnDeclarations=*/true,322 /*ForObjCContainer=*/true,323 ProtocolIdents, protocols);324 }325 } else if (protocols.empty() && Tok.is(tok::less) &&326 ParseObjCProtocolReferences(protocols, protocolLocs, true, true,327 LAngleLoc, EndProtoLoc,328 /*consumeLastToken=*/true)) {329 return nullptr;330 }331 332 if (Tok.isNot(tok::less))333 Actions.ObjC().ActOnTypedefedProtocols(protocols, protocolLocs,334 superClassId, superClassLoc);335 336 SkipBodyInfo SkipBody;337 ObjCInterfaceDecl *ClsType = Actions.ObjC().ActOnStartClassInterface(338 getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,339 superClassLoc, typeArgs,340 SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),341 protocols.size(), protocolLocs.data(), EndProtoLoc, attrs, &SkipBody);342 343 if (Tok.is(tok::l_brace))344 ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);345 346 ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);347 348 if (SkipBody.CheckSameAsPrevious) {349 auto *PreviousDef = cast<ObjCInterfaceDecl>(SkipBody.Previous);350 if (Actions.ActOnDuplicateODRHashDefinition(ClsType, PreviousDef)) {351 ClsType->mergeDuplicateDefinitionWithCommon(PreviousDef->getDefinition());352 } else {353 ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),354 getPreprocessor().getLangOpts());355 DiagsEmitter.diagnoseMismatch(PreviousDef, ClsType);356 ClsType->setInvalidDecl();357 }358 }359 360 return ClsType;361}362 363/// Add an attribute for a context-sensitive type nullability to the given364/// declarator.365static void addContextSensitiveTypeNullability(Parser &P,366 Declarator &D,367 NullabilityKind nullability,368 SourceLocation nullabilityLoc,369 bool &addedToDeclSpec) {370 // Create the attribute.371 auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * {372 return Pool.create(P.getNullabilityKeyword(nullability),373 SourceRange(nullabilityLoc), AttributeScopeInfo(),374 nullptr, 0, ParsedAttr::Form::ContextSensitiveKeyword());375 };376 377 if (D.getNumTypeObjects() > 0) {378 // Add the attribute to the declarator chunk nearest the declarator.379 D.getTypeObject(0).getAttrs().addAtEnd(380 getNullabilityAttr(D.getAttributePool()));381 } else if (!addedToDeclSpec) {382 // Otherwise, just put it on the declaration specifiers (if one383 // isn't there already).384 D.getMutableDeclSpec().getAttributes().addAtEnd(385 getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));386 addedToDeclSpec = true;387 }388}389 390ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(391 ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,392 SmallVectorImpl<IdentifierLoc> &protocolIdents, SourceLocation &rAngleLoc,393 bool mayBeProtocolList) {394 assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");395 396 // Within the type parameter list, don't treat '>' as an operator.397 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);398 399 // Local function to "flush" the protocol identifiers, turning them into400 // type parameters.401 SmallVector<Decl *, 4> typeParams;402 auto makeProtocolIdentsIntoTypeParameters = [&]() {403 unsigned index = 0;404 for (const auto &pair : protocolIdents) {405 DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam(406 getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(),407 index++, pair.getIdentifierInfo(), pair.getLoc(), SourceLocation(),408 nullptr);409 if (typeParam.isUsable())410 typeParams.push_back(typeParam.get());411 }412 413 protocolIdents.clear();414 mayBeProtocolList = false;415 };416 417 bool invalid = false;418 lAngleLoc = ConsumeToken();419 420 do {421 // Parse the variance, if any.422 SourceLocation varianceLoc;423 ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant;424 if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) {425 variance = Tok.is(tok::kw___covariant)426 ? ObjCTypeParamVariance::Covariant427 : ObjCTypeParamVariance::Contravariant;428 varianceLoc = ConsumeToken();429 430 // Once we've seen a variance specific , we know this is not a431 // list of protocol references.432 if (mayBeProtocolList) {433 // Up until now, we have been queuing up parameters because they434 // might be protocol references. Turn them into parameters now.435 makeProtocolIdentsIntoTypeParameters();436 }437 }438 439 // Parse the identifier.440 if (!Tok.is(tok::identifier)) {441 // Code completion.442 if (Tok.is(tok::code_completion)) {443 // FIXME: If these aren't protocol references, we'll need different444 // completions.445 cutOffParsing();446 Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(447 protocolIdents);448 449 // FIXME: Better recovery here?.450 return nullptr;451 }452 453 Diag(Tok, diag::err_objc_expected_type_parameter);454 invalid = true;455 break;456 }457 458 IdentifierInfo *paramName = Tok.getIdentifierInfo();459 SourceLocation paramLoc = ConsumeToken();460 461 // If there is a bound, parse it.462 SourceLocation colonLoc;463 TypeResult boundType;464 if (TryConsumeToken(tok::colon, colonLoc)) {465 // Once we've seen a bound, we know this is not a list of protocol466 // references.467 if (mayBeProtocolList) {468 // Up until now, we have been queuing up parameters because they469 // might be protocol references. Turn them into parameters now.470 makeProtocolIdentsIntoTypeParameters();471 }472 473 // type-name474 boundType = ParseTypeName();475 if (boundType.isInvalid())476 invalid = true;477 } else if (mayBeProtocolList) {478 // If this could still be a protocol list, just capture the identifier.479 // We don't want to turn it into a parameter.480 protocolIdents.emplace_back(paramLoc, paramName);481 continue;482 }483 484 // Create the type parameter.485 DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam(486 getCurScope(), variance, varianceLoc, typeParams.size(), paramName,487 paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr);488 if (typeParam.isUsable())489 typeParams.push_back(typeParam.get());490 } while (TryConsumeToken(tok::comma));491 492 // Parse the '>'.493 if (invalid) {494 SkipUntil(tok::greater, tok::at, StopBeforeMatch);495 if (Tok.is(tok::greater))496 ConsumeToken();497 } else if (ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc,498 /*ConsumeLastToken=*/true,499 /*ObjCGenericList=*/true)) {500 SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus,501 tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace,502 tok::comma, tok::semi },503 StopBeforeMatch);504 if (Tok.is(tok::greater))505 ConsumeToken();506 }507 508 if (mayBeProtocolList) {509 // A type parameter list must be followed by either a ':' (indicating the510 // presence of a superclass) or a '(' (indicating that this is a category511 // or extension). This disambiguates between an objc-type-parameter-list512 // and a objc-protocol-refs.513 if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) {514 // Returning null indicates that we don't have a type parameter list.515 // The results the caller needs to handle the protocol references are516 // captured in the reference parameters already.517 return nullptr;518 }519 520 // We have a type parameter list that looks like a list of protocol521 // references. Turn that parameter list into type parameters.522 makeProtocolIdentsIntoTypeParameters();523 }524 525 // Form the type parameter list and enter its scope.526 ObjCTypeParamList *list = Actions.ObjC().actOnObjCTypeParamList(527 getCurScope(), lAngleLoc, typeParams, rAngleLoc);528 Scope.enter(list);529 530 // Clear out the angle locations; they're used by the caller to indicate531 // whether there are any protocol references.532 lAngleLoc = SourceLocation();533 rAngleLoc = SourceLocation();534 return invalid ? nullptr : list;535}536 537ObjCTypeParamList *Parser::parseObjCTypeParamList() {538 SourceLocation lAngleLoc;539 SmallVector<IdentifierLoc, 1> protocolIdents;540 SourceLocation rAngleLoc;541 542 ObjCTypeParamListScope Scope(Actions, getCurScope());543 return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents,544 rAngleLoc,545 /*mayBeProtocolList=*/false);546}547 548static bool isTopLevelObjCKeyword(tok::ObjCKeywordKind DirectiveKind) {549 switch (DirectiveKind) {550 case tok::objc_class:551 case tok::objc_compatibility_alias:552 case tok::objc_interface:553 case tok::objc_implementation:554 case tok::objc_protocol:555 return true;556 default:557 return false;558 }559}560 561void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,562 Decl *CDecl) {563 SmallVector<Decl *, 32> allMethods;564 SmallVector<DeclGroupPtrTy, 8> allTUVariables;565 tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;566 567 SourceRange AtEnd;568 569 while (true) {570 // If this is a method prototype, parse it.571 if (Tok.isOneOf(tok::minus, tok::plus)) {572 if (Decl *methodPrototype =573 ParseObjCMethodPrototype(MethodImplKind, false))574 allMethods.push_back(methodPrototype);575 // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for576 // method definitions.577 if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {578 // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.579 SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);580 if (Tok.is(tok::semi))581 ConsumeToken();582 }583 continue;584 }585 if (Tok.is(tok::l_paren)) {586 Diag(Tok, diag::err_expected_minus_or_plus);587 ParseObjCMethodDecl(Tok.getLocation(),588 tok::minus,589 MethodImplKind, false);590 continue;591 }592 // Ignore excess semicolons.593 if (Tok.is(tok::semi)) {594 // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons,595 // to make -Wextra-semi diagnose them.596 ConsumeToken();597 continue;598 }599 600 // If we got to the end of the file, exit the loop.601 if (isEofOrEom())602 break;603 604 // Code completion within an Objective-C interface.605 if (Tok.is(tok::code_completion)) {606 cutOffParsing();607 Actions.CodeCompletion().CodeCompleteOrdinaryName(608 getCurScope(), CurParsedObjCImpl609 ? SemaCodeCompletion::PCC_ObjCImplementation610 : SemaCodeCompletion::PCC_ObjCInterface);611 return;612 }613 614 // If we don't have an @ directive, parse it as a function definition.615 if (Tok.isNot(tok::at)) {616 // The code below does not consume '}'s because it is afraid of eating the617 // end of a namespace. Because of the way this code is structured, an618 // erroneous r_brace would cause an infinite loop if not handled here.619 if (Tok.is(tok::r_brace))620 break;621 622 ParsedAttributes EmptyDeclAttrs(AttrFactory);623 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);624 625 // Since we call ParseDeclarationOrFunctionDefinition() instead of626 // ParseExternalDeclaration() below (so that this doesn't parse nested627 // @interfaces), this needs to duplicate some code from the latter.628 if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {629 SourceLocation DeclEnd;630 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);631 allTUVariables.push_back(ParseDeclaration(DeclaratorContext::File,632 DeclEnd, EmptyDeclAttrs,633 EmptyDeclSpecAttrs));634 continue;635 }636 637 allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(638 EmptyDeclAttrs, EmptyDeclSpecAttrs));639 continue;640 }641 642 // Otherwise, we have an @ directive, peak at the next token643 SourceLocation AtLoc = Tok.getLocation();644 const auto &NextTok = NextToken();645 if (NextTok.is(tok::code_completion)) {646 cutOffParsing();647 Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope());648 return;649 }650 651 tok::ObjCKeywordKind DirectiveKind = NextTok.getObjCKeywordID();652 if (DirectiveKind == tok::objc_end) { // @end -> terminate list653 ConsumeToken(); // the "@"654 AtEnd.setBegin(AtLoc);655 AtEnd.setEnd(Tok.getLocation());656 break;657 } else if (DirectiveKind == tok::objc_not_keyword) {658 Diag(NextTok, diag::err_objc_unknown_at);659 SkipUntil(tok::semi);660 continue;661 }662 663 // If we see something like '@interface' that's only allowed at the top664 // level, bail out as if we saw an '@end'. We'll diagnose this below.665 if (isTopLevelObjCKeyword(DirectiveKind))666 break;667 668 // Otherwise parse it as part of the current declaration. Eat "@identifier".669 ConsumeToken();670 ConsumeToken();671 672 switch (DirectiveKind) {673 default:674 // FIXME: If someone forgets an @end on a protocol, this loop will675 // continue to eat up tons of stuff and spew lots of nonsense errors. It676 // would probably be better to bail out if we saw an @class or @interface677 // or something like that.678 Diag(AtLoc, diag::err_objc_illegal_interface_qual);679 // Skip until we see an '@' or '}' or ';'.680 SkipUntil(tok::r_brace, tok::at, StopAtSemi);681 break;682 683 case tok::objc_required:684 case tok::objc_optional:685 // This is only valid on protocols.686 if (contextKey != tok::objc_protocol)687 Diag(AtLoc, diag::err_objc_directive_only_in_protocol);688 else689 MethodImplKind = DirectiveKind;690 break;691 692 case tok::objc_property:693 ObjCDeclSpec OCDS;694 SourceLocation LParenLoc;695 // Parse property attribute list, if any.696 if (Tok.is(tok::l_paren)) {697 LParenLoc = Tok.getLocation();698 ParseObjCPropertyAttribute(OCDS);699 }700 701 bool addedToDeclSpec = false;702 auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {703 if (FD.D.getIdentifier() == nullptr) {704 Diag(AtLoc, diag::err_objc_property_requires_field_name)705 << FD.D.getSourceRange();706 return nullptr;707 }708 if (FD.BitfieldSize) {709 Diag(AtLoc, diag::err_objc_property_bitfield)710 << FD.D.getSourceRange();711 return nullptr;712 }713 714 // Map a nullability property attribute to a context-sensitive keyword715 // attribute.716 if (OCDS.getPropertyAttributes() &717 ObjCPropertyAttribute::kind_nullability)718 addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),719 OCDS.getNullabilityLoc(),720 addedToDeclSpec);721 722 // Install the property declarator into interfaceDecl.723 const IdentifierInfo *SelName =724 OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();725 726 Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName);727 const IdentifierInfo *SetterName = OCDS.getSetterName();728 Selector SetterSel;729 if (SetterName)730 SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);731 else732 SetterSel = SelectorTable::constructSetterSelector(733 PP.getIdentifierTable(), PP.getSelectorTable(),734 FD.D.getIdentifier());735 Decl *Property = Actions.ObjC().ActOnProperty(736 getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,737 MethodImplKind);738 739 FD.complete(Property);740 return Property;741 };742 743 // Parse all the comma separated declarators.744 ParsingDeclSpec DS(*this);745 ParseStructDeclaration(DS, ObjCPropertyCallback);746 747 ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);748 break;749 }750 }751 752 // We break out of the big loop in 3 cases: when we see @end or when we see753 // top-level ObjC keyword or EOF. In the former case, eat the @end. In the754 // later cases, emit an error.755 if (Tok.isObjCAtKeyword(tok::objc_end)) {756 ConsumeToken(); // the "end" identifier757 } else {758 Diag(Tok, diag::err_objc_missing_end)759 << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");760 Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)761 << (int)Actions.ObjC().getObjCContainerKind();762 AtEnd.setBegin(Tok.getLocation());763 AtEnd.setEnd(Tok.getLocation());764 }765 766 // Insert collected methods declarations into the @interface object.767 // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.768 Actions.ObjC().ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);769}770 771/// Diagnose redundant or conflicting nullability information.772static void diagnoseRedundantPropertyNullability(Parser &P,773 ObjCDeclSpec &DS,774 NullabilityKind nullability,775 SourceLocation nullabilityLoc){776 if (DS.getNullability() == nullability) {777 P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)778 << DiagNullabilityKind(nullability, true)779 << SourceRange(DS.getNullabilityLoc());780 return;781 }782 783 P.Diag(nullabilityLoc, diag::err_nullability_conflicting)784 << DiagNullabilityKind(nullability, true)785 << DiagNullabilityKind(DS.getNullability(), true)786 << SourceRange(DS.getNullabilityLoc());787}788 789void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {790 assert(Tok.getKind() == tok::l_paren);791 BalancedDelimiterTracker T(*this, tok::l_paren);792 T.consumeOpen();793 794 while (true) {795 if (Tok.is(tok::code_completion)) {796 cutOffParsing();797 Actions.CodeCompletion().CodeCompleteObjCPropertyFlags(getCurScope(), DS);798 return;799 }800 const IdentifierInfo *II = Tok.getIdentifierInfo();801 802 // If this is not an identifier at all, bail out early.803 if (!II) {804 T.consumeClose();805 return;806 }807 808 SourceLocation AttrName = ConsumeToken(); // consume last attribute name809 810 if (II->isStr("readonly"))811 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);812 else if (II->isStr("assign"))813 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_assign);814 else if (II->isStr("unsafe_unretained"))815 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);816 else if (II->isStr("readwrite"))817 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite);818 else if (II->isStr("retain"))819 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_retain);820 else if (II->isStr("strong"))821 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_strong);822 else if (II->isStr("copy"))823 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_copy);824 else if (II->isStr("nonatomic"))825 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic);826 else if (II->isStr("atomic"))827 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_atomic);828 else if (II->isStr("weak"))829 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_weak);830 else if (II->isStr("getter") || II->isStr("setter")) {831 bool IsSetter = II->getNameStart()[0] == 's';832 833 // getter/setter require extra treatment.834 unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :835 diag::err_objc_expected_equal_for_getter;836 837 if (ExpectAndConsume(tok::equal, DiagID)) {838 SkipUntil(tok::r_paren, StopAtSemi);839 return;840 }841 842 if (Tok.is(tok::code_completion)) {843 cutOffParsing();844 if (IsSetter)845 Actions.CodeCompletion().CodeCompleteObjCPropertySetter(846 getCurScope());847 else848 Actions.CodeCompletion().CodeCompleteObjCPropertyGetter(849 getCurScope());850 return;851 }852 853 SourceLocation SelLoc;854 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);855 856 if (!SelIdent) {857 Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)858 << IsSetter;859 SkipUntil(tok::r_paren, StopAtSemi);860 return;861 }862 863 if (IsSetter) {864 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_setter);865 DS.setSetterName(SelIdent, SelLoc);866 867 if (ExpectAndConsume(tok::colon,868 diag::err_expected_colon_after_setter_name)) {869 SkipUntil(tok::r_paren, StopAtSemi);870 return;871 }872 } else {873 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_getter);874 DS.setGetterName(SelIdent, SelLoc);875 }876 } else if (II->isStr("nonnull")) {877 if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)878 diagnoseRedundantPropertyNullability(*this, DS,879 NullabilityKind::NonNull,880 Tok.getLocation());881 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);882 DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);883 } else if (II->isStr("nullable")) {884 if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)885 diagnoseRedundantPropertyNullability(*this, DS,886 NullabilityKind::Nullable,887 Tok.getLocation());888 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);889 DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);890 } else if (II->isStr("null_unspecified")) {891 if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)892 diagnoseRedundantPropertyNullability(*this, DS,893 NullabilityKind::Unspecified,894 Tok.getLocation());895 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);896 DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);897 } else if (II->isStr("null_resettable")) {898 if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)899 diagnoseRedundantPropertyNullability(*this, DS,900 NullabilityKind::Unspecified,901 Tok.getLocation());902 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);903 DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);904 905 // Also set the null_resettable bit.906 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable);907 } else if (II->isStr("class")) {908 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_class);909 } else if (II->isStr("direct")) {910 DS.setPropertyAttributes(ObjCPropertyAttribute::kind_direct);911 } else {912 Diag(AttrName, diag::err_objc_expected_property_attr) << II;913 SkipUntil(tok::r_paren, StopAtSemi);914 return;915 }916 917 if (Tok.isNot(tok::comma))918 break;919 920 ConsumeToken();921 }922 923 T.consumeClose();924}925 926Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,927 bool MethodDefinition) {928 assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");929 930 tok::TokenKind methodType = Tok.getKind();931 SourceLocation mLoc = ConsumeToken();932 Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,933 MethodDefinition);934 // Since this rule is used for both method declarations and definitions,935 // the caller is (optionally) responsible for consuming the ';'.936 return MDecl;937}938 939IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {940 941 switch (Tok.getKind()) {942 case tok::colon:943 // Empty selector piece uses the location of the ':'.944 SelectorLoc = Tok.getLocation();945 return nullptr;946 case tok::ampamp:947 case tok::ampequal:948 case tok::amp:949 case tok::pipe:950 case tok::tilde:951 case tok::exclaim:952 case tok::exclaimequal:953 case tok::pipepipe:954 case tok::pipeequal:955 case tok::caret:956 case tok::caretequal: {957 std::string ThisTok(PP.getSpelling(Tok));958 if (isLetter(ThisTok[0])) {959 IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok);960 Tok.setKind(tok::identifier);961 SelectorLoc = ConsumeToken();962 return II;963 }964 return nullptr;965 }966 967 case tok::kw___attribute:968 return nullptr;969 970 default:971 IdentifierInfo *II = Tok.getIdentifierInfo();972 if (!II)973 return nullptr;974 SelectorLoc = ConsumeToken();975 return II;976 }977}978 979bool Parser::isTokIdentifier_in() const {980 // FIXME: May have to do additional look-ahead to only allow for981 // valid tokens following an 'in'; such as an identifier, unary operators,982 // '[' etc.983 return (getLangOpts().ObjC && Tok.is(tok::identifier) &&984 Tok.getIdentifierInfo() ==985 ObjCTypeQuals[llvm::to_underlying(ObjCTypeQual::in)]);986}987 988void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,989 DeclaratorContext Context) {990 assert(Context == DeclaratorContext::ObjCParameter ||991 Context == DeclaratorContext::ObjCResult);992 993 while (true) {994 if (Tok.is(tok::code_completion)) {995 cutOffParsing();996 Actions.CodeCompletion().CodeCompleteObjCPassingType(997 getCurScope(), DS, Context == DeclaratorContext::ObjCParameter);998 return;999 }1000 1001 if (Tok.isNot(tok::identifier))1002 return;1003 1004 const IdentifierInfo *II = Tok.getIdentifierInfo();1005 for (unsigned i = 0; i != llvm::to_underlying(ObjCTypeQual::NumQuals);1006 ++i) {1007 ObjCTypeQual TQ = static_cast<ObjCTypeQual>(i);1008 if (II != ObjCTypeQuals[llvm::to_underlying(TQ)] ||1009 NextToken().is(tok::less) || NextToken().is(tok::coloncolon))1010 continue;1011 1012 ObjCDeclSpec::ObjCDeclQualifier Qual;1013 NullabilityKind Nullability;1014 switch (TQ) {1015 default: llvm_unreachable("Unknown decl qualifier");1016 case ObjCTypeQual::in:1017 Qual = ObjCDeclSpec::DQ_In;1018 break;1019 case ObjCTypeQual::out:1020 Qual = ObjCDeclSpec::DQ_Out;1021 break;1022 case ObjCTypeQual::inout:1023 Qual = ObjCDeclSpec::DQ_Inout;1024 break;1025 case ObjCTypeQual::oneway:1026 Qual = ObjCDeclSpec::DQ_Oneway;1027 break;1028 case ObjCTypeQual::bycopy:1029 Qual = ObjCDeclSpec::DQ_Bycopy;1030 break;1031 case ObjCTypeQual::byref:1032 Qual = ObjCDeclSpec::DQ_Byref;1033 break;1034 1035 case ObjCTypeQual::nonnull:1036 Qual = ObjCDeclSpec::DQ_CSNullability;1037 Nullability = NullabilityKind::NonNull;1038 break;1039 1040 case ObjCTypeQual::nullable:1041 Qual = ObjCDeclSpec::DQ_CSNullability;1042 Nullability = NullabilityKind::Nullable;1043 break;1044 1045 case ObjCTypeQual::null_unspecified:1046 Qual = ObjCDeclSpec::DQ_CSNullability;1047 Nullability = NullabilityKind::Unspecified;1048 break;1049 }1050 1051 // FIXME: Diagnose redundant specifiers.1052 DS.setObjCDeclQualifier(Qual);1053 if (Qual == ObjCDeclSpec::DQ_CSNullability)1054 DS.setNullability(Tok.getLocation(), Nullability);1055 1056 ConsumeToken();1057 II = nullptr;1058 break;1059 }1060 1061 // If this wasn't a recognized qualifier, bail out.1062 if (II) return;1063 }1064}1065 1066/// Take all the decl attributes out of the given list and add1067/// them to the given attribute set.1068static void takeDeclAttributesAppend(ParsedAttributesView &attrs,1069 ParsedAttributesView &from) {1070 for (auto &AL : llvm::reverse(from)) {1071 if (!AL.isUsedAsTypeAttr()) {1072 from.remove(&AL);1073 attrs.addAtEnd(&AL);1074 }1075 }1076}1077 1078/// takeDeclAttributes - Take all the decl attributes from the given1079/// declarator and add them to the given list.1080static void takeDeclAttributes(ParsedAttributes &attrs,1081 Declarator &D) {1082 // This gets called only from Parser::ParseObjCTypeName(), and that should1083 // never add declaration attributes to the Declarator.1084 assert(D.getDeclarationAttributes().empty());1085 1086 // First, take ownership of all attributes.1087 attrs.getPool().takeAllFrom(D.getAttributePool());1088 attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());1089 1090 // Now actually move the attributes over.1091 takeDeclAttributesAppend(attrs, D.getMutableDeclSpec().getAttributes());1092 takeDeclAttributesAppend(attrs, D.getAttributes());1093 for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)1094 takeDeclAttributesAppend(attrs, D.getTypeObject(i).getAttrs());1095}1096 1097ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,1098 DeclaratorContext context,1099 ParsedAttributes *paramAttrs) {1100 assert(context == DeclaratorContext::ObjCParameter ||1101 context == DeclaratorContext::ObjCResult);1102 assert((paramAttrs != nullptr) ==1103 (context == DeclaratorContext::ObjCParameter));1104 1105 assert(Tok.is(tok::l_paren) && "expected (");1106 1107 BalancedDelimiterTracker T(*this, tok::l_paren);1108 T.consumeOpen();1109 1110 ObjCDeclContextSwitch ObjCDC(*this);1111 1112 // Parse type qualifiers, in, inout, etc.1113 ParseObjCTypeQualifierList(DS, context);1114 SourceLocation TypeStartLoc = Tok.getLocation();1115 1116 ParsedType Ty;1117 if (isTypeSpecifierQualifier() || isObjCInstancetype()) {1118 // Parse an abstract declarator.1119 DeclSpec declSpec(AttrFactory);1120 declSpec.setObjCQualifiers(&DS);1121 DeclSpecContext dsContext = DeclSpecContext::DSC_normal;1122 if (context == DeclaratorContext::ObjCResult)1123 dsContext = DeclSpecContext::DSC_objc_method_result;1124 ParseSpecifierQualifierList(declSpec, AS_none, dsContext);1125 Declarator declarator(declSpec, ParsedAttributesView::none(), context);1126 ParseDeclarator(declarator);1127 1128 // If that's not invalid, extract a type.1129 if (!declarator.isInvalidType()) {1130 // Map a nullability specifier to a context-sensitive keyword attribute.1131 bool addedToDeclSpec = false;1132 if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)1133 addContextSensitiveTypeNullability(*this, declarator,1134 DS.getNullability(),1135 DS.getNullabilityLoc(),1136 addedToDeclSpec);1137 1138 TypeResult type = Actions.ActOnTypeName(declarator);1139 if (!type.isInvalid())1140 Ty = type.get();1141 1142 // If we're parsing a parameter, steal all the decl attributes1143 // and add them to the decl spec.1144 if (context == DeclaratorContext::ObjCParameter)1145 takeDeclAttributes(*paramAttrs, declarator);1146 }1147 }1148 1149 if (Tok.is(tok::r_paren))1150 T.consumeClose();1151 else if (Tok.getLocation() == TypeStartLoc) {1152 // If we didn't eat any tokens, then this isn't a type.1153 Diag(Tok, diag::err_expected_type);1154 SkipUntil(tok::r_paren, StopAtSemi);1155 } else {1156 // Otherwise, we found *something*, but didn't get a ')' in the right1157 // place. Emit an error then return what we have as the type.1158 T.consumeClose();1159 }1160 return Ty;1161}1162 1163Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,1164 tok::TokenKind mType,1165 tok::ObjCKeywordKind MethodImplKind,1166 bool MethodDefinition) {1167 ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);1168 1169 if (Tok.is(tok::code_completion)) {1170 cutOffParsing();1171 Actions.CodeCompletion().CodeCompleteObjCMethodDecl(getCurScope(),1172 mType == tok::minus,1173 /*ReturnType=*/nullptr);1174 return nullptr;1175 }1176 1177 // Parse the return type if present.1178 ParsedType ReturnType;1179 ObjCDeclSpec DSRet;1180 if (Tok.is(tok::l_paren))1181 ReturnType =1182 ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResult, nullptr);1183 1184 // If attributes exist before the method, parse them.1185 ParsedAttributes methodAttrs(AttrFactory);1186 MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),1187 methodAttrs);1188 1189 if (Tok.is(tok::code_completion)) {1190 cutOffParsing();1191 Actions.CodeCompletion().CodeCompleteObjCMethodDecl(1192 getCurScope(), mType == tok::minus, ReturnType);1193 return nullptr;1194 }1195 1196 // Now parse the selector.1197 SourceLocation selLoc;1198 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);1199 1200 // An unnamed colon is valid.1201 if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.1202 Diag(Tok, diag::err_expected_selector_for_method)1203 << SourceRange(mLoc, Tok.getLocation());1204 // Skip until we get a ; or @.1205 SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);1206 return nullptr;1207 }1208 1209 SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;1210 if (Tok.isNot(tok::colon)) {1211 // If attributes exist after the method, parse them.1212 MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),1213 methodAttrs);1214 1215 Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);1216 Decl *Result = Actions.ObjC().ActOnMethodDeclaration(1217 getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType,1218 selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs,1219 MethodImplKind, false, MethodDefinition);1220 PD.complete(Result);1221 return Result;1222 }1223 1224 SmallVector<const IdentifierInfo *, 12> KeyIdents;1225 SmallVector<SourceLocation, 12> KeyLocs;1226 SmallVector<SemaObjC::ObjCArgInfo, 12> ArgInfos;1227 ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |1228 Scope::FunctionDeclarationScope | Scope::DeclScope);1229 1230 AttributePool allParamAttrs(AttrFactory);1231 while (true) {1232 ParsedAttributes paramAttrs(AttrFactory);1233 SemaObjC::ObjCArgInfo ArgInfo;1234 1235 // Each iteration parses a single keyword argument.1236 if (ExpectAndConsume(tok::colon))1237 break;1238 1239 ArgInfo.Type = nullptr;1240 if (Tok.is(tok::l_paren)) // Parse the argument type if present.1241 ArgInfo.Type = ParseObjCTypeName(1242 ArgInfo.DeclSpec, DeclaratorContext::ObjCParameter, ¶mAttrs);1243 1244 // If attributes exist before the argument name, parse them.1245 // Regardless, collect all the attributes we've parsed so far.1246 MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),1247 paramAttrs);1248 ArgInfo.ArgAttrs = paramAttrs;1249 1250 // Code completion for the next piece of the selector.1251 if (Tok.is(tok::code_completion)) {1252 cutOffParsing();1253 KeyIdents.push_back(SelIdent);1254 Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector(1255 getCurScope(), mType == tok::minus,1256 /*AtParameterName=*/true, ReturnType, KeyIdents);1257 return nullptr;1258 }1259 1260 if (expectIdentifier())1261 break; // missing argument name.1262 1263 ArgInfo.Name = Tok.getIdentifierInfo();1264 ArgInfo.NameLoc = Tok.getLocation();1265 ConsumeToken(); // Eat the identifier.1266 1267 ArgInfos.push_back(ArgInfo);1268 KeyIdents.push_back(SelIdent);1269 KeyLocs.push_back(selLoc);1270 1271 // Make sure the attributes persist.1272 allParamAttrs.takeAllFrom(paramAttrs.getPool());1273 1274 // Code completion for the next piece of the selector.1275 if (Tok.is(tok::code_completion)) {1276 cutOffParsing();1277 Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector(1278 getCurScope(), mType == tok::minus,1279 /*AtParameterName=*/false, ReturnType, KeyIdents);1280 return nullptr;1281 }1282 1283 // Check for another keyword selector.1284 SelIdent = ParseObjCSelectorPiece(selLoc);1285 if (!SelIdent && Tok.isNot(tok::colon))1286 break;1287 if (!SelIdent) {1288 SourceLocation ColonLoc = Tok.getLocation();1289 if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {1290 Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;1291 Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;1292 Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;1293 }1294 }1295 // We have a selector or a colon, continue parsing.1296 }1297 1298 bool isVariadic = false;1299 bool cStyleParamWarned = false;1300 // Parse the (optional) parameter list.1301 while (Tok.is(tok::comma)) {1302 ConsumeToken();1303 if (Tok.is(tok::ellipsis)) {1304 isVariadic = true;1305 ConsumeToken();1306 break;1307 }1308 if (!cStyleParamWarned) {1309 Diag(Tok, diag::warn_cstyle_param);1310 cStyleParamWarned = true;1311 }1312 DeclSpec DS(AttrFactory);1313 ParsedTemplateInfo TemplateInfo;1314 ParseDeclarationSpecifiers(DS, TemplateInfo);1315 // Parse the declarator.1316 Declarator ParmDecl(DS, ParsedAttributesView::none(),1317 DeclaratorContext::Prototype);1318 ParseDeclarator(ParmDecl);1319 const IdentifierInfo *ParmII = ParmDecl.getIdentifier();1320 Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);1321 CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,1322 ParmDecl.getIdentifierLoc(),1323 Param,1324 nullptr));1325 }1326 1327 // Turn ArgInfos into parameters. This must happen after parsing all1328 // parameters for bug compatibility with previous versions of Clang. (For1329 // instance, if a method declares a parameter called "id", that parameter must1330 // not shadow the "id" type.)1331 SmallVector<ParmVarDecl *, 12> ObjCParamInfo;1332 for (auto &ArgInfo : ArgInfos) {1333 ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration(1334 getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition);1335 ObjCParamInfo.push_back(Param);1336 }1337 1338 // FIXME: Add support for optional parameter list...1339 // If attributes exist after the method, parse them.1340 MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),1341 methodAttrs);1342 1343 if (KeyIdents.size() == 0)1344 return nullptr;1345 1346 Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),1347 &KeyIdents[0]);1348 Decl *Result = Actions.ObjC().ActOnMethodDeclaration(1349 getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,1350 Sel, ObjCParamInfo.data(), CParamInfo.data(), CParamInfo.size(),1351 methodAttrs, MethodImplKind, isVariadic, MethodDefinition);1352 1353 PD.complete(Result);1354 return Result;1355}1356 1357bool Parser::1358ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,1359 SmallVectorImpl<SourceLocation> &ProtocolLocs,1360 bool WarnOnDeclarations, bool ForObjCContainer,1361 SourceLocation &LAngleLoc, SourceLocation &EndLoc,1362 bool consumeLastToken) {1363 assert(Tok.is(tok::less) && "expected <");1364 1365 LAngleLoc = ConsumeToken(); // the "<"1366 1367 SmallVector<IdentifierLoc, 8> ProtocolIdents;1368 1369 while (true) {1370 if (Tok.is(tok::code_completion)) {1371 cutOffParsing();1372 Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(1373 ProtocolIdents);1374 return true;1375 }1376 1377 if (expectIdentifier()) {1378 SkipUntil(tok::greater, StopAtSemi);1379 return true;1380 }1381 ProtocolIdents.emplace_back(Tok.getLocation(), Tok.getIdentifierInfo());1382 ProtocolLocs.push_back(Tok.getLocation());1383 ConsumeToken();1384 1385 if (!TryConsumeToken(tok::comma))1386 break;1387 }1388 1389 // Consume the '>'.1390 if (ParseGreaterThanInTemplateList(LAngleLoc, EndLoc, consumeLastToken,1391 /*ObjCGenericList=*/false))1392 return true;1393 1394 // Convert the list of protocols identifiers into a list of protocol decls.1395 Actions.ObjC().FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,1396 ProtocolIdents, Protocols);1397 return false;1398}1399 1400TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {1401 assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");1402 assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C");1403 1404 SourceLocation lAngleLoc;1405 SmallVector<Decl *, 8> protocols;1406 SmallVector<SourceLocation, 8> protocolLocs;1407 (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false,1408 lAngleLoc, rAngleLoc,1409 /*consumeLastToken=*/true);1410 TypeResult result = Actions.ObjC().actOnObjCProtocolQualifierType(1411 lAngleLoc, protocols, protocolLocs, rAngleLoc);1412 if (result.isUsable()) {1413 Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id)1414 << FixItHint::CreateInsertion(lAngleLoc, "id")1415 << SourceRange(lAngleLoc, rAngleLoc);1416 }1417 1418 return result;1419}1420 1421void Parser::parseObjCTypeArgsOrProtocolQualifiers(1422 ParsedType baseType,1423 SourceLocation &typeArgsLAngleLoc,1424 SmallVectorImpl<ParsedType> &typeArgs,1425 SourceLocation &typeArgsRAngleLoc,1426 SourceLocation &protocolLAngleLoc,1427 SmallVectorImpl<Decl *> &protocols,1428 SmallVectorImpl<SourceLocation> &protocolLocs,1429 SourceLocation &protocolRAngleLoc,1430 bool consumeLastToken,1431 bool warnOnIncompleteProtocols) {1432 assert(Tok.is(tok::less) && "Not at the start of type args or protocols");1433 SourceLocation lAngleLoc = ConsumeToken();1434 1435 // Whether all of the elements we've parsed thus far are single1436 // identifiers, which might be types or might be protocols.1437 bool allSingleIdentifiers = true;1438 SmallVector<IdentifierInfo *, 4> identifiers;1439 SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs;1440 1441 // Parse a list of comma-separated identifiers, bailing out if we1442 // see something different.1443 do {1444 // Parse a single identifier.1445 if (Tok.is(tok::identifier) &&1446 (NextToken().is(tok::comma) ||1447 NextToken().is(tok::greater) ||1448 NextToken().is(tok::greatergreater))) {1449 identifiers.push_back(Tok.getIdentifierInfo());1450 identifierLocs.push_back(ConsumeToken());1451 continue;1452 }1453 1454 if (Tok.is(tok::code_completion)) {1455 // FIXME: Also include types here.1456 SmallVector<IdentifierLoc, 4> identifierLocPairs;1457 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1458 identifierLocPairs.emplace_back(identifierLocs[i], identifiers[i]);1459 }1460 1461 QualType BaseT = Actions.GetTypeFromParser(baseType);1462 cutOffParsing();1463 if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {1464 Actions.CodeCompletion().CodeCompleteOrdinaryName(1465 getCurScope(), SemaCodeCompletion::PCC_Type);1466 } else {1467 Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(1468 identifierLocPairs);1469 }1470 return;1471 }1472 1473 allSingleIdentifiers = false;1474 break;1475 } while (TryConsumeToken(tok::comma));1476 1477 // If we parsed an identifier list, semantic analysis sorts out1478 // whether it refers to protocols or to type arguments.1479 if (allSingleIdentifiers) {1480 // Parse the closing '>'.1481 SourceLocation rAngleLoc;1482 (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,1483 /*ObjCGenericList=*/true);1484 1485 // Let Sema figure out what we parsed.1486 Actions.ObjC().actOnObjCTypeArgsOrProtocolQualifiers(1487 getCurScope(), baseType, lAngleLoc, identifiers, identifierLocs,1488 rAngleLoc, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc,1489 protocolLAngleLoc, protocols, protocolRAngleLoc,1490 warnOnIncompleteProtocols);1491 return;1492 }1493 1494 // We parsed an identifier list but stumbled into non single identifiers, this1495 // means we might (a) check that what we already parsed is a legitimate type1496 // (not a protocol or unknown type) and (b) parse the remaining ones, which1497 // must all be type args.1498 1499 // Convert the identifiers into type arguments.1500 bool invalid = false;1501 IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr;1502 SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc;1503 SmallVector<IdentifierInfo *, 2> unknownTypeArgs;1504 SmallVector<SourceLocation, 2> unknownTypeArgsLoc;1505 1506 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1507 ParsedType typeArg1508 = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());1509 if (typeArg) {1510 DeclSpec DS(AttrFactory);1511 const char *prevSpec = nullptr;1512 unsigned diagID;1513 DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID,1514 typeArg, Actions.getASTContext().getPrintingPolicy());1515 1516 // Form a declarator to turn this into a type.1517 Declarator D(DS, ParsedAttributesView::none(),1518 DeclaratorContext::TypeName);1519 TypeResult fullTypeArg = Actions.ActOnTypeName(D);1520 if (fullTypeArg.isUsable()) {1521 typeArgs.push_back(fullTypeArg.get());1522 if (!foundValidTypeId) {1523 foundValidTypeId = identifiers[i];1524 foundValidTypeSrcLoc = identifierLocs[i];1525 }1526 } else {1527 invalid = true;1528 unknownTypeArgs.push_back(identifiers[i]);1529 unknownTypeArgsLoc.push_back(identifierLocs[i]);1530 }1531 } else {1532 invalid = true;1533 if (!Actions.ObjC().LookupProtocol(identifiers[i], identifierLocs[i])) {1534 unknownTypeArgs.push_back(identifiers[i]);1535 unknownTypeArgsLoc.push_back(identifierLocs[i]);1536 } else if (!foundProtocolId) {1537 foundProtocolId = identifiers[i];1538 foundProtocolSrcLoc = identifierLocs[i];1539 }1540 }1541 }1542 1543 // Continue parsing type-names.1544 do {1545 Token CurTypeTok = Tok;1546 TypeResult typeArg = ParseTypeName();1547 1548 // Consume the '...' for a pack expansion.1549 SourceLocation ellipsisLoc;1550 TryConsumeToken(tok::ellipsis, ellipsisLoc);1551 if (typeArg.isUsable() && ellipsisLoc.isValid()) {1552 typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc);1553 }1554 1555 if (typeArg.isUsable()) {1556 typeArgs.push_back(typeArg.get());1557 if (!foundValidTypeId) {1558 foundValidTypeId = CurTypeTok.getIdentifierInfo();1559 foundValidTypeSrcLoc = CurTypeTok.getLocation();1560 }1561 } else {1562 invalid = true;1563 }1564 } while (TryConsumeToken(tok::comma));1565 1566 // Diagnose the mix between type args and protocols.1567 if (foundProtocolId && foundValidTypeId)1568 Actions.ObjC().DiagnoseTypeArgsAndProtocols(1569 foundProtocolId, foundProtocolSrcLoc, foundValidTypeId,1570 foundValidTypeSrcLoc);1571 1572 // Diagnose unknown arg types.1573 ParsedType T;1574 if (unknownTypeArgs.size())1575 for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i)1576 Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i],1577 getCurScope(), nullptr, T);1578 1579 // Parse the closing '>'.1580 SourceLocation rAngleLoc;1581 (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,1582 /*ObjCGenericList=*/true);1583 1584 if (invalid) {1585 typeArgs.clear();1586 return;1587 }1588 1589 // Record left/right angle locations.1590 typeArgsLAngleLoc = lAngleLoc;1591 typeArgsRAngleLoc = rAngleLoc;1592}1593 1594void Parser::parseObjCTypeArgsAndProtocolQualifiers(1595 ParsedType baseType,1596 SourceLocation &typeArgsLAngleLoc,1597 SmallVectorImpl<ParsedType> &typeArgs,1598 SourceLocation &typeArgsRAngleLoc,1599 SourceLocation &protocolLAngleLoc,1600 SmallVectorImpl<Decl *> &protocols,1601 SmallVectorImpl<SourceLocation> &protocolLocs,1602 SourceLocation &protocolRAngleLoc,1603 bool consumeLastToken) {1604 assert(Tok.is(tok::less));1605 1606 // Parse the first angle-bracket-delimited clause.1607 parseObjCTypeArgsOrProtocolQualifiers(baseType,1608 typeArgsLAngleLoc,1609 typeArgs,1610 typeArgsRAngleLoc,1611 protocolLAngleLoc,1612 protocols,1613 protocolLocs,1614 protocolRAngleLoc,1615 consumeLastToken,1616 /*warnOnIncompleteProtocols=*/false);1617 if (Tok.is(tok::eof)) // Nothing else to do here...1618 return;1619 1620 // An Objective-C object pointer followed by type arguments1621 // can then be followed again by a set of protocol references, e.g.,1622 // \c NSArray<NSView><NSTextDelegate>1623 if ((consumeLastToken && Tok.is(tok::less)) ||1624 (!consumeLastToken && NextToken().is(tok::less))) {1625 // If we aren't consuming the last token, the prior '>' is still hanging1626 // there. Consume it before we parse the protocol qualifiers.1627 if (!consumeLastToken)1628 ConsumeToken();1629 1630 if (!protocols.empty()) {1631 SkipUntilFlags skipFlags = SkipUntilFlags();1632 if (!consumeLastToken)1633 skipFlags = skipFlags | StopBeforeMatch;1634 Diag(Tok, diag::err_objc_type_args_after_protocols)1635 << SourceRange(protocolLAngleLoc, protocolRAngleLoc);1636 SkipUntil(tok::greater, tok::greatergreater, skipFlags);1637 } else {1638 ParseObjCProtocolReferences(protocols, protocolLocs,1639 /*WarnOnDeclarations=*/false,1640 /*ForObjCContainer=*/false,1641 protocolLAngleLoc, protocolRAngleLoc,1642 consumeLastToken);1643 }1644 }1645}1646 1647TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(1648 SourceLocation loc,1649 ParsedType type,1650 bool consumeLastToken,1651 SourceLocation &endLoc) {1652 assert(Tok.is(tok::less));1653 SourceLocation typeArgsLAngleLoc;1654 SmallVector<ParsedType, 4> typeArgs;1655 SourceLocation typeArgsRAngleLoc;1656 SourceLocation protocolLAngleLoc;1657 SmallVector<Decl *, 4> protocols;1658 SmallVector<SourceLocation, 4> protocolLocs;1659 SourceLocation protocolRAngleLoc;1660 1661 // Parse type arguments and protocol qualifiers.1662 parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs,1663 typeArgsRAngleLoc, protocolLAngleLoc,1664 protocols, protocolLocs,1665 protocolRAngleLoc, consumeLastToken);1666 1667 if (Tok.is(tok::eof))1668 return true; // Invalid type result.1669 1670 // Compute the location of the last token.1671 if (consumeLastToken)1672 endLoc = PrevTokLocation;1673 else1674 endLoc = Tok.getLocation();1675 1676 return Actions.ObjC().actOnObjCTypeArgsAndProtocolQualifiers(1677 getCurScope(), loc, type, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc,1678 protocolLAngleLoc, protocols, protocolLocs, protocolRAngleLoc);1679}1680 1681void Parser::HelperActionsForIvarDeclarations(1682 ObjCContainerDecl *interfaceDecl, SourceLocation atLoc,1683 BalancedDelimiterTracker &T, SmallVectorImpl<Decl *> &AllIvarDecls,1684 bool RBraceMissing) {1685 if (!RBraceMissing)1686 T.consumeClose();1687 1688 assert(getObjCDeclContext() == interfaceDecl &&1689 "Ivars should have interfaceDecl as their decl context");1690 Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);1691 // Call ActOnFields() even if we don't have any decls. This is useful1692 // for code rewriting tools that need to be aware of the empty list.1693 Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls,1694 T.getOpenLocation(), T.getCloseLocation(),1695 ParsedAttributesView());1696}1697 1698void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl,1699 tok::ObjCKeywordKind visibility,1700 SourceLocation atLoc) {1701 assert(Tok.is(tok::l_brace) && "expected {");1702 SmallVector<Decl *, 32> AllIvarDecls;1703 1704 ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope);1705 1706 BalancedDelimiterTracker T(*this, tok::l_brace);1707 T.consumeOpen();1708 // While we still have something to read, read the instance variables.1709 while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {1710 // Each iteration of this loop reads one objc-instance-variable-decl.1711 1712 // Check for extraneous top-level semicolon.1713 if (Tok.is(tok::semi)) {1714 ConsumeExtraSemi(ExtraSemiKind::InstanceVariableList);1715 continue;1716 }1717 1718 // Set the default visibility to private.1719 if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec1720 if (Tok.is(tok::code_completion)) {1721 cutOffParsing();1722 Actions.CodeCompletion().CodeCompleteObjCAtVisibility(getCurScope());1723 return;1724 }1725 1726 switch (Tok.getObjCKeywordID()) {1727 case tok::objc_private:1728 case tok::objc_public:1729 case tok::objc_protected:1730 case tok::objc_package:1731 visibility = Tok.getObjCKeywordID();1732 ConsumeToken();1733 continue;1734 1735 case tok::objc_end:1736 Diag(Tok, diag::err_objc_unexpected_atend);1737 Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));1738 Tok.setKind(tok::at);1739 Tok.setLength(1);1740 PP.EnterToken(Tok, /*IsReinject*/true);1741 HelperActionsForIvarDeclarations(interfaceDecl, atLoc,1742 T, AllIvarDecls, true);1743 return;1744 1745 default:1746 Diag(Tok, diag::err_objc_illegal_visibility_spec);1747 continue;1748 }1749 }1750 1751 if (Tok.is(tok::code_completion)) {1752 cutOffParsing();1753 Actions.CodeCompletion().CodeCompleteOrdinaryName(1754 getCurScope(), SemaCodeCompletion::PCC_ObjCInstanceVariableList);1755 return;1756 }1757 1758 // This needs to duplicate a small amount of code from1759 // ParseStructUnionBody() for things that should work in both1760 // C struct and in Objective-C class instance variables.1761 if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {1762 SourceLocation DeclEnd;1763 ParseStaticAssertDeclaration(DeclEnd);1764 continue;1765 }1766 1767 auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {1768 assert(getObjCDeclContext() == interfaceDecl &&1769 "Ivar should have interfaceDecl as its decl context");1770 // Install the declarator into the interface decl.1771 FD.D.setObjCIvar(true);1772 Decl *Field = Actions.ObjC().ActOnIvar(1773 getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,1774 FD.BitfieldSize, visibility);1775 if (Field)1776 AllIvarDecls.push_back(Field);1777 FD.complete(Field);1778 return Field;1779 };1780 1781 // Parse all the comma separated declarators.1782 ParsingDeclSpec DS(*this);1783 ParseStructDeclaration(DS, ObjCIvarCallback);1784 1785 if (Tok.is(tok::semi)) {1786 ConsumeToken();1787 } else {1788 Diag(Tok, diag::err_expected_semi_decl_list);1789 // Skip to end of block or statement1790 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);1791 }1792 }1793 HelperActionsForIvarDeclarations(interfaceDecl, atLoc,1794 T, AllIvarDecls, false);1795}1796 1797Parser::DeclGroupPtrTy1798Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,1799 ParsedAttributes &attrs) {1800 assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&1801 "ParseObjCAtProtocolDeclaration(): Expected @protocol");1802 ConsumeToken(); // the "protocol" identifier1803 1804 if (Tok.is(tok::code_completion)) {1805 cutOffParsing();1806 Actions.CodeCompletion().CodeCompleteObjCProtocolDecl(getCurScope());1807 return nullptr;1808 }1809 1810 MaybeSkipAttributes(tok::objc_protocol);1811 1812 if (expectIdentifier())1813 return nullptr; // missing protocol name.1814 // Save the protocol name, then consume it.1815 IdentifierInfo *protocolName = Tok.getIdentifierInfo();1816 SourceLocation nameLoc = ConsumeToken();1817 1818 if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.1819 IdentifierLoc ProtoInfo(nameLoc, protocolName);1820 return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo,1821 attrs);1822 }1823 1824 CheckNestedObjCContexts(AtLoc);1825 1826 if (Tok.is(tok::comma)) { // list of forward declarations.1827 SmallVector<IdentifierLoc, 8> ProtocolRefs;1828 ProtocolRefs.emplace_back(nameLoc, protocolName);1829 1830 // Parse the list of forward declarations.1831 while (true) {1832 ConsumeToken(); // the ','1833 if (expectIdentifier()) {1834 SkipUntil(tok::semi);1835 return nullptr;1836 }1837 ProtocolRefs.emplace_back(Tok.getLocation(), Tok.getIdentifierInfo());1838 ConsumeToken(); // the identifier1839 1840 if (Tok.isNot(tok::comma))1841 break;1842 }1843 // Consume the ';'.1844 if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))1845 return nullptr;1846 1847 return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs,1848 attrs);1849 }1850 1851 // Last, and definitely not least, parse a protocol declaration.1852 SourceLocation LAngleLoc, EndProtoLoc;1853 1854 SmallVector<Decl *, 8> ProtocolRefs;1855 SmallVector<SourceLocation, 8> ProtocolLocs;1856 if (Tok.is(tok::less) &&1857 ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,1858 LAngleLoc, EndProtoLoc,1859 /*consumeLastToken=*/true))1860 return nullptr;1861 1862 SkipBodyInfo SkipBody;1863 ObjCProtocolDecl *ProtoType = Actions.ObjC().ActOnStartProtocolInterface(1864 AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),1865 ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody);1866 1867 ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);1868 if (SkipBody.CheckSameAsPrevious) {1869 auto *PreviousDef = cast<ObjCProtocolDecl>(SkipBody.Previous);1870 if (Actions.ActOnDuplicateODRHashDefinition(ProtoType, PreviousDef)) {1871 ProtoType->mergeDuplicateDefinitionWithCommon(1872 PreviousDef->getDefinition());1873 } else {1874 ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),1875 getPreprocessor().getLangOpts());1876 DiagsEmitter.diagnoseMismatch(PreviousDef, ProtoType);1877 }1878 }1879 return Actions.ConvertDeclToDeclGroup(ProtoType);1880}1881 1882Parser::DeclGroupPtrTy1883Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,1884 ParsedAttributes &Attrs) {1885 assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&1886 "ParseObjCAtImplementationDeclaration(): Expected @implementation");1887 CheckNestedObjCContexts(AtLoc);1888 ConsumeToken(); // the "implementation" identifier1889 1890 // Code completion after '@implementation'.1891 if (Tok.is(tok::code_completion)) {1892 cutOffParsing();1893 Actions.CodeCompletion().CodeCompleteObjCImplementationDecl(getCurScope());1894 return nullptr;1895 }1896 1897 MaybeSkipAttributes(tok::objc_implementation);1898 1899 if (expectIdentifier())1900 return nullptr; // missing class or category name.1901 // We have a class or category name - consume it.1902 IdentifierInfo *nameId = Tok.getIdentifierInfo();1903 SourceLocation nameLoc = ConsumeToken(); // consume class or category name1904 ObjCImplDecl *ObjCImpDecl = nullptr;1905 1906 // Neither a type parameter list nor a list of protocol references is1907 // permitted here. Parse and diagnose them.1908 if (Tok.is(tok::less)) {1909 SourceLocation lAngleLoc, rAngleLoc;1910 SmallVector<IdentifierLoc, 8> protocolIdents;1911 SourceLocation diagLoc = Tok.getLocation();1912 ObjCTypeParamListScope typeParamScope(Actions, getCurScope());1913 if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc,1914 protocolIdents, rAngleLoc)) {1915 Diag(diagLoc, diag::err_objc_parameterized_implementation)1916 << SourceRange(diagLoc, PrevTokLocation);1917 } else if (lAngleLoc.isValid()) {1918 Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier)1919 << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc));1920 }1921 }1922 1923 if (Tok.is(tok::l_paren)) {1924 // we have a category implementation.1925 ConsumeParen();1926 SourceLocation categoryLoc, rparenLoc;1927 IdentifierInfo *categoryId = nullptr;1928 1929 if (Tok.is(tok::code_completion)) {1930 cutOffParsing();1931 Actions.CodeCompletion().CodeCompleteObjCImplementationCategory(1932 getCurScope(), nameId, nameLoc);1933 return nullptr;1934 }1935 1936 if (Tok.is(tok::identifier)) {1937 categoryId = Tok.getIdentifierInfo();1938 categoryLoc = ConsumeToken();1939 } else {1940 Diag(Tok, diag::err_expected)1941 << tok::identifier; // missing category name.1942 return nullptr;1943 }1944 if (Tok.isNot(tok::r_paren)) {1945 Diag(Tok, diag::err_expected) << tok::r_paren;1946 SkipUntil(tok::r_paren); // don't stop at ';'1947 return nullptr;1948 }1949 rparenLoc = ConsumeParen();1950 if (Tok.is(tok::less)) { // we have illegal '<' try to recover1951 Diag(Tok, diag::err_unexpected_protocol_qualifier);1952 SourceLocation protocolLAngleLoc, protocolRAngleLoc;1953 SmallVector<Decl *, 4> protocols;1954 SmallVector<SourceLocation, 4> protocolLocs;1955 (void)ParseObjCProtocolReferences(protocols, protocolLocs,1956 /*warnOnIncompleteProtocols=*/false,1957 /*ForObjCContainer=*/false,1958 protocolLAngleLoc, protocolRAngleLoc,1959 /*consumeLastToken=*/true);1960 }1961 ObjCImpDecl = Actions.ObjC().ActOnStartCategoryImplementation(1962 AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs);1963 1964 } else {1965 // We have a class implementation1966 SourceLocation superClassLoc;1967 IdentifierInfo *superClassId = nullptr;1968 if (TryConsumeToken(tok::colon)) {1969 // We have a super class1970 if (expectIdentifier())1971 return nullptr; // missing super class name.1972 superClassId = Tok.getIdentifierInfo();1973 superClassLoc = ConsumeToken(); // Consume super class name1974 }1975 ObjCImpDecl = Actions.ObjC().ActOnStartClassImplementation(1976 AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs);1977 1978 if (Tok.is(tok::l_brace)) // we have ivars1979 ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);1980 else if (Tok.is(tok::less)) { // we have illegal '<' try to recover1981 Diag(Tok, diag::err_unexpected_protocol_qualifier);1982 1983 SourceLocation protocolLAngleLoc, protocolRAngleLoc;1984 SmallVector<Decl *, 4> protocols;1985 SmallVector<SourceLocation, 4> protocolLocs;1986 (void)ParseObjCProtocolReferences(protocols, protocolLocs,1987 /*warnOnIncompleteProtocols=*/false,1988 /*ForObjCContainer=*/false,1989 protocolLAngleLoc, protocolRAngleLoc,1990 /*consumeLastToken=*/true);1991 }1992 }1993 assert(ObjCImpDecl);1994 1995 SmallVector<Decl *, 8> DeclsInGroup;1996 1997 {1998 ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);1999 while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {2000 ParsedAttributes DeclAttrs(AttrFactory);2001 MaybeParseCXX11Attributes(DeclAttrs);2002 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);2003 if (DeclGroupPtrTy DGP =2004 ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs)) {2005 DeclGroupRef DG = DGP.get();2006 DeclsInGroup.append(DG.begin(), DG.end());2007 }2008 }2009 }2010 2011 return Actions.ObjC().ActOnFinishObjCImplementation(ObjCImpDecl,2012 DeclsInGroup);2013}2014 2015Parser::DeclGroupPtrTy2016Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {2017 assert(Tok.isObjCAtKeyword(tok::objc_end) &&2018 "ParseObjCAtEndDeclaration(): Expected @end");2019 ConsumeToken(); // the "end" identifier2020 if (CurParsedObjCImpl)2021 CurParsedObjCImpl->finish(atEnd);2022 else2023 // missing @implementation2024 Diag(atEnd.getBegin(), diag::err_expected_objc_container);2025 return nullptr;2026}2027 2028Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {2029 if (!Finished) {2030 finish(P.Tok.getLocation());2031 if (P.isEofOrEom()) {2032 P.Diag(P.Tok, diag::err_objc_missing_end)2033 << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");2034 P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start)2035 << SemaObjC::OCK_Implementation;2036 }2037 }2038 P.CurParsedObjCImpl = nullptr;2039 assert(LateParsedObjCMethods.empty());2040}2041 2042void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {2043 assert(!Finished);2044 P.Actions.ObjC().DefaultSynthesizeProperties(P.getCurScope(), Dcl,2045 AtEnd.getBegin());2046 for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)2047 P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],2048 true/*Methods*/);2049 2050 P.Actions.ObjC().ActOnAtEnd(P.getCurScope(), AtEnd);2051 2052 if (HasCFunction)2053 for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)2054 P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],2055 false/*c-functions*/);2056 2057 /// Clear and free the cached objc methods.2058 for (LateParsedObjCMethodContainer::iterator2059 I = LateParsedObjCMethods.begin(),2060 E = LateParsedObjCMethods.end(); I != E; ++I)2061 delete *I;2062 LateParsedObjCMethods.clear();2063 2064 Finished = true;2065}2066 2067Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {2068 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&2069 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");2070 ConsumeToken(); // consume compatibility_alias2071 if (expectIdentifier())2072 return nullptr;2073 IdentifierInfo *aliasId = Tok.getIdentifierInfo();2074 SourceLocation aliasLoc = ConsumeToken(); // consume alias-name2075 if (expectIdentifier())2076 return nullptr;2077 IdentifierInfo *classId = Tok.getIdentifierInfo();2078 SourceLocation classLoc = ConsumeToken(); // consume class-name;2079 ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");2080 return Actions.ObjC().ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,2081 classId, classLoc);2082}2083 2084Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {2085 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&2086 "ParseObjCPropertySynthesize(): Expected '@synthesize'");2087 ConsumeToken(); // consume synthesize2088 2089 while (true) {2090 if (Tok.is(tok::code_completion)) {2091 cutOffParsing();2092 Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition(2093 getCurScope());2094 return nullptr;2095 }2096 2097 if (Tok.isNot(tok::identifier)) {2098 Diag(Tok, diag::err_synthesized_property_name);2099 SkipUntil(tok::semi);2100 return nullptr;2101 }2102 2103 IdentifierInfo *propertyIvar = nullptr;2104 IdentifierInfo *propertyId = Tok.getIdentifierInfo();2105 SourceLocation propertyLoc = ConsumeToken(); // consume property name2106 SourceLocation propertyIvarLoc;2107 if (TryConsumeToken(tok::equal)) {2108 // property '=' ivar-name2109 if (Tok.is(tok::code_completion)) {2110 cutOffParsing();2111 Actions.CodeCompletion().CodeCompleteObjCPropertySynthesizeIvar(2112 getCurScope(), propertyId);2113 return nullptr;2114 }2115 2116 if (expectIdentifier())2117 break;2118 propertyIvar = Tok.getIdentifierInfo();2119 propertyIvarLoc = ConsumeToken(); // consume ivar-name2120 }2121 Actions.ObjC().ActOnPropertyImplDecl(2122 getCurScope(), atLoc, propertyLoc, true, propertyId, propertyIvar,2123 propertyIvarLoc, ObjCPropertyQueryKind::OBJC_PR_query_unknown);2124 if (Tok.isNot(tok::comma))2125 break;2126 ConsumeToken(); // consume ','2127 }2128 ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");2129 return nullptr;2130}2131 2132Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {2133 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&2134 "ParseObjCPropertyDynamic(): Expected '@dynamic'");2135 ConsumeToken(); // consume dynamic2136 2137 bool isClassProperty = false;2138 if (Tok.is(tok::l_paren)) {2139 ConsumeParen();2140 const IdentifierInfo *II = Tok.getIdentifierInfo();2141 2142 if (!II) {2143 Diag(Tok, diag::err_objc_expected_property_attr) << II;2144 SkipUntil(tok::r_paren, StopAtSemi);2145 } else {2146 SourceLocation AttrName = ConsumeToken(); // consume attribute name2147 if (II->isStr("class")) {2148 isClassProperty = true;2149 if (Tok.isNot(tok::r_paren)) {2150 Diag(Tok, diag::err_expected) << tok::r_paren;2151 SkipUntil(tok::r_paren, StopAtSemi);2152 } else2153 ConsumeParen();2154 } else {2155 Diag(AttrName, diag::err_objc_expected_property_attr) << II;2156 SkipUntil(tok::r_paren, StopAtSemi);2157 }2158 }2159 }2160 2161 while (true) {2162 if (Tok.is(tok::code_completion)) {2163 cutOffParsing();2164 Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition(2165 getCurScope());2166 return nullptr;2167 }2168 2169 if (expectIdentifier()) {2170 SkipUntil(tok::semi);2171 return nullptr;2172 }2173 2174 IdentifierInfo *propertyId = Tok.getIdentifierInfo();2175 SourceLocation propertyLoc = ConsumeToken(); // consume property name2176 Actions.ObjC().ActOnPropertyImplDecl(2177 getCurScope(), atLoc, propertyLoc, false, propertyId, nullptr,2178 SourceLocation(),2179 isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class2180 : ObjCPropertyQueryKind::OBJC_PR_query_unknown);2181 2182 if (Tok.isNot(tok::comma))2183 break;2184 ConsumeToken(); // consume ','2185 }2186 ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");2187 return nullptr;2188}2189 2190StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {2191 ExprResult Res;2192 ConsumeToken(); // consume throw2193 if (Tok.isNot(tok::semi)) {2194 Res = ParseExpression();2195 if (Res.isInvalid()) {2196 SkipUntil(tok::semi);2197 return StmtError();2198 }2199 }2200 // consume ';'2201 ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");2202 return Actions.ObjC().ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());2203}2204 2205StmtResult2206Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {2207 ConsumeToken(); // consume synchronized2208 if (Tok.isNot(tok::l_paren)) {2209 Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";2210 return StmtError();2211 }2212 2213 // The operand is surrounded with parentheses.2214 ConsumeParen(); // '('2215 ExprResult operand(ParseExpression());2216 2217 if (Tok.is(tok::r_paren)) {2218 ConsumeParen(); // ')'2219 } else {2220 if (!operand.isInvalid())2221 Diag(Tok, diag::err_expected) << tok::r_paren;2222 2223 // Skip forward until we see a left brace, but don't consume it.2224 SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);2225 }2226 2227 // Require a compound statement.2228 if (Tok.isNot(tok::l_brace)) {2229 if (!operand.isInvalid())2230 Diag(Tok, diag::err_expected) << tok::l_brace;2231 return StmtError();2232 }2233 2234 // Check the @synchronized operand now.2235 if (!operand.isInvalid())2236 operand =2237 Actions.ObjC().ActOnObjCAtSynchronizedOperand(atLoc, operand.get());2238 2239 // Parse the compound statement within a new scope.2240 ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);2241 StmtResult body(ParseCompoundStatementBody());2242 bodyScope.Exit();2243 2244 // If there was a semantic or parse error earlier with the2245 // operand, fail now.2246 if (operand.isInvalid())2247 return StmtError();2248 2249 if (body.isInvalid())2250 body = Actions.ActOnNullStmt(Tok.getLocation());2251 2252 return Actions.ObjC().ActOnObjCAtSynchronizedStmt(atLoc, operand.get(),2253 body.get());2254}2255 2256StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {2257 bool catch_or_finally_seen = false;2258 2259 ConsumeToken(); // consume try2260 if (Tok.isNot(tok::l_brace)) {2261 Diag(Tok, diag::err_expected) << tok::l_brace;2262 return StmtError();2263 }2264 StmtVector CatchStmts;2265 StmtResult FinallyStmt;2266 ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);2267 StmtResult TryBody(ParseCompoundStatementBody());2268 TryScope.Exit();2269 if (TryBody.isInvalid())2270 TryBody = Actions.ActOnNullStmt(Tok.getLocation());2271 2272 while (Tok.is(tok::at)) {2273 // At this point, we need to lookahead to determine if this @ is the start2274 // of an @catch or @finally. We don't want to consume the @ token if this2275 // is an @try or @encode or something else.2276 Token AfterAt = GetLookAheadToken(1);2277 if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&2278 !AfterAt.isObjCAtKeyword(tok::objc_finally))2279 break;2280 2281 SourceLocation AtCatchFinallyLoc = ConsumeToken();2282 if (Tok.isObjCAtKeyword(tok::objc_catch)) {2283 Decl *FirstPart = nullptr;2284 ConsumeToken(); // consume catch2285 if (Tok.is(tok::l_paren)) {2286 ConsumeParen();2287 ParseScope CatchScope(this, Scope::DeclScope |2288 Scope::CompoundStmtScope |2289 Scope::AtCatchScope);2290 if (Tok.isNot(tok::ellipsis)) {2291 DeclSpec DS(AttrFactory);2292 ParsedTemplateInfo TemplateInfo;2293 ParseDeclarationSpecifiers(DS, TemplateInfo);2294 Declarator ParmDecl(DS, ParsedAttributesView::none(),2295 DeclaratorContext::ObjCCatch);2296 ParseDeclarator(ParmDecl);2297 2298 // Inform the actions module about the declarator, so it2299 // gets added to the current scope.2300 FirstPart =2301 Actions.ObjC().ActOnObjCExceptionDecl(getCurScope(), ParmDecl);2302 } else2303 ConsumeToken(); // consume '...'2304 2305 SourceLocation RParenLoc;2306 2307 if (Tok.is(tok::r_paren))2308 RParenLoc = ConsumeParen();2309 else // Skip over garbage, until we get to ')'. Eat the ')'.2310 SkipUntil(tok::r_paren, StopAtSemi);2311 2312 StmtResult CatchBody(true);2313 if (Tok.is(tok::l_brace))2314 CatchBody = ParseCompoundStatementBody();2315 else2316 Diag(Tok, diag::err_expected) << tok::l_brace;2317 if (CatchBody.isInvalid())2318 CatchBody = Actions.ActOnNullStmt(Tok.getLocation());2319 2320 StmtResult Catch = Actions.ObjC().ActOnObjCAtCatchStmt(2321 AtCatchFinallyLoc, RParenLoc, FirstPart, CatchBody.get());2322 if (!Catch.isInvalid())2323 CatchStmts.push_back(Catch.get());2324 2325 } else {2326 Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)2327 << "@catch clause";2328 return StmtError();2329 }2330 catch_or_finally_seen = true;2331 } else {2332 assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");2333 ConsumeToken(); // consume finally2334 ParseScope FinallyScope(this,2335 Scope::DeclScope | Scope::CompoundStmtScope);2336 2337 bool ShouldCapture =2338 getTargetInfo().getTriple().isWindowsMSVCEnvironment();2339 if (ShouldCapture)2340 Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(),2341 CR_ObjCAtFinally, 1);2342 2343 StmtResult FinallyBody(true);2344 if (Tok.is(tok::l_brace))2345 FinallyBody = ParseCompoundStatementBody();2346 else2347 Diag(Tok, diag::err_expected) << tok::l_brace;2348 2349 if (FinallyBody.isInvalid()) {2350 FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());2351 if (ShouldCapture)2352 Actions.ActOnCapturedRegionError();2353 } else if (ShouldCapture) {2354 FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get());2355 }2356 2357 FinallyStmt = Actions.ObjC().ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,2358 FinallyBody.get());2359 catch_or_finally_seen = true;2360 break;2361 }2362 }2363 if (!catch_or_finally_seen) {2364 Diag(atLoc, diag::err_missing_catch_finally);2365 return StmtError();2366 }2367 2368 return Actions.ObjC().ActOnObjCAtTryStmt(atLoc, TryBody.get(), CatchStmts,2369 FinallyStmt.get());2370}2371 2372StmtResult2373Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {2374 ConsumeToken(); // consume autoreleasepool2375 if (Tok.isNot(tok::l_brace)) {2376 Diag(Tok, diag::err_expected) << tok::l_brace;2377 return StmtError();2378 }2379 // Enter a scope to hold everything within the compound stmt. Compound2380 // statements can always hold declarations.2381 ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);2382 2383 StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());2384 2385 BodyScope.Exit();2386 if (AutoreleasePoolBody.isInvalid())2387 AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());2388 return Actions.ObjC().ActOnObjCAutoreleasePoolStmt(atLoc,2389 AutoreleasePoolBody.get());2390}2391 2392void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {2393 if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&2394 trySkippingFunctionBody()) {2395 Actions.ActOnSkippedFunctionBody(MDecl);2396 return;2397 }2398 2399 LexedMethod* LM = new LexedMethod(this, MDecl);2400 CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);2401 CachedTokens &Toks = LM->Toks;2402 // Begin by storing the '{' or 'try' or ':' token.2403 Toks.push_back(Tok);2404 if (Tok.is(tok::kw_try)) {2405 ConsumeToken();2406 if (Tok.is(tok::colon)) {2407 Toks.push_back(Tok);2408 ConsumeToken();2409 while (Tok.isNot(tok::l_brace)) {2410 ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);2411 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);2412 }2413 }2414 Toks.push_back(Tok); // also store '{'2415 }2416 else if (Tok.is(tok::colon)) {2417 ConsumeToken();2418 // FIXME: This is wrong, due to C++11 braced initialization.2419 while (Tok.isNot(tok::l_brace)) {2420 ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);2421 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);2422 }2423 Toks.push_back(Tok); // also store '{'2424 }2425 ConsumeBrace();2426 // Consume everything up to (and including) the matching right brace.2427 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);2428 while (Tok.is(tok::kw_catch)) {2429 ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);2430 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);2431 }2432}2433 2434Decl *Parser::ParseObjCMethodDefinition() {2435 Decl *MDecl = ParseObjCMethodPrototype();2436 2437 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),2438 "parsing Objective-C method");2439 2440 // parse optional ';'2441 if (Tok.is(tok::semi)) {2442 if (CurParsedObjCImpl) {2443 Diag(Tok, diag::warn_semicolon_before_method_body)2444 << FixItHint::CreateRemoval(Tok.getLocation());2445 }2446 ConsumeToken();2447 }2448 2449 // We should have an opening brace now.2450 if (Tok.isNot(tok::l_brace)) {2451 Diag(Tok, diag::err_expected_method_body);2452 2453 // Skip over garbage, until we get to '{'. Don't eat the '{'.2454 SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);2455 2456 // If we didn't find the '{', bail out.2457 if (Tok.isNot(tok::l_brace))2458 return nullptr;2459 }2460 2461 if (!MDecl) {2462 ConsumeBrace();2463 SkipUntil(tok::r_brace);2464 return nullptr;2465 }2466 2467 // Allow the rest of sema to find private method decl implementations.2468 Actions.ObjC().AddAnyMethodToGlobalPool(MDecl);2469 assert (CurParsedObjCImpl2470 && "ParseObjCMethodDefinition - Method out of @implementation");2471 // Consume the tokens and store them for later parsing.2472 StashAwayMethodOrFunctionBodyTokens(MDecl);2473 return MDecl;2474}2475 2476StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc,2477 ParsedStmtContext StmtCtx) {2478 if (Tok.is(tok::code_completion)) {2479 cutOffParsing();2480 Actions.CodeCompletion().CodeCompleteObjCAtStatement(getCurScope());2481 return StmtError();2482 }2483 2484 if (Tok.isObjCAtKeyword(tok::objc_try))2485 return ParseObjCTryStmt(AtLoc);2486 2487 if (Tok.isObjCAtKeyword(tok::objc_throw))2488 return ParseObjCThrowStmt(AtLoc);2489 2490 if (Tok.isObjCAtKeyword(tok::objc_synchronized))2491 return ParseObjCSynchronizedStmt(AtLoc);2492 2493 if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))2494 return ParseObjCAutoreleasePoolStmt(AtLoc);2495 2496 if (Tok.isObjCAtKeyword(tok::objc_import) &&2497 getLangOpts().DebuggerSupport) {2498 SkipUntil(tok::semi);2499 return Actions.ActOnNullStmt(Tok.getLocation());2500 }2501 2502 ExprStatementTokLoc = AtLoc;2503 ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));2504 if (Res.isInvalid()) {2505 // If the expression is invalid, skip ahead to the next semicolon. Not2506 // doing this opens us up to the possibility of infinite loops if2507 // ParseExpression does not consume any tokens.2508 SkipUntil(tok::semi);2509 return StmtError();2510 }2511 2512 // Otherwise, eat the semicolon.2513 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);2514 return handleExprStmt(Res, StmtCtx);2515}2516 2517ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {2518 switch (Tok.getKind()) {2519 case tok::code_completion:2520 cutOffParsing();2521 Actions.CodeCompletion().CodeCompleteObjCAtExpression(getCurScope());2522 return ExprError();2523 2524 case tok::minus:2525 case tok::plus: {2526 tok::TokenKind Kind = Tok.getKind();2527 SourceLocation OpLoc = ConsumeToken();2528 2529 if (!Tok.is(tok::numeric_constant)) {2530 const char *Symbol = nullptr;2531 switch (Kind) {2532 case tok::minus: Symbol = "-"; break;2533 case tok::plus: Symbol = "+"; break;2534 default: llvm_unreachable("missing unary operator case");2535 }2536 Diag(Tok, diag::err_nsnumber_nonliteral_unary)2537 << Symbol;2538 return ExprError();2539 }2540 2541 ExprResult Lit(Actions.ActOnNumericConstant(Tok));2542 if (Lit.isInvalid()) {2543 return Lit;2544 }2545 ConsumeToken(); // Consume the literal token.2546 2547 Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());2548 if (Lit.isInvalid())2549 return Lit;2550 2551 return ParsePostfixExpressionSuffix(2552 Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()));2553 }2554 2555 case tok::string_literal: // primary-expression: string-literal2556 case tok::wide_string_literal:2557 return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));2558 2559 case tok::char_constant:2560 return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));2561 2562 case tok::numeric_constant:2563 return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));2564 2565 case tok::kw_true: // Objective-C++, etc.2566 case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes2567 return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));2568 case tok::kw_false: // Objective-C++, etc.2569 case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no2570 return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));2571 2572 case tok::l_square:2573 // Objective-C array literal2574 return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));2575 2576 case tok::l_brace:2577 // Objective-C dictionary literal2578 return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));2579 2580 case tok::l_paren:2581 // Objective-C boxed expression2582 return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));2583 2584 default:2585 if (Tok.getIdentifierInfo() == nullptr)2586 return ExprError(Diag(AtLoc, diag::err_unexpected_at));2587 2588 switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {2589 case tok::objc_encode:2590 return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));2591 case tok::objc_protocol:2592 return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));2593 case tok::objc_selector:2594 return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));2595 case tok::objc_available:2596 return ParseAvailabilityCheckExpr(AtLoc);2597 default: {2598 const char *str = nullptr;2599 // Only provide the @try/@finally/@autoreleasepool fixit when we're sure2600 // that this is a proper statement where such directives could actually2601 // occur.2602 if (GetLookAheadToken(1).is(tok::l_brace) &&2603 ExprStatementTokLoc == AtLoc) {2604 char ch = Tok.getIdentifierInfo()->getNameStart()[0];2605 str =2606 ch == 't' ? "try"2607 : (ch == 'f' ? "finally"2608 : (ch == 'a' ? "autoreleasepool" : nullptr));2609 }2610 if (str) {2611 SourceLocation kwLoc = Tok.getLocation();2612 return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<2613 FixItHint::CreateReplacement(kwLoc, str));2614 }2615 else2616 return ExprError(Diag(AtLoc, diag::err_unexpected_at));2617 }2618 }2619 }2620}2621 2622bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {2623 InMessageExpressionRAIIObject InMessage(*this, true);2624 2625 if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,2626 tok::annot_cxxscope))2627 TryAnnotateTypeOrScopeToken();2628 2629 if (!Tok.isSimpleTypeSpecifier(getLangOpts())) {2630 // objc-receiver:2631 // expression2632 ExprResult Receiver = ParseExpression();2633 if (Receiver.isInvalid())2634 return true;2635 2636 IsExpr = true;2637 TypeOrExpr = Receiver.get();2638 return false;2639 }2640 2641 // objc-receiver:2642 // typename-specifier2643 // simple-type-specifier2644 // expression (that starts with one of the above)2645 DeclSpec DS(AttrFactory);2646 ParseCXXSimpleTypeSpecifier(DS);2647 2648 if (Tok.is(tok::l_paren)) {2649 // If we see an opening parentheses at this point, we are2650 // actually parsing an expression that starts with a2651 // function-style cast, e.g.,2652 //2653 // postfix-expression:2654 // simple-type-specifier ( expression-list [opt] )2655 // typename-specifier ( expression-list [opt] )2656 //2657 // Parse the remainder of this case, then the (optional)2658 // postfix-expression suffix, followed by the (optional)2659 // right-hand side of the binary expression. We have an2660 // instance method.2661 ExprResult Receiver = ParseCXXTypeConstructExpression(DS);2662 if (!Receiver.isInvalid())2663 Receiver = ParsePostfixExpressionSuffix(Receiver.get());2664 if (!Receiver.isInvalid())2665 Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);2666 if (Receiver.isInvalid())2667 return true;2668 2669 IsExpr = true;2670 TypeOrExpr = Receiver.get();2671 return false;2672 }2673 2674 // We have a class message. Turn the simple-type-specifier or2675 // typename-specifier we parsed into a type and parse the2676 // remainder of the class message.2677 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),2678 DeclaratorContext::TypeName);2679 TypeResult Type = Actions.ActOnTypeName(DeclaratorInfo);2680 if (Type.isInvalid())2681 return true;2682 2683 IsExpr = false;2684 TypeOrExpr = Type.get().getAsOpaquePtr();2685 return false;2686}2687 2688bool Parser::isSimpleObjCMessageExpression() {2689 assert(Tok.is(tok::l_square) && getLangOpts().ObjC &&2690 "Incorrect start for isSimpleObjCMessageExpression");2691 return GetLookAheadToken(1).is(tok::identifier) &&2692 GetLookAheadToken(2).is(tok::identifier);2693}2694 2695bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {2696 if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) ||2697 InMessageExpression)2698 return false;2699 2700 TypeResult Type;2701 2702 if (Tok.is(tok::annot_typename))2703 Type = getTypeAnnotation(Tok);2704 else if (Tok.is(tok::identifier))2705 Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),2706 getCurScope());2707 else2708 return false;2709 2710 // FIXME: Should not be querying properties of types from the parser.2711 if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) {2712 const Token &AfterNext = GetLookAheadToken(2);2713 if (AfterNext.isOneOf(tok::colon, tok::r_square)) {2714 if (Tok.is(tok::identifier))2715 TryAnnotateTypeOrScopeToken();2716 2717 return Tok.is(tok::annot_typename);2718 }2719 }2720 2721 return false;2722}2723 2724ExprResult Parser::ParseObjCMessageExpression() {2725 assert(Tok.is(tok::l_square) && "'[' expected");2726 SourceLocation LBracLoc = ConsumeBracket(); // consume '['2727 2728 if (Tok.is(tok::code_completion)) {2729 cutOffParsing();2730 Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope());2731 return ExprError();2732 }2733 2734 InMessageExpressionRAIIObject InMessage(*this, true);2735 2736 if (getLangOpts().CPlusPlus) {2737 // We completely separate the C and C++ cases because C++ requires2738 // more complicated (read: slower) parsing.2739 2740 // Handle send to super.2741 // FIXME: This doesn't benefit from the same typo-correction we2742 // get in Objective-C.2743 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&2744 NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())2745 return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,2746 nullptr);2747 2748 // Parse the receiver, which is either a type or an expression.2749 bool IsExpr;2750 void *TypeOrExpr = nullptr;2751 if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {2752 SkipUntil(tok::r_square, StopAtSemi);2753 return ExprError();2754 }2755 2756 if (IsExpr)2757 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,2758 static_cast<Expr *>(TypeOrExpr));2759 2760 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),2761 ParsedType::getFromOpaquePtr(TypeOrExpr),2762 nullptr);2763 }2764 2765 if (Tok.is(tok::identifier)) {2766 IdentifierInfo *Name = Tok.getIdentifierInfo();2767 SourceLocation NameLoc = Tok.getLocation();2768 ParsedType ReceiverType;2769 switch (Actions.ObjC().getObjCMessageKind(2770 getCurScope(), Name, NameLoc, Name == Ident_super,2771 NextToken().is(tok::period), ReceiverType)) {2772 case SemaObjC::ObjCSuperMessage:2773 return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,2774 nullptr);2775 2776 case SemaObjC::ObjCClassMessage:2777 if (!ReceiverType) {2778 SkipUntil(tok::r_square, StopAtSemi);2779 return ExprError();2780 }2781 2782 ConsumeToken(); // the type name2783 2784 // Parse type arguments and protocol qualifiers.2785 if (Tok.is(tok::less)) {2786 SourceLocation NewEndLoc;2787 TypeResult NewReceiverType2788 = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType,2789 /*consumeLastToken=*/true,2790 NewEndLoc);2791 if (!NewReceiverType.isUsable()) {2792 SkipUntil(tok::r_square, StopAtSemi);2793 return ExprError();2794 }2795 2796 ReceiverType = NewReceiverType.get();2797 }2798 2799 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),2800 ReceiverType, nullptr);2801 2802 case SemaObjC::ObjCInstanceMessage:2803 // Fall through to parse an expression.2804 break;2805 }2806 }2807 2808 // Otherwise, an arbitrary expression can be the receiver of a send.2809 ExprResult Res = ParseExpression();2810 if (Res.isInvalid()) {2811 SkipUntil(tok::r_square, StopAtSemi);2812 return Res;2813 }2814 2815 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,2816 Res.get());2817}2818 2819ExprResult2820Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,2821 SourceLocation SuperLoc,2822 ParsedType ReceiverType,2823 Expr *ReceiverExpr) {2824 InMessageExpressionRAIIObject InMessage(*this, true);2825 2826 if (Tok.is(tok::code_completion)) {2827 cutOffParsing();2828 if (SuperLoc.isValid())2829 Actions.CodeCompletion().CodeCompleteObjCSuperMessage(2830 getCurScope(), SuperLoc, {}, false);2831 else if (ReceiverType)2832 Actions.CodeCompletion().CodeCompleteObjCClassMessage(2833 getCurScope(), ReceiverType, {}, false);2834 else2835 Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(2836 getCurScope(), ReceiverExpr, {}, false);2837 return ExprError();2838 }2839 2840 // Parse objc-selector2841 SourceLocation Loc;2842 IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);2843 2844 SmallVector<const IdentifierInfo *, 12> KeyIdents;2845 SmallVector<SourceLocation, 12> KeyLocs;2846 ExprVector KeyExprs;2847 2848 if (Tok.is(tok::colon)) {2849 while (true) {2850 // Each iteration parses a single keyword argument.2851 KeyIdents.push_back(selIdent);2852 KeyLocs.push_back(Loc);2853 2854 if (ExpectAndConsume(tok::colon)) {2855 // We must manually skip to a ']', otherwise the expression skipper will2856 // stop at the ']' when it skips to the ';'. We want it to skip beyond2857 // the enclosing expression.2858 SkipUntil(tok::r_square, StopAtSemi);2859 return ExprError();2860 }2861 2862 /// Parse the expression after ':'2863 2864 if (Tok.is(tok::code_completion)) {2865 cutOffParsing();2866 if (SuperLoc.isValid())2867 Actions.CodeCompletion().CodeCompleteObjCSuperMessage(2868 getCurScope(), SuperLoc, KeyIdents,2869 /*AtArgumentExpression=*/true);2870 else if (ReceiverType)2871 Actions.CodeCompletion().CodeCompleteObjCClassMessage(2872 getCurScope(), ReceiverType, KeyIdents,2873 /*AtArgumentExpression=*/true);2874 else2875 Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(2876 getCurScope(), ReceiverExpr, KeyIdents,2877 /*AtArgumentExpression=*/true);2878 2879 return ExprError();2880 }2881 2882 ExprResult Expr;2883 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {2884 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);2885 Expr = ParseBraceInitializer();2886 } else2887 Expr = ParseAssignmentExpression();2888 2889 ExprResult Res(Expr);2890 if (Res.isInvalid()) {2891 // We must manually skip to a ']', otherwise the expression skipper will2892 // stop at the ']' when it skips to the ';'. We want it to skip beyond2893 // the enclosing expression.2894 SkipUntil(tok::r_square, StopAtSemi);2895 return Res;2896 }2897 2898 // We have a valid expression.2899 KeyExprs.push_back(Res.get());2900 2901 // Code completion after each argument.2902 if (Tok.is(tok::code_completion)) {2903 cutOffParsing();2904 if (SuperLoc.isValid())2905 Actions.CodeCompletion().CodeCompleteObjCSuperMessage(2906 getCurScope(), SuperLoc, KeyIdents,2907 /*AtArgumentExpression=*/false);2908 else if (ReceiverType)2909 Actions.CodeCompletion().CodeCompleteObjCClassMessage(2910 getCurScope(), ReceiverType, KeyIdents,2911 /*AtArgumentExpression=*/false);2912 else2913 Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(2914 getCurScope(), ReceiverExpr, KeyIdents,2915 /*AtArgumentExpression=*/false);2916 return ExprError();2917 }2918 2919 // Check for another keyword selector.2920 selIdent = ParseObjCSelectorPiece(Loc);2921 if (!selIdent && Tok.isNot(tok::colon))2922 break;2923 // We have a selector or a colon, continue parsing.2924 }2925 // Parse the, optional, argument list, comma separated.2926 while (Tok.is(tok::comma)) {2927 SourceLocation commaLoc = ConsumeToken(); // Eat the ','.2928 /// Parse the expression after ','2929 ExprResult Res(ParseAssignmentExpression());2930 if (Res.isInvalid()) {2931 if (Tok.is(tok::colon)) {2932 Diag(commaLoc, diag::note_extra_comma_message_arg) <<2933 FixItHint::CreateRemoval(commaLoc);2934 }2935 // We must manually skip to a ']', otherwise the expression skipper will2936 // stop at the ']' when it skips to the ';'. We want it to skip beyond2937 // the enclosing expression.2938 SkipUntil(tok::r_square, StopAtSemi);2939 return Res;2940 }2941 2942 // We have a valid expression.2943 KeyExprs.push_back(Res.get());2944 }2945 } else if (!selIdent) {2946 Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.2947 2948 // We must manually skip to a ']', otherwise the expression skipper will2949 // stop at the ']' when it skips to the ';'. We want it to skip beyond2950 // the enclosing expression.2951 SkipUntil(tok::r_square, StopAtSemi);2952 return ExprError();2953 }2954 2955 if (Tok.isNot(tok::r_square)) {2956 Diag(Tok, diag::err_expected)2957 << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);2958 // We must manually skip to a ']', otherwise the expression skipper will2959 // stop at the ']' when it skips to the ';'. We want it to skip beyond2960 // the enclosing expression.2961 SkipUntil(tok::r_square, StopAtSemi);2962 return ExprError();2963 }2964 2965 SourceLocation RBracLoc = ConsumeBracket(); // consume ']'2966 2967 unsigned nKeys = KeyIdents.size();2968 if (nKeys == 0) {2969 KeyIdents.push_back(selIdent);2970 KeyLocs.push_back(Loc);2971 }2972 Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);2973 2974 if (SuperLoc.isValid())2975 return Actions.ObjC().ActOnSuperMessage(2976 getCurScope(), SuperLoc, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs);2977 else if (ReceiverType)2978 return Actions.ObjC().ActOnClassMessage(getCurScope(), ReceiverType, Sel,2979 LBracLoc, KeyLocs, RBracLoc,2980 KeyExprs);2981 return Actions.ObjC().ActOnInstanceMessage(2982 getCurScope(), ReceiverExpr, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs);2983}2984 2985ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {2986 ExprResult Res(ParseStringLiteralExpression());2987 if (Res.isInvalid()) return Res;2988 2989 // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string2990 // expressions. At this point, we know that the only valid thing that starts2991 // with '@' is an @"".2992 SmallVector<SourceLocation, 4> AtLocs;2993 ExprVector AtStrings;2994 AtLocs.push_back(AtLoc);2995 AtStrings.push_back(Res.get());2996 2997 while (Tok.is(tok::at)) {2998 AtLocs.push_back(ConsumeToken()); // eat the @.2999 3000 // Invalid unless there is a string literal.3001 if (!isTokenStringLiteral())3002 return ExprError(Diag(Tok, diag::err_objc_concat_string));3003 3004 ExprResult Lit(ParseStringLiteralExpression());3005 if (Lit.isInvalid())3006 return Lit;3007 3008 AtStrings.push_back(Lit.get());3009 }3010 3011 return Actions.ObjC().ParseObjCStringLiteral(AtLocs.data(), AtStrings);3012}3013 3014ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,3015 bool ArgValue) {3016 SourceLocation EndLoc = ConsumeToken(); // consume the keyword.3017 return Actions.ObjC().ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);3018}3019 3020ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {3021 ExprResult Lit(Actions.ActOnCharacterConstant(Tok));3022 if (Lit.isInvalid()) {3023 return Lit;3024 }3025 ConsumeToken(); // Consume the literal token.3026 return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get());3027}3028 3029ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {3030 ExprResult Lit(Actions.ActOnNumericConstant(Tok));3031 if (Lit.isInvalid()) {3032 return Lit;3033 }3034 ConsumeToken(); // Consume the literal token.3035 return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get());3036}3037 3038ExprResult3039Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {3040 if (Tok.isNot(tok::l_paren))3041 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");3042 3043 BalancedDelimiterTracker T(*this, tok::l_paren);3044 T.consumeOpen();3045 ExprResult ValueExpr(ParseAssignmentExpression());3046 if (T.consumeClose())3047 return ExprError();3048 3049 if (ValueExpr.isInvalid())3050 return ExprError();3051 3052 // Wrap the sub-expression in a parenthesized expression, to distinguish3053 // a boxed expression from a literal.3054 SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();3055 ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());3056 return Actions.ObjC().BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),3057 ValueExpr.get());3058}3059 3060ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {3061 ExprVector ElementExprs; // array elements.3062 ConsumeBracket(); // consume the l_square.3063 3064 bool HasInvalidEltExpr = false;3065 while (Tok.isNot(tok::r_square)) {3066 // Parse list of array element expressions (all must be id types).3067 ExprResult Res(ParseAssignmentExpression());3068 if (Res.isInvalid()) {3069 // We must manually skip to a ']', otherwise the expression skipper will3070 // stop at the ']' when it skips to the ';'. We want it to skip beyond3071 // the enclosing expression.3072 SkipUntil(tok::r_square, StopAtSemi);3073 return Res;3074 }3075 3076 // Parse the ellipsis that indicates a pack expansion.3077 if (Tok.is(tok::ellipsis))3078 Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());3079 if (Res.isInvalid())3080 HasInvalidEltExpr = true;3081 3082 ElementExprs.push_back(Res.get());3083 3084 if (Tok.is(tok::comma))3085 ConsumeToken(); // Eat the ','.3086 else if (Tok.isNot(tok::r_square))3087 return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square3088 << tok::comma);3089 }3090 SourceLocation EndLoc = ConsumeBracket(); // location of ']'3091 3092 if (HasInvalidEltExpr)3093 return ExprError();3094 3095 MultiExprArg Args(ElementExprs);3096 return Actions.ObjC().BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);3097}3098 3099ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {3100 SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.3101 ConsumeBrace(); // consume the l_square.3102 while (Tok.isNot(tok::r_brace)) {3103 // Parse the comma separated key : value expressions.3104 ExprResult KeyExpr;3105 {3106 ColonProtectionRAIIObject X(*this);3107 KeyExpr = ParseAssignmentExpression();3108 if (KeyExpr.isInvalid()) {3109 // We must manually skip to a '}', otherwise the expression skipper will3110 // stop at the '}' when it skips to the ';'. We want it to skip beyond3111 // the enclosing expression.3112 SkipUntil(tok::r_brace, StopAtSemi);3113 return KeyExpr;3114 }3115 }3116 3117 if (ExpectAndConsume(tok::colon)) {3118 SkipUntil(tok::r_brace, StopAtSemi);3119 return ExprError();3120 }3121 3122 ExprResult ValueExpr(ParseAssignmentExpression());3123 if (ValueExpr.isInvalid()) {3124 // We must manually skip to a '}', otherwise the expression skipper will3125 // stop at the '}' when it skips to the ';'. We want it to skip beyond3126 // the enclosing expression.3127 SkipUntil(tok::r_brace, StopAtSemi);3128 return ValueExpr;3129 }3130 3131 // Parse the ellipsis that designates this as a pack expansion. Do not3132 // ActOnPackExpansion here, leave it to template instantiation time where3133 // we can get better diagnostics.3134 SourceLocation EllipsisLoc;3135 if (getLangOpts().CPlusPlus)3136 TryConsumeToken(tok::ellipsis, EllipsisLoc);3137 3138 // We have a valid expression. Collect it in a vector so we can3139 // build the argument list.3140 ObjCDictionaryElement Element = {KeyExpr.get(), ValueExpr.get(),3141 EllipsisLoc, std::nullopt};3142 Elements.push_back(Element);3143 3144 if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))3145 return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace3146 << tok::comma);3147 }3148 SourceLocation EndLoc = ConsumeBrace();3149 3150 // Create the ObjCDictionaryLiteral.3151 return Actions.ObjC().BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),3152 Elements);3153}3154 3155ExprResult3156Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {3157 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");3158 3159 SourceLocation EncLoc = ConsumeToken();3160 3161 if (Tok.isNot(tok::l_paren))3162 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");3163 3164 BalancedDelimiterTracker T(*this, tok::l_paren);3165 T.consumeOpen();3166 3167 TypeResult Ty = ParseTypeName();3168 3169 T.consumeClose();3170 3171 if (Ty.isInvalid())3172 return ExprError();3173 3174 return Actions.ObjC().ParseObjCEncodeExpression(3175 AtLoc, EncLoc, T.getOpenLocation(), Ty.get(), T.getCloseLocation());3176}3177 3178ExprResult3179Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {3180 SourceLocation ProtoLoc = ConsumeToken();3181 3182 if (Tok.isNot(tok::l_paren))3183 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");3184 3185 BalancedDelimiterTracker T(*this, tok::l_paren);3186 T.consumeOpen();3187 3188 if (expectIdentifier())3189 return ExprError();3190 3191 IdentifierInfo *protocolId = Tok.getIdentifierInfo();3192 SourceLocation ProtoIdLoc = ConsumeToken();3193 3194 T.consumeClose();3195 3196 return Actions.ObjC().ParseObjCProtocolExpression(3197 protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), ProtoIdLoc,3198 T.getCloseLocation());3199}3200 3201ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {3202 SourceLocation SelectorLoc = ConsumeToken();3203 3204 if (Tok.isNot(tok::l_paren))3205 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");3206 3207 SmallVector<const IdentifierInfo *, 12> KeyIdents;3208 SourceLocation sLoc;3209 3210 BalancedDelimiterTracker T(*this, tok::l_paren);3211 T.consumeOpen();3212 bool HasOptionalParen = Tok.is(tok::l_paren);3213 if (HasOptionalParen)3214 ConsumeParen();3215 3216 if (Tok.is(tok::code_completion)) {3217 cutOffParsing();3218 Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), KeyIdents);3219 return ExprError();3220 }3221 3222 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);3223 if (!SelIdent && // missing selector name.3224 Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))3225 return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);3226 3227 KeyIdents.push_back(SelIdent);3228 3229 unsigned nColons = 0;3230 if (Tok.isNot(tok::r_paren)) {3231 while (true) {3232 if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.3233 ++nColons;3234 KeyIdents.push_back(nullptr);3235 } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.3236 return ExprError();3237 ++nColons;3238 3239 if (Tok.is(tok::r_paren))3240 break;3241 3242 if (Tok.is(tok::code_completion)) {3243 cutOffParsing();3244 Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(),3245 KeyIdents);3246 return ExprError();3247 }3248 3249 // Check for another keyword selector.3250 SourceLocation Loc;3251 SelIdent = ParseObjCSelectorPiece(Loc);3252 KeyIdents.push_back(SelIdent);3253 if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))3254 break;3255 }3256 }3257 if (HasOptionalParen && Tok.is(tok::r_paren))3258 ConsumeParen(); // ')'3259 T.consumeClose();3260 Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);3261 return Actions.ObjC().ParseObjCSelectorExpression(3262 Sel, AtLoc, SelectorLoc, T.getOpenLocation(), T.getCloseLocation(),3263 !HasOptionalParen);3264}3265 3266void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {3267 // MCDecl might be null due to error in method or c-function prototype, etc.3268 Decl *MCDecl = LM.D;3269 bool skip =3270 MCDecl && ((parseMethod && !Actions.ObjC().isObjCMethodDecl(MCDecl)) ||3271 (!parseMethod && Actions.ObjC().isObjCMethodDecl(MCDecl)));3272 if (skip)3273 return;3274 3275 // Save the current token position.3276 SourceLocation OrigLoc = Tok.getLocation();3277 3278 assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");3279 // Store an artificial EOF token to ensure that we don't run off the end of3280 // the method's body when we come to parse it.3281 Token Eof;3282 Eof.startToken();3283 Eof.setKind(tok::eof);3284 Eof.setEofData(MCDecl);3285 Eof.setLocation(OrigLoc);3286 LM.Toks.push_back(Eof);3287 // Append the current token at the end of the new token stream so that it3288 // doesn't get lost.3289 LM.Toks.push_back(Tok);3290 PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true);3291 3292 // Consume the previously pushed token.3293 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);3294 3295 assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&3296 "Inline objective-c method not starting with '{' or 'try' or ':'");3297 // Enter a scope for the method or c-function body.3298 ParseScope BodyScope(3299 this, (parseMethod ? Scope::ObjCMethodScope : Scope::NoScope) |3300 Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope);3301 Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);3302 3303 // Tell the actions module that we have entered a method or c-function definition3304 // with the specified Declarator for the method/function.3305 if (parseMethod)3306 Actions.ObjC().ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);3307 else3308 Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);3309 if (Tok.is(tok::kw_try))3310 ParseFunctionTryBlock(MCDecl, BodyScope);3311 else {3312 if (Tok.is(tok::colon))3313 ParseConstructorInitializer(MCDecl);3314 else3315 Actions.ActOnDefaultCtorInitializers(MCDecl);3316 ParseFunctionStatementBody(MCDecl, BodyScope);3317 }3318 3319 if (Tok.getLocation() != OrigLoc) {3320 // Due to parsing error, we either went over the cached tokens or3321 // there are still cached tokens left. If it's the latter case skip the3322 // leftover tokens.3323 // Since this is an uncommon situation that should be avoided, use the3324 // expensive isBeforeInTranslationUnit call.3325 if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),3326 OrigLoc))3327 while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))3328 ConsumeAnyToken();3329 }3330 // Clean up the remaining EOF token, only if it's inserted by us. Otherwise3331 // this might be code-completion token, which must be propagated to callers.3332 if (Tok.is(tok::eof) && Tok.getEofData() == MCDecl)3333 ConsumeAnyToken();3334}3335