diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8664d23da76a..ebcc4808b7c3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2592,6 +2592,8 @@ public: bool VolatileThis); typedef std::function TypoDiagnosticGenerator; + typedef std::function + TypoRecoveryCallback; private: bool CppLookupName(LookupResult &R, Scope *S); @@ -2599,6 +2601,7 @@ private: struct TypoExprState { std::unique_ptr Consumer; TypoDiagnosticGenerator DiagHandler; + TypoRecoveryCallback RecoveryHandler; }; /// \brief The set of unhandled TypoExprs and their associated state. @@ -2606,7 +2609,8 @@ private: /// \brief Creates a new TypoExpr AST node. TypoExpr *createDelayedTypo(std::unique_ptr TCC, - TypoDiagnosticGenerator TDG); + TypoDiagnosticGenerator TDG, + TypoRecoveryCallback TRC); // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls. // @@ -2718,7 +2722,7 @@ public: CXXScopeSpec *SS, std::unique_ptr CCC, TypoDiagnosticGenerator TDG, - CorrectTypoKind Mode, + TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr); diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index e5c49124c61d..12f7f06d5c94 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Ownership.h" #include "llvm/ADT/SmallVector.h" namespace clang { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 861fb068e7d2..1d9df2d4d453 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5996,13 +5996,17 @@ public: // For the first TypoExpr and an uncached TypoExpr, find the next likely // typo correction and return it. while (TypoCorrection TC = State.Consumer->getNextCorrection()) { - LookupResult R(SemaRef, - State.Consumer->getLookupResult().getLookupNameInfo(), - State.Consumer->getLookupResult().getLookupKind()); - if (!TC.isKeyword()) - R.addDecl(TC.getCorrectionDecl()); - ExprResult NE = - SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false); + ExprResult NE; + if (State.RecoveryHandler) { + NE = State.RecoveryHandler(SemaRef, E, TC); + } else { + LookupResult R(SemaRef, + State.Consumer->getLookupResult().getLookupNameInfo(), + State.Consumer->getLookupResult().getLookupKind()); + if (!TC.isKeyword()) + R.addDecl(TC.getCorrectionDecl()); + NE = SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false); + } assert(!NE.isUnset() && "Typo was transformed into a valid-but-null ExprResult"); if (!NE.isInvalid()) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index afb56fe99685..eab819e15fc4 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4332,6 +4332,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, /// \param TDG A TypoDiagnosticGenerator functor that will be used to print /// diagnostics when the actual typo correction is attempted. /// +/// \param TRC A TypoRecoveryCallback functor that will be used to build an +/// Expr from a typo correction candidate. +/// /// \param MemberContext if non-NULL, the context in which to look for /// a member access expression. /// @@ -4350,7 +4353,7 @@ TypoExpr *Sema::CorrectTypoDelayed( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, std::unique_ptr CCC, - TypoDiagnosticGenerator TDG, CorrectTypoKind Mode, + TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) { assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback"); @@ -4375,7 +4378,7 @@ TypoExpr *Sema::CorrectTypoDelayed( return nullptr; ExprEvalContexts.back().NumTypos++; - return createDelayedTypo(std::move(Consumer), std::move(TDG)); + return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC)); } void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { @@ -4575,14 +4578,15 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); } -TypoExpr * -Sema::createDelayedTypo(std::unique_ptr TCC, - TypoDiagnosticGenerator TDG) { +TypoExpr *Sema::createDelayedTypo(std::unique_ptr TCC, + TypoDiagnosticGenerator TDG, + TypoRecoveryCallback TRC) { assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer"); auto TE = new (Context) TypoExpr(Context.DependentTy); auto &State = DelayedTypos[TE]; State.Consumer = std::move(TCC); State.DiagHandler = std::move(TDG); + State.RecoveryHandler = std::move(TRC); return TE; }