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