Also keep track of the stack of Exprs visited during the tree transform
so the callback can be passed the parent of the TypoExpr.
---
 include/clang/Sema/Sema.h           |  8 ++++++--
 include/clang/Sema/TypoCorrection.h |  8 ++++++++
 lib/Sema/SemaExprCXX.cpp            | 19 ++++++++++++-------
 lib/Sema/SemaLookup.cpp             | 12 +++++++-----
 4 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 74d5cde..8228396 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -171,6 +171,7 @@ namespace clang {
   class TypeLoc;
   class TypoCorrectionConsumer;
   class TypoDiagnosticGenerator;
+  class TypoRecoveryCallback;
   class UnqualifiedId;
   class UnresolvedLookupExpr;
   class UnresolvedMemberExpr;
@@ -2573,6 +2574,7 @@ private:
   struct TypoExprState {
     std::unique_ptr<TypoCorrectionConsumer> Consumer;
     std::unique_ptr<TypoDiagnosticGenerator> DiagHandler;
+    std::unique_ptr<TypoRecoveryCallback> RecoveryHandler;
   };
 
   /// \brief The set of unhandled TypoExprs and their associated state.
@@ -2580,7 +2582,8 @@ private:
 
   /// \brief Creates a new TypoExpr AST node.
   TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
-                              std::unique_ptr<TypoDiagnosticGenerator> TDG);
+                              std::unique_ptr<TypoDiagnosticGenerator> TDG,
+                              std::unique_ptr<TypoRecoveryCallback> TRC);
 
   // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
   //
@@ -2690,7 +2693,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 541ae48..b06c0d2 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()(const TypoCorrection &TC) = 0;
   virtual ~TypoDiagnosticGenerator() = default;
 };
+
+class TypoRecoveryCallback {
+public:
+  virtual ExprResult operator()(Sema &SemaRef, TypoExpr *TE,
+                                TypoCorrection TC) = 0;
+  virtual ~TypoRecoveryCallback() = default;
+};
 }
 
 #endif
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4d2b727..682ec0a 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -5989,13 +5989,18 @@ 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());
-      return TransformCache[E] =
-                 SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
+      if (!State.RecoveryHandler) {
+        LookupResult R(SemaRef,
+                       State.Consumer->getLookupResult().getLookupNameInfo(),
+                       State.Consumer->getLookupResult().getLookupKind());
+        if (!TC.isKeyword())
+          R.addDecl(TC.getCorrectionDecl());
+        return TransformCache[E] =
+                   SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
+      }
+      ExprResult NE = (*State.RecoveryHandler)(SemaRef, E, TC);
+      if (!NE.isInvalid())
+        return TransformCache[E] = NE;
     }
     return TransformCache[E] = ExprError();
   }
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 0a1930a..c192ade 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -4334,7 +4334,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");
@@ -4359,7 +4360,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) {
@@ -4559,14 +4560,15 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
       << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
 }
 
-TypoExpr *
-Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
-                        std::unique_ptr<TypoDiagnosticGenerator> TDG) {
+TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
+                                  std::unique_ptr<TypoDiagnosticGenerator> TDG,
+                                  std::unique_ptr<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;
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to