Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -789,9 +789,8 @@ /// 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); Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1899,11 +1899,11 @@ /// 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 { @@ -3258,7 +3258,7 @@ 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); @@ -3342,7 +3342,7 @@ 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, @@ -3352,7 +3352,7 @@ 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, @@ -4223,7 +4223,7 @@ 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, @@ -4233,7 +4233,7 @@ bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, ArrayRef Args = None, TypoExpr **Out = nullptr); Index: include/clang/Sema/TypoCorrection.h =================================================================== --- include/clang/Sema/TypoCorrection.h +++ include/clang/Sema/TypoCorrection.h @@ -312,6 +312,13 @@ : 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 @@ 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 @@ 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 @@ }; // Callback class that effectively disabled typo correction -class NoTypoCorrectionCCC : public CorrectionCandidateCallback { +class NoTypoCorrectionCCC final : public CorrectionCandidateCallback { public: NoTypoCorrectionCCC() { WantTypeSpecifiers = false; @@ -384,6 +408,9 @@ bool ValidateCandidate(const TypoCorrection &candidate) override { return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // namespace clang Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2851,7 +2851,7 @@ 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(); Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -543,7 +543,7 @@ } 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 @@ return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Token NextToken; bool AllowNonTypes; @@ -1041,19 +1045,21 @@ 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()) { Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -563,7 +563,7 @@ 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); Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -116,7 +116,7 @@ } 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 @@ return CorrectionCandidateCallback::ValidateCandidate(candidate); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Token NextToken; }; @@ -181,9 +185,8 @@ 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); Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -1147,7 +1147,7 @@ } namespace { -class TentativeParseCCC : public CorrectionCandidateCallback { +class TentativeParseCCC final : public CorrectionCandidateCallback { public: TentativeParseCCC(const Token &Next) { WantRemainingKeywords = false; @@ -1165,6 +1165,10 @@ 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 @@ // 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: Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1487,7 +1487,7 @@ /// 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 @@ // 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: Index: lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- lib/Sema/SemaCXXScopeSpec.cpp +++ lib/Sema/SemaCXXScopeSpec.cpp @@ -429,8 +429,9 @@ // 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 @@ return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl()); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: Sema &SRef; }; @@ -614,9 +619,9 @@ // 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 = Index: lib/Sema/SemaCodeComplete.cpp =================================================================== --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -6387,8 +6387,9 @@ 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); } Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -61,7 +61,7 @@ namespace { -class TypeNameValidatorCCC : public CorrectionCandidateCallback { +class TypeNameValidatorCCC final : public CorrectionCandidateCallback { public: TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, bool AllowTemplates = false, @@ -105,6 +105,10 @@ return !WantClassName && candidate.isKeyword(); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: bool AllowInvalidDecl; bool WantClassName; @@ -367,11 +371,10 @@ 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 @@ // 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 @@ 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 @@ // 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 @@ 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(); @@ -7664,7 +7666,7 @@ // 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) @@ -7696,6 +7698,10 @@ return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: ASTContext &Context; FunctionDecl *OriginalFD; @@ -7743,6 +7749,8 @@ 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) { @@ -7759,10 +7767,8 @@ // 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()); @@ -13501,10 +13507,10 @@ // 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); } Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -3781,7 +3781,7 @@ // 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 @@ return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: CXXRecordDecl *ClassDecl; }; @@ -3924,11 +3928,10 @@ // 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 @@ 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 @@ 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 @@ } namespace { -class UsingValidatorCCC : public CorrectionCandidateCallback { +class UsingValidatorCCC final : public CorrectionCandidateCallback { public: UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf) @@ -9936,6 +9943,10 @@ return !HasTypenameKeyword; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: bool HasTypenameKeyword; bool IsInstantiation; @@ -10092,12 +10103,11 @@ 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) Index: lib/Sema/SemaDeclObjC.cpp =================================================================== --- lib/Sema/SemaDeclObjC.cpp +++ lib/Sema/SemaDeclObjC.cpp @@ -499,7 +499,7 @@ // 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 @@ return ID && !declaresSameEntity(ID, CurrentIDecl); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: ObjCInterfaceDecl *CurrentIDecl; }; @@ -549,11 +553,10 @@ 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 @@ 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 @@ 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 @@ return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // end anonymous namespace @@ -1670,12 +1677,10 @@ } // 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 @@ } 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 Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -922,8 +922,9 @@ 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(); @@ -1916,11 +1917,10 @@ /// 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; @@ -2009,7 +2009,7 @@ 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); @@ -2017,9 +2017,9 @@ 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; @@ -2168,7 +2168,7 @@ 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"); @@ -2290,9 +2290,9 @@ // 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) { @@ -2304,9 +2304,8 @@ // 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(); @@ -2560,8 +2559,10 @@ 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(); @@ -4899,7 +4900,7 @@ } namespace { -class FunctionCallCCC : public FunctionCallFilterCCC { +class FunctionCallCCC final : public FunctionCallFilterCCC { public: FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName, unsigned NumArgs, MemberExpr *ME) @@ -4915,6 +4916,10 @@ return FunctionCallFilterCCC::ValidateCandidate(candidate); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: const IdentifierInfo *const FunctionName; }; @@ -4927,11 +4932,10 @@ 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()) { Index: lib/Sema/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -590,7 +590,7 @@ // 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 @@ return false; } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: const RecordDecl *const Record; }; @@ -696,9 +700,9 @@ }; 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 @@ 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, Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -1921,11 +1921,10 @@ } // 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) { @@ -2082,7 +2081,7 @@ namespace { -class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { +class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback { public: ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { // Determine whether "super" is acceptable in the current context. @@ -2094,6 +2093,10 @@ return candidate.getCorrectionDeclAs() || candidate.isKeyword("super"); } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // end anonymous namespace @@ -2169,9 +2172,9 @@ } } + 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 Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -2208,7 +2208,7 @@ // 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 @@ return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); } + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + private: RecordDecl *Record; }; @@ -2420,10 +2424,10 @@ // 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, Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1079,8 +1079,8 @@ 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; } Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -4572,8 +4572,7 @@ 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 @@ 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 @@ } } - 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 @@ 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 @@ // 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 @@ /// 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; Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -1886,6 +1886,11 @@ } return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } + }; class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback { @@ -1902,6 +1907,10 @@ } return false; } + + std::unique_ptr clone() override { + return llvm::make_unique(*this); + } }; } // namespace @@ -1917,9 +1926,10 @@ 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 @@ -14053,9 +14063,9 @@ 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()); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -11905,15 +11905,6 @@ } -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. @@ -11948,16 +11939,22 @@ 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"); Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -410,14 +410,14 @@ 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 @@ 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); Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -924,12 +924,16 @@ 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 @@ 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; Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -5908,7 +5908,8 @@ 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; @@ -7040,7 +7041,8 @@ 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; @@ -7077,7 +7079,8 @@ 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;