---
 include/clang/AST/Expr.h            |  5 ++++-
 include/clang/Sema/Sema.h           |  3 ++-
 include/clang/Sema/TypoCorrection.h |  8 ++++++++
 lib/Sema/SemaExprCXX.cpp            | 24 ++++++++++++++++--------
 lib/Sema/SemaLookup.cpp             | 13 +++++++++----
 5 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 23d0a31..9af222d 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -4833,13 +4833,15 @@ public:
 
 class TypoCorrectionConsumer;
 class TypoDiagnosticGenerator;
+class TypoRecoveryCallback;
 
 /// TypoExpr - Internal placeholder for expressions where typo correction
 /// still needs to be performed and/or an error diagnostic emitted.
 class TypoExpr : public Expr {
 public:
   TypoExpr(std::unique_ptr<TypoCorrectionConsumer> TCC,
-           std::unique_ptr<TypoDiagnosticGenerator> TDG);
+           std::unique_ptr<TypoDiagnosticGenerator> TDG,
+           std::unique_ptr<TypoRecoveryCallback> TRC);
   child_range children() { return child_range(); }
   SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
   SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
@@ -4849,6 +4851,7 @@ public:
 
   std::unique_ptr<TypoCorrectionConsumer> Consumer;
   std::unique_ptr<TypoDiagnosticGenerator> DiagHandler;
+  std::unique_ptr<TypoRecoveryCallback> RecoveryHandler;
 };
 }  // end namespace clang
 
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 2f5589d..1b11460 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2667,7 +2667,8 @@ public:
       const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
       Scope *S, CXXScopeSpec *SS,
       std::unique_ptr<CorrectionCandidateCallback> CCC,
-      std::unique_ptr<TypoDiagnosticGenerator> TDG, CorrectTypoKind Mode,
+      std::unique_ptr<TypoDiagnosticGenerator> TDG,
+      std::unique_ptr<TypoRecoveryCallback> TRC, CorrectTypoKind Mode,
       DeclContext *MemberContext = nullptr, bool EnteringContext = false,
       const ObjCObjectPointerType *OPT = nullptr);
 
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index 135b187..ed5ce65 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/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 {
@@ -360,6 +361,13 @@ class TypoDiagnosticGenerator {
   virtual void operator()(TypoCorrection &TC) = 0;
   virtual ~TypoDiagnosticGenerator() = default;
 };
+
+class TypoRecoveryCallback {
+public:
+  virtual ExprResult operator()(Sema &SemaRef, TypoExpr *TE, TypoCorrection &TC,
+                                Expr *Parent) = 0;
+  virtual ~TypoRecoveryCallback() = default;
+};
 }
 
 #endif
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 9dc0e01..c05fc87 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -6001,16 +6001,24 @@ public:
       return TransformCache[E];
     }
 
+    Expr *Parent =
+        ExprStack.size() > 1 ? ExprStack[ExprStack.size() - 2] : nullptr;
+
     // For the first TypoExpr and an uncached TypoExpr, find the next likely
     // typo correction and return it.
-    while (TypoCorrection TC = E->Consumer->getNextCorrection()) {
-      LookupResult R(SemaRef,
-                     E->Consumer->getLookupResult().getLookupNameInfo(),
-                     E->Consumer->getLookupResult().getLookupKind());
-      if (!TC.isKeyword())
-        R.addDecl(TC.getCorrectionDecl());
-      return TransformCache[E] =
-                 SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
+    while (TypoCorrection &TC = E->Consumer->getNextCorrection()) {
+      if (!E->RecoveryHandler) {
+        LookupResult R(SemaRef,
+                       E->Consumer->getLookupResult().getLookupNameInfo(),
+                       E->Consumer->getLookupResult().getLookupKind());
+        if (!TC.isKeyword())
+          R.addDecl(TC.getCorrectionDecl());
+        return TransformCache[E] =
+                   SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
+      }
+      ExprResult NE = (*E->RecoveryHandler)(SemaRef, E, TC, Parent);
+      if (!NE.isInvalid())
+        return TransformCache[E] = NE;
     }
     return TransformCache[E] = ExprError();
   }
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 5be0e1b..94ede79 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -4352,7 +4352,8 @@ TypoExpr *Sema::CorrectTypoDelayed(
     const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
     Scope *S, CXXScopeSpec *SS,
     std::unique_ptr<CorrectionCandidateCallback> CCC,
-    std::unique_ptr<TypoDiagnosticGenerator> TDG, CorrectTypoKind Mode,
+    std::unique_ptr<TypoDiagnosticGenerator> TDG,
+    std::unique_ptr<TypoRecoveryCallback> TRC, CorrectTypoKind Mode,
     DeclContext *MemberContext, bool EnteringContext,
     const ObjCObjectPointerType *OPT) {
   assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
@@ -4376,7 +4377,8 @@ TypoExpr *Sema::CorrectTypoDelayed(
     return nullptr;
 
   ExprEvalContexts.back().NumTypos++;
-  return new (Context) TypoExpr(std::move(Consumer), std::move(TDG));
+  return new (Context)
+      TypoExpr(std::move(Consumer), std::move(TDG), std::move(TRC));
 }
 
 void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@@ -4582,17 +4584,20 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
 }
 
 TypoExpr::TypoExpr(std::unique_ptr<TypoCorrectionConsumer> TCC,
-                   std::unique_ptr<TypoDiagnosticGenerator> TDG)
+                   std::unique_ptr<TypoDiagnosticGenerator> TDG,
+                   std::unique_ptr<TypoRecoveryCallback> TRC)
     : Expr(TypoExprClass, TCC->getContext().DependentTy, VK_LValue, OK_Ordinary,
            /*isTypeDependent*/ true,
            /*isValueDependent*/ true,
            /*isInstantiationDependent*/ true,
            /*containsUnexpandedParameterPack*/ false),
-      Consumer(std::move(TCC)), DiagHandler(std::move(TDG)) {
+      Consumer(std::move(TCC)), DiagHandler(std::move(TDG)),
+      RecoveryHandler(std::move(TRC)) {
   assert(Consumer && "TypoExpr requires a valid TypoCorrectionConsumer");
 }
 
 void TypoExpr::clear() {
   Consumer.reset(nullptr);
   DiagHandler.reset(nullptr);
+  RecoveryHandler.reset(nullptr);
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to