From: Bruno Ricci Date: Mon, 25 Mar 2019 17:08:51 +0000 (+0000) Subject: [Sema][NFCI] Don't allocate storage for the various CorrectionCandidateCallback unles... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=62e8a2946b0928cb349cee4acb6fb64f950312f2;p=clang [Sema][NFCI] Don't allocate storage for the various CorrectionCandidateCallback unless we are going to do some typo correction The various CorrectionCandidateCallbacks are currently heap-allocated unconditionally. This was needed because of delayed typo correction. However these allocations represent currently 15.4% of all allocations (number of allocations) when parsing all of Boost (!), mostly because of ParseCastExpression, ParseStatementOrDeclarationAfterAttrtibutes and isCXXDeclarationSpecifier. Note that all of these callback objects are small. Let's not do this. Instead initially allocate the callback on the stack, and only do a heap allocation if we are going to do some typo correction. Do this by: 1. Adding a clone function to each callback, which will do a polymorphic clone of the callback. This clone function is required to be implemented by every callback (of which there is a fair amount). Make sure this is the case by making it pure virtual. 2. Use this clone function when we are going to try to correct a typo. This additionally cut the time of -fsyntax-only on all of Boost by 0.5% (not that much, but still something). No functional changes intended. Differential Revision: https://reviews.llvm.org/D58827 Reviewed By: rnk git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356925 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e8975dc834..d8f6c720b4 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -789,9 +789,8 @@ private: /// Annotation was successful. ANK_Success }; - AnnotatedNameKind - TryAnnotateName(bool IsAddressOfOperand, - std::unique_ptr CCC = nullptr); + AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = nullptr); /// Push a tok::annot_cxxscope token onto the token stream. void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index be084e2e84..376c376ed0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1914,11 +1914,11 @@ public: /// expression. /// /// \param CCC The correction callback, if typo correction is desired. - NameClassification - ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, - SourceLocation NameLoc, const Token &NextToken, - bool IsAddressOfOperand, - std::unique_ptr CCC = nullptr); + NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, + IdentifierInfo *&Name, SourceLocation NameLoc, + const Token &NextToken, + bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = nullptr); /// Describes the detailed kind of a template name. Used in diagnostics. enum class TemplateNameKindForDiagnostics { @@ -3266,7 +3266,7 @@ private: makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool ErrorRecovery); @@ -3350,7 +3350,7 @@ public: TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, bool EnteringContext = false, @@ -3360,7 +3360,7 @@ public: TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, @@ -4230,7 +4230,7 @@ public: ExprResult ActOnIdExpression( Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, - std::unique_ptr CCC = nullptr, + CorrectionCandidateCallback *CCC = nullptr, bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); void DecomposeUnqualifiedId(const UnqualifiedId &Id, @@ -4240,7 +4240,7 @@ public: bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, ArrayRef Args = None, TypoExpr **Out = nullptr); diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index da57d1bf67..b49a96c0b9 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -312,6 +312,13 @@ public: : InvalidDistance; } + /// Clone this CorrectionCandidateCallback. CorrectionCandidateCallbacks are + /// initially stack-allocated. However in case where delayed typo-correction + /// is done we need to move the callback to storage with a longer lifetime. + /// Every class deriving from CorrectionCandidateCallback must implement + /// this method. + virtual std::unique_ptr clone() = 0; + void setTypoName(IdentifierInfo *II) { Typo = II; } void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } @@ -342,14 +349,28 @@ protected: NestedNameSpecifier *TypoNNS; }; +class DefaultFilterCCC final : public CorrectionCandidateCallback { +public: + explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr, + NestedNameSpecifier *TypoNNS = nullptr) + : CorrectionCandidateCallback(Typo, TypoNNS) {} + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } +}; + /// Simple template class for restricting typo correction candidates /// to ones having a single Decl* of the given type. template -class DeclFilterCCC : public CorrectionCandidateCallback { +class DeclFilterCCC final : public CorrectionCandidateCallback { public: bool ValidateCandidate(const TypoCorrection &candidate) override { return candidate.getCorrectionDeclAs(); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; // Callback class to limit the allowed keywords and to only accept typo @@ -362,6 +383,9 @@ public: MemberExpr *ME = nullptr); bool ValidateCandidate(const TypoCorrection &candidate) override; + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } private: unsigned NumArgs; @@ -371,7 +395,7 @@ private: }; // Callback class that effectively disabled typo correction -class NoTypoCorrectionCCC : public CorrectionCandidateCallback { +class NoTypoCorrectionCCC final : public CorrectionCandidateCallback { public: NoTypoCorrectionCCC() { WantTypeSpecifiers = false; @@ -384,6 +408,9 @@ public: bool ValidateCandidate(const TypoCorrection &candidate) override { return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // namespace clang diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 556fce2188..688347bd2d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2854,7 +2854,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, IdentifierInfo *Name = AfterScope.getIdentifierInfo(); Sema::NameClassification Classification = Actions.ClassifyName( getCurScope(), SS, Name, AfterScope.getLocation(), Next, - /*IsAddressOfOperand*/false); + /*IsAddressOfOperand=*/false, /*CCC=*/nullptr); switch (Classification.getKind()) { case Sema::NC_Error: SkipMalformedDecl(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 575d32d8e7..4039df888a 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -543,7 +543,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } namespace { -class CastExpressionIdValidator : public CorrectionCandidateCallback { +class CastExpressionIdValidator final : public CorrectionCandidateCallback { public: CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes) : NextToken(Next), AllowNonTypes(AllowNonTypes) { @@ -572,6 +572,10 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Token NextToken; bool AllowNonTypes; @@ -1041,19 +1045,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, CXXScopeSpec ScopeSpec; SourceLocation TemplateKWLoc; Token Replacement; - auto Validator = llvm::make_unique( - Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); - Validator->IsAddressOfOperand = isAddressOfOperand; + CastExpressionIdValidator Validator( + /*Next=*/Tok, + /*AllowTypes=*/isTypeCast != NotTypeCast, + /*AllowNonTypes=*/isTypeCast != IsTypeCast); + Validator.IsAddressOfOperand = isAddressOfOperand; if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) { - Validator->WantExpressionKeywords = false; - Validator->WantRemainingKeywords = false; + Validator.WantExpressionKeywords = false; + Validator.WantRemainingKeywords = false; } else { - Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); + Validator.WantRemainingKeywords = Tok.isNot(tok::r_paren); } Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression( getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), - isAddressOfOperand, std::move(Validator), + isAddressOfOperand, &Validator, /*IsInlineAsmIdentifier=*/false, Tok.is(tok::r_paren) ? nullptr : &Replacement); if (!Res.isInvalid() && Res.isUnset()) { diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 94055d4045..c3094d6992 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -563,7 +563,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe ExprResult E = Actions.ActOnIdExpression( getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren), - isAddressOfOperand, nullptr, /*IsInlineAsmIdentifier=*/false, + isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false, &Replacement); if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less)) checkPotentialAngleBracket(E); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 2db31320ad..cee160565f 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -116,7 +116,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, } namespace { -class StatementFilterCCC : public CorrectionCandidateCallback { +class StatementFilterCCC final : public CorrectionCandidateCallback { public: StatementFilterCCC(Token nextTok) : NextToken(nextTok) { WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square, @@ -139,6 +139,10 @@ public: return CorrectionCandidateCallback::ValidateCandidate(candidate); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Token NextToken; }; @@ -181,9 +185,8 @@ Retry: if (Next.isNot(tok::coloncolon)) { // Try to limit which sets of keywords should be included in typo // correction based on what the next token is. - if (TryAnnotateName(/*IsAddressOfOperand*/ false, - llvm::make_unique(Next)) == - ANK_Error) { + StatementFilterCCC CCC(Next); + if (TryAnnotateName(/*IsAddressOfOperand*/ false, &CCC) == ANK_Error) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 81079cda94..d0549a9725 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1147,7 +1147,7 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { } namespace { -class TentativeParseCCC : public CorrectionCandidateCallback { +class TentativeParseCCC final : public CorrectionCandidateCallback { public: TentativeParseCCC(const Token &Next) { WantRemainingKeywords = false; @@ -1165,6 +1165,10 @@ public: return CorrectionCandidateCallback::ValidateCandidate(Candidate); } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration @@ -1293,8 +1297,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // a parse error one way or another. In that case, tell the caller that // this is ambiguous. Typo-correct to type and expression keywords and // to types and identifiers, in order to try to recover from errors. - switch (TryAnnotateName(false /* no nested name specifier */, - llvm::make_unique(Next))) { + TentativeParseCCC CCC(Next); + switch (TryAnnotateName(false /* no nested name specifier */, &CCC)) { case ANK_Error: return TPResult::Error; case ANK_TentativeDecl: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index fbda4eae90..9c8faae254 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1487,7 +1487,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { /// no typo correction will be performed. Parser::AnnotatedNameKind Parser::TryAnnotateName(bool IsAddressOfOperand, - std::unique_ptr CCC) { + CorrectionCandidateCallback *CCC) { assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); const bool EnteringContext = false; @@ -1523,9 +1523,9 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // after a scope specifier, because in general we can't recover from typos // there (eg, after correcting 'A::template B::C' [sic], we would need to // jump back into scope specifier parsing). - Sema::NameClassification Classification = Actions.ClassifyName( - getCurScope(), SS, Name, NameLoc, Next, IsAddressOfOperand, - SS.isEmpty() ? std::move(CCC) : nullptr); + Sema::NameClassification Classification = + Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, + IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr); switch (Classification.getKind()) { case Sema::NC_Error: diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 2370c41997..93912dae03 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -429,8 +429,9 @@ namespace { // Callback to only accept typo corrections that can be a valid C++ member // intializer: either a non-static field member or a base class. -class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback { - public: +class NestedNameSpecifierValidatorCCC final + : public CorrectionCandidateCallback { +public: explicit NestedNameSpecifierValidatorCCC(Sema &SRef) : SRef(SRef) {} @@ -438,6 +439,10 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback { return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl()); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Sema &SRef; }; @@ -614,9 +619,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, // different kind of error, so look for typos. DeclarationName Name = Found.getLookupName(); Found.clear(); + NestedNameSpecifierValidatorCCC CCC(*this); if (TypoCorrection Corrected = CorrectTypo( - Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, - llvm::make_unique(*this), + Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, CCC, CTK_ErrorRecovery, LookupCtx, EnteringContext)) { if (LookupCtx) { bool DroppedSpecifier = diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 08b61e1987..0946a24676 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -6407,8 +6407,9 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - ExprResult SuperExpr = - ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false); + ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, + /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), SelIdents, AtArgumentExpression); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4aa9dc25ac..92595f63f7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -61,7 +61,7 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { namespace { -class TypeNameValidatorCCC : public CorrectionCandidateCallback { +class TypeNameValidatorCCC final : public CorrectionCandidateCallback { public: TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, bool AllowTemplates = false, @@ -105,6 +105,10 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback { return !WantClassName && candidate.isKeyword(); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: bool AllowInvalidDecl; bool WantClassName; @@ -367,11 +371,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: if (CorrectedII) { - TypoCorrection Correction = - CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS, - llvm::make_unique( - true, isClassName, AllowDeducedTemplate), - CTK_ErrorRecovery); + TypeNameValidatorCCC CCC(/*AllowInvalid=*/true, isClassName, + AllowDeducedTemplate); + TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), Kind, + S, SS, CCC, CTK_ErrorRecovery); IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); TemplateTy Template; bool MemberOfUnknownSpecialization; @@ -664,11 +667,12 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, // There may have been a typo in the name of the type. Look up typo // results, in case we have something that we can suggest. + TypeNameValidatorCCC CCC(/*AllowInvalid=*/false, /*WantClass=*/false, + /*AllowTemplates=*/IsTemplateName, + /*AllowNonTemplates=*/!IsTemplateName); if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS, - llvm::make_unique( - false, false, IsTemplateName, !IsTemplateName), - CTK_ErrorRecovery)) { + CCC, CTK_ErrorRecovery)) { // FIXME: Support error recovery for the template-name case. bool CanRecover = !IsTemplateName; if (Corrected.isKeyword()) { @@ -843,8 +847,7 @@ static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS, Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, const Token &NextToken, - bool IsAddressOfOperand, - std::unique_ptr CCC) { + bool IsAddressOfOperand, CorrectionCandidateCallback *CCC) { DeclarationNameInfo NameInfo(Name, NameLoc); ObjCMethodDecl *CurMethod = getCurMethodDecl(); @@ -926,10 +929,9 @@ Corrected: // close to this name. if (!SecondTry && CCC) { SecondTry = true; - if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), - Result.getLookupKind(), S, - &SS, std::move(CCC), - CTK_ErrorRecovery)) { + if (TypoCorrection Corrected = + CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, + &SS, *CCC, CTK_ErrorRecovery)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; @@ -1865,10 +1867,10 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, if (!IDecl && DoTypoCorrection) { // Perform typo correction at the given location, but only if we // find an Objective-C class name. - if (TypoCorrection C = CorrectTypo( - DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, TUScope, nullptr, - llvm::make_unique>(), - CTK_ErrorRecovery)) { + DeclFilterCCC CCC{}; + if (TypoCorrection C = + CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, + TUScope, nullptr, CCC, CTK_ErrorRecovery)) { diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); IDecl = C.getCorrectionDeclAs(); Id = IDecl->getIdentifier(); @@ -7688,7 +7690,7 @@ namespace { // Callback to only accept typo corrections that have a non-zero edit distance. // Also only accept corrections that have the same parent decl. -class DifferentNameValidatorCCC : public CorrectionCandidateCallback { +class DifferentNameValidatorCCC final : public CorrectionCandidateCallback { public: DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD, CXXRecordDecl *Parent) @@ -7720,6 +7722,10 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback { return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: ASTContext &Context; FunctionDecl *OriginalFD; @@ -7767,6 +7773,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration( assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); CXXMethodDecl *MD = dyn_cast(NewFD); + DifferentNameValidatorCCC CCC(SemaRef.Context, NewFD, + MD ? MD->getParent() : nullptr); if (!Prev.empty()) { for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); Func != FuncEnd; ++Func) { @@ -7783,10 +7791,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration( // If the qualified name lookup yielded nothing, try typo correction } else if ((Correction = SemaRef.CorrectTypo( Prev.getLookupNameInfo(), Prev.getLookupKind(), S, - &ExtraArgs.D.getCXXScopeSpec(), - llvm::make_unique( - SemaRef.Context, NewFD, MD ? MD->getParent() : nullptr), - Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) { + &ExtraArgs.D.getCXXScopeSpec(), CCC, Sema::CTK_ErrorRecovery, + IsLocalFriend ? nullptr : NewDC))) { // Set up everything for the call to ActOnFunctionDeclarator ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(), ExtraArgs.D.getIdentifierLoc()); @@ -13538,10 +13544,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // function declaration is going to be treated as an error. if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) { TypoCorrection Corrected; - if (S && - (Corrected = CorrectTypo( - DeclarationNameInfo(&II, Loc), LookupOrdinaryName, S, nullptr, - llvm::make_unique>(), CTK_NonError))) + DeclFilterCCC CCC{}; + if (S && (Corrected = + CorrectTypo(DeclarationNameInfo(&II, Loc), LookupOrdinaryName, + S, nullptr, CCC, CTK_NonError))) diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion), /*ErrorRecovery*/false); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 55e176f4c7..9f9e117ab9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3781,7 +3781,7 @@ namespace { // Callback to only accept typo corrections that can be a valid C++ member // intializer: either a non-static field member or a base class. -class MemInitializerValidatorCCC : public CorrectionCandidateCallback { +class MemInitializerValidatorCCC final : public CorrectionCandidateCallback { public: explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) : ClassDecl(ClassDecl) {} @@ -3795,6 +3795,10 @@ public: return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: CXXRecordDecl *ClassDecl; }; @@ -3924,11 +3928,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // If no results were found, try to correct typos. TypoCorrection Corr; + MemInitializerValidatorCCC CCC(ClassDecl); if (R.empty() && BaseType.isNull() && - (Corr = CorrectTypo( - R.getLookupNameInfo(), R.getLookupKind(), S, &SS, - llvm::make_unique(ClassDecl), - CTK_ErrorRecovery, ClassDecl))) { + (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, + CCC, CTK_ErrorRecovery, ClassDecl))) { if (FieldDecl *Member = Corr.getCorrectionDeclAs()) { // We have found a non-static data member with a similar // name to what was typed; complain and initialize that @@ -9353,13 +9356,17 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { namespace { // Callback to only accept typo corrections that are namespaces. -class NamespaceValidatorCCC : public CorrectionCandidateCallback { +class NamespaceValidatorCCC final : public CorrectionCandidateCallback { public: bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) return isa(ND) || isa(ND); return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } @@ -9369,9 +9376,9 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, SourceLocation IdentLoc, IdentifierInfo *Ident) { R.clear(); + NamespaceValidatorCCC CCC{}; if (TypoCorrection Corrected = - S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, - llvm::make_unique(), + S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, CCC, Sema::CTK_ErrorRecovery)) { if (DeclContext *DC = S.computeDeclContext(SS, false)) { std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); @@ -9866,7 +9873,7 @@ static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived, } namespace { -class UsingValidatorCCC : public CorrectionCandidateCallback { +class UsingValidatorCCC final : public CorrectionCandidateCallback { public: UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf) @@ -9936,6 +9943,10 @@ public: return !HasTypenameKeyword; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: bool HasTypenameKeyword; bool IsInstantiation; @@ -10092,12 +10103,11 @@ NamedDecl *Sema::BuildUsingDeclaration( isa(LookupContext) && getSourceManager().isInSystemHeader(UsingLoc)) return nullptr; - if (TypoCorrection Corrected = CorrectTypo( - R.getLookupNameInfo(), R.getLookupKind(), S, &SS, - llvm::make_unique( - HasTypenameKeyword, IsInstantiation, SS.getScopeRep(), - dyn_cast(CurContext)), - CTK_ErrorRecovery)) { + UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(), + dyn_cast(CurContext)); + if (TypoCorrection Corrected = + CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC, + CTK_ErrorRecovery)) { // We reject candidates where DroppedSpecifier == true, hence the // literal '0' below. diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 76b2129211..7fa561012f 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -499,7 +499,7 @@ namespace { // Callback to only accept typo corrections that are Objective-C classes. // If an ObjCInterfaceDecl* is given to the constructor, then the validation // function will reject corrections to that class. -class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { +class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback { public: ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {} explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl) @@ -510,6 +510,10 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { return ID && !declaresSameEntity(ID, CurrentIDecl); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: ObjCInterfaceDecl *CurrentIDecl; }; @@ -549,11 +553,10 @@ ActOnSuperClassOfClassInterface(Scope *S, if (!PrevDecl) { // Try to correct for a typo in the superclass name without correcting // to the class we're defining. + ObjCInterfaceValidatorCCC CCC(IDecl); if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(SuperName, SuperLoc), - LookupOrdinaryName, TUScope, - nullptr, llvm::make_unique(IDecl), - CTK_ErrorRecovery)) { + DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, + TUScope, nullptr, CCC, CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) << SuperName << ClassName); PrevDecl = Corrected.getCorrectionDeclAs(); @@ -1292,11 +1295,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, for (const IdentifierLocPair &Pair : ProtocolId) { ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second); if (!PDecl) { + DeclFilterCCC CCC{}; TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(Pair.first, Pair.second), - LookupObjCProtocolName, TUScope, nullptr, - llvm::make_unique>(), - CTK_ErrorRecovery); + DeclarationNameInfo(Pair.first, Pair.second), LookupObjCProtocolName, + TUScope, nullptr, CCC, CTK_ErrorRecovery); if ((PDecl = Corrected.getCorrectionDeclAs())) diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) << Pair.first); @@ -1334,7 +1336,8 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, namespace { // Callback to only accept typo corrections that are either // Objective-C protocols or valid Objective-C type arguments. -class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback { +class ObjCTypeArgOrProtocolValidatorCCC final + : public CorrectionCandidateCallback { ASTContext &Context; Sema::LookupNameKind LookupKind; public: @@ -1381,6 +1384,10 @@ class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback { return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // end anonymous namespace @@ -1670,12 +1677,10 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( } // Perform typo correction on the name. - TypoCorrection corrected = CorrectTypo( - DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S, - nullptr, - llvm::make_unique(Context, - lookupKind), - CTK_ErrorRecovery); + ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind); + TypoCorrection corrected = + CorrectTypo(DeclarationNameInfo(identifiers[i], identifierLocs[i]), + lookupKind, S, nullptr, CCC, CTK_ErrorRecovery); if (corrected) { // Did we find a protocol? if (auto proto = corrected.getCorrectionDeclAs()) { @@ -1967,9 +1972,10 @@ Decl *Sema::ActOnStartClassImplementation( } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. - TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, - nullptr, llvm::make_unique(), CTK_NonError); + ObjCInterfaceValidatorCCC CCC{}; + TypoCorrection Corrected = + CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc), + LookupOrdinaryName, TUScope, nullptr, CCC, CTK_NonError); if (Corrected.getCorrectionDeclAs()) { // Suggest the (potentially) correct interface name. Don't provide a // code-modification hint or use the typo name for recovery, because diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3af87b6fd4..29b8bff947 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -911,8 +911,9 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, UnqualifiedId Name; Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), E->getBeginLoc()); - ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, - Name, true, false); + ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name, + /*HasTrailingLParen=*/true, + /*IsAddressOfOperand=*/false); if (TrapFn.isInvalid()) return ExprError(); @@ -1905,11 +1906,10 @@ static void emitEmptyLookupTypoDiagnostic( /// Diagnose an empty lookup. /// /// \return false if new lookup candidates were found -bool -Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - std::unique_ptr CCC, - TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef Args, TypoExpr **Out) { +bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectionCandidateCallback &CCC, + TemplateArgumentListInfo *ExplicitTemplateArgs, + ArrayRef Args, TypoExpr **Out) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -1998,7 +1998,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, assert(!ExplicitTemplateArgs && "Diagnosing an empty lookup with explicit template args!"); *Out = CorrectTypoDelayed( - R.getLookupNameInfo(), R.getLookupKind(), S, &SS, std::move(CCC), + R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC, [=](const TypoCorrection &TC) { emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args, diagnostic, diagnostic_suggest); @@ -2006,9 +2006,9 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, nullptr, CTK_ErrorRecovery); if (*Out) return true; - } else if (S && (Corrected = - CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, - &SS, std::move(CCC), CTK_ErrorRecovery))) { + } else if (S && + (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), + S, &SS, CCC, CTK_ErrorRecovery))) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr; @@ -2157,7 +2157,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, - std::unique_ptr CCC, + CorrectionCandidateCallback *CCC, bool IsInlineAsmIdentifier, Token *KeywordReplacement) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); @@ -2279,9 +2279,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // If this name wasn't predeclared and if this is not a function // call, diagnose the problem. TypoExpr *TE = nullptr; - auto DefaultValidator = llvm::make_unique( - II, SS.isValid() ? SS.getScopeRep() : nullptr); - DefaultValidator->IsAddressOfOperand = IsAddressOfOperand; + DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep() + : nullptr); + DefaultValidator.IsAddressOfOperand = IsAddressOfOperand; assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) && "Typo correction callback misconfigured"); if (CCC) { @@ -2293,9 +2293,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for // a template name, but we happen to have always already looked up the name // before we get here if it must be a template name. - if (DiagnoseEmptyLookup(S, SS, R, - CCC ? std::move(CCC) : std::move(DefaultValidator), - nullptr, None, &TE)) { + if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr, + None, &TE)) { if (TE && KeywordReplacement) { auto &State = getTypoExprState(TE); auto BestTC = State.Consumer->getNextCorrection(); @@ -2549,8 +2548,10 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam); CXXScopeSpec SelfScopeSpec; SourceLocation TemplateKWLoc; - ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, - SelfName, false, false); + ExprResult SelfExpr = + ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName, + /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); if (SelfExpr.isInvalid()) return ExprError(); @@ -4893,7 +4894,7 @@ Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto, } namespace { -class FunctionCallCCC : public FunctionCallFilterCCC { +class FunctionCallCCC final : public FunctionCallFilterCCC { public: FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName, unsigned NumArgs, MemberExpr *ME) @@ -4909,6 +4910,10 @@ public: return FunctionCallFilterCCC::ValidateCandidate(candidate); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: const IdentifierInfo *const FunctionName; }; @@ -4921,11 +4926,10 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn, DeclarationName FuncName = FDecl->getDeclName(); SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc(); + FunctionCallCCC CCC(S, FuncName.getAsIdentifierInfo(), Args.size(), ME); if (TypoCorrection Corrected = S.CorrectTypo( DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName, - S.getScopeForContext(S.CurContext), nullptr, - llvm::make_unique(S, FuncName.getAsIdentifierInfo(), - Args.size(), ME), + S.getScopeForContext(S.CurContext), nullptr, CCC, Sema::CTK_ErrorRecovery)) { if (NamedDecl *ND = Corrected.getFoundDecl()) { if (Corrected.isOverloaded()) { diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 2f9c8d6ee2..b07bba5584 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -590,7 +590,7 @@ namespace { // Callback to only accept typo corrections that are either a ValueDecl or a // FunctionTemplateDecl and are declared in the current record or, for a C++ // classes, one of its base classes. -class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { +class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { public: explicit RecordMemberExprValidatorCCC(const RecordType *RTy) : Record(RTy->getDecl()) { @@ -628,6 +628,10 @@ public: return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: const RecordDecl *const Record; }; @@ -696,9 +700,9 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, }; QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), R.redeclarationKind()}; + RecordMemberExprValidatorCCC CCC(RTy); TE = SemaRef.CorrectTypoDelayed( - R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, - llvm::make_unique(RTy), + R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC, [=, &SemaRef](const TypoCorrection &TC) { if (TC) { assert(!TC.isKeyword() && @@ -1331,11 +1335,11 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (!IV) { // Attempt to correct for typos in ivar names. - auto Validator = llvm::make_unique>(); - Validator->IsObjCIvarLookup = IsArrow; + DeclFilterCCC Validator{}; + Validator.IsObjCIvarLookup = IsArrow; if (TypoCorrection Corrected = S.CorrectTypo( R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr, - std::move(Validator), Sema::CTK_ErrorRecovery, IDecl)) { + Validator, Sema::CTK_ErrorRecovery, IDecl)) { IV = Corrected.getCorrectionDeclAs(); S.diagnoseTypo( Corrected, diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index d6c656e06b..818a981b49 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1946,11 +1946,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, } // Attempt to correct for typos in property names. - if (TypoCorrection Corrected = - CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc), - LookupOrdinaryName, nullptr, nullptr, - llvm::make_unique>(), - CTK_ErrorRecovery, IFace, false, OPT)) { + DeclFilterCCC CCC{}; + if (TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, + nullptr, nullptr, CCC, CTK_ErrorRecovery, IFace, false, OPT)) { DeclarationName TypoResult = Corrected.getCorrection(); if (TypoResult.isIdentifier() && TypoResult.getAsIdentifierInfo() == Member) { @@ -2107,7 +2106,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, namespace { -class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { +class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback { public: ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { // Determine whether "super" is acceptable in the current context. @@ -2119,6 +2118,10 @@ class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { return candidate.getCorrectionDeclAs() || candidate.isKeyword("super"); } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // end anonymous namespace @@ -2194,9 +2197,9 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, } } + ObjCInterfaceOrSuperCCC CCC(getCurMethodDecl()); if (TypoCorrection Corrected = CorrectTypo( - Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, - llvm::make_unique(getCurMethodDecl()), + Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC, CTK_ErrorRecovery, nullptr, false, nullptr, false)) { if (Corrected.isKeyword()) { // If we've found the keyword "super" (the only keyword that would be diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 090192e2ac..24786886da 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2208,7 +2208,7 @@ namespace { // Callback to only accept typo corrections that are for field members of // the given struct or union. -class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { +class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback { public: explicit FieldInitializerValidatorCCC(RecordDecl *RD) : Record(RD) {} @@ -2218,6 +2218,10 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: RecordDecl *Record; }; @@ -2420,10 +2424,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Name lookup didn't find anything. // Determine whether this was a typo for another field name. + FieldInitializerValidatorCCC CCC(RT->getDecl()); if (TypoCorrection Corrected = SemaRef.CorrectTypo( DeclarationNameInfo(FieldName, D->getFieldLoc()), - Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, - llvm::make_unique(RT->getDecl()), + Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, CCC, Sema::CTK_ErrorRecovery, RT->getDecl())) { SemaRef.diagnoseTypo( Corrected, diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 4ed9fdc359..5ec05b1ba0 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1079,8 +1079,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (R.empty()) { // FIXME: Disable corrections that would add qualification? CXXScopeSpec ScopeSpec; - if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, - llvm::make_unique>())) + DeclFilterCCC Validator{}; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) continue; } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 86960e0a1d..f27a9591dd 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -4572,8 +4572,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, std::unique_ptr Sema::makeTypoCorrectionConsumer( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool ErrorRecovery) { @@ -4635,9 +4634,13 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( TypoName.getBeginLoc()); } - CorrectionCandidateCallback &CCCRef = *CCC; + // Extend the lifetime of the callback. We delayed this until here + // to avoid allocations in the hot path (which is where no typo correction + // occurs). Note that CorrectionCandidateCallback is polymorphic and + // initially stack-allocated. + std::unique_ptr ClonedCCC = CCC.clone(); auto Consumer = llvm::make_unique( - *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, + *this, TypoName, LookupKind, S, SS, std::move(ClonedCCC), MemberContext, EnteringContext); // Perform name lookup to find visible, similarly-named entities. @@ -4689,7 +4692,9 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( } } - AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty()); + AddKeywordsToConsumer(*this, *Consumer, S, + *Consumer->getCorrectionValidator(), + SS && SS->isNotEmpty()); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. @@ -4743,19 +4748,18 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool RecordFailure) { - assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback"); - // Always let the ExternalSource have the first chance at correction, even // if we would otherwise have given up. if (ExternalSource) { - if (TypoCorrection Correction = ExternalSource->CorrectTypo( - TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT)) + if (TypoCorrection Correction = + ExternalSource->CorrectTypo(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, OPT)) return Correction; } @@ -4763,12 +4767,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for // some instances of CTC_Unknown, while WantRemainingKeywords is true // for CTC_Unknown but not for CTC_ObjCMessageReceiver. - bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords; + bool ObjCMessageReceiver = CCC.WantObjCSuper && !CCC.WantRemainingKeywords; IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); - auto Consumer = makeTypoCorrectionConsumer( - TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, Mode == CTK_ErrorRecovery); + auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, + OPT, Mode == CTK_ErrorRecovery); if (!Consumer) return TypoCorrection(); @@ -4878,16 +4882,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, /// needed. TypoExpr *Sema::CorrectTypoDelayed( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) { - assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback"); - - auto Consumer = makeTypoCorrectionConsumer( - TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, Mode == CTK_ErrorRecovery); + auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, + OPT, Mode == CTK_ErrorRecovery); // Give the external sema source a chance to correct the typo. TypoCorrection ExternalTypo; diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index f541d75ce5..dbccb69aad 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1955,6 +1955,11 @@ public: } return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + }; class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback { @@ -1972,6 +1977,10 @@ public: } return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // namespace @@ -1988,9 +1997,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, VarDecl *VD; if (!Lookup.isSingleResult()) { - if (TypoCorrection Corrected = CorrectTypo( - Id, LookupOrdinaryName, CurScope, nullptr, - llvm::make_unique(*this), CTK_ErrorRecovery)) { + VarDeclFilterCCC CCC(*this); + if (TypoCorrection Corrected = + CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC, + CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest @@ -14379,9 +14389,9 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, Lookup.suppressDiagnostics(); if (!Lookup.isSingleResult()) { + VarOrFuncDeclFilterCCC CCC(*this); if (TypoCorrection Corrected = - CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, - llvm::make_unique(*this), + CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC, CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) << Id.getName()); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2f6f94313b..eea9298a56 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11892,15 +11892,6 @@ public: } -static std::unique_ptr -MakeValidator(Sema &SemaRef, MemberExpr *ME, size_t NumArgs, - bool HasTemplateArgs, bool AllowTypoCorrection) { - if (!AllowTypoCorrection) - return llvm::make_unique(); - return llvm::make_unique(SemaRef, NumArgs, - HasTemplateArgs, ME); -} - /// Attempts to recover from a call where no functions were found. /// /// Returns true if new candidates were found. @@ -11935,16 +11926,22 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); bool DoDiagnoseEmptyLookup = EmptyLookup; - if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, - OverloadCandidateSet::CSK_Normal, - ExplicitTemplateArgs, Args, - &DoDiagnoseEmptyLookup) && - (!DoDiagnoseEmptyLookup || SemaRef.DiagnoseEmptyLookup( - S, SS, R, - MakeValidator(SemaRef, dyn_cast(Fn), Args.size(), - ExplicitTemplateArgs != nullptr, AllowTypoCorrection), - ExplicitTemplateArgs, Args))) - return ExprError(); + if (!DiagnoseTwoPhaseLookup( + SemaRef, Fn->getExprLoc(), SS, R, OverloadCandidateSet::CSK_Normal, + ExplicitTemplateArgs, Args, &DoDiagnoseEmptyLookup)) { + NoTypoCorrectionCCC NoTypoValidator{}; + FunctionCallFilterCCC FunctionCallValidator(SemaRef, Args.size(), + ExplicitTemplateArgs != nullptr, + dyn_cast(Fn)); + CorrectionCandidateCallback &Validator = + AllowTypoCorrection + ? static_cast(FunctionCallValidator) + : static_cast(NoTypoValidator); + if (!DoDiagnoseEmptyLookup || + SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs, + Args)) + return ExprError(); + } assert(!R.empty() && "lookup results empty despite recovery"); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 3f642b5c42..1010370838 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -410,14 +410,14 @@ bool Sema::LookupTemplateName(LookupResult &Found, DeclarationName Name = Found.getLookupName(); Found.clear(); // Simple filter callback that, for keywords, only accepts the C++ *_cast - auto FilterCCC = llvm::make_unique(); - FilterCCC->WantTypeSpecifiers = false; - FilterCCC->WantExpressionKeywords = false; - FilterCCC->WantRemainingKeywords = false; - FilterCCC->WantCXXNamedCasts = true; - if (TypoCorrection Corrected = CorrectTypo( - Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, - std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) { + DefaultFilterCCC FilterCCC{}; + FilterCCC.WantTypeSpecifiers = false; + FilterCCC.WantExpressionKeywords = false; + FilterCCC.WantRemainingKeywords = false; + FilterCCC.WantCXXNamedCasts = true; + if (TypoCorrection Corrected = + CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S, + &SS, FilterCCC, CTK_ErrorRecovery, LookupCtx)) { Found.setLookupName(Corrected.getCorrection()); if (auto *ND = Corrected.getFoundDecl()) Found.addDecl(ND); @@ -579,13 +579,16 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, return S.getAsTemplateNameDecl(ND); return Candidate.isKeyword(); } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; DeclarationName Name = NameInfo.getName(); - if (TypoCorrection Corrected = - CorrectTypo(NameInfo, LookupKind, S, &SS, - llvm::make_unique(*this), - CTK_ErrorRecovery, LookupCtx)) { + TemplateCandidateFilter CCC(*this); + if (TypoCorrection Corrected = CorrectTypo(NameInfo, LookupKind, S, &SS, CCC, + CTK_ErrorRecovery, LookupCtx)) { auto *ND = Corrected.getFoundDecl(); if (ND) ND = getAsTemplateNameDecl(ND); diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index faf90c093f..d06b7d49b4 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -924,12 +924,16 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { namespace { // Callback to only accept typo corrections that refer to parameter packs. -class ParameterPackValidatorCCC : public CorrectionCandidateCallback { +class ParameterPackValidatorCCC final : public CorrectionCandidateCallback { public: bool ValidateCandidate(const TypoCorrection &candidate) override { NamedDecl *ND = candidate.getCorrectionDecl(); return ND && ND->isParameterPack(); } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } @@ -965,18 +969,18 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, break; case LookupResult::NotFound: - case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::NotFoundInCurrentInstantiation: { + ParameterPackValidatorCCC CCC{}; if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, - llvm::make_unique(), - CTK_ErrorRecovery)) { + CCC, CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, PDiag(diag::note_parameter_pack_here)); ParameterPack = Corrected.getCorrectionDecl(); } break; - + } case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: break; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d4a6fc8ff6..d5516bc7a9 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -5913,7 +5913,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); ExprResult AddrSpace = S.ActOnIdExpression( - S.getCurScope(), SS, TemplateKWLoc, id, false, false); + S.getCurScope(), SS, TemplateKWLoc, id, /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); if (AddrSpace.isInvalid()) return; @@ -7043,7 +7044,8 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr, Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, - Id, false, false); + Id, /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); if (Size.isInvalid()) return; @@ -7080,7 +7082,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, - id, false, false); + id, /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); if (Size.isInvalid()) return;