bool VolatileThis);
typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
+ typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
+ TypoRecoveryCallback;
private:
bool CppLookupName(LookupResult &R, Scope *S);
struct TypoExprState {
std::unique_ptr<TypoCorrectionConsumer> Consumer;
TypoDiagnosticGenerator DiagHandler;
+ TypoRecoveryCallback RecoveryHandler;
};
/// \brief The set of unhandled TypoExprs and their associated state.
/// \brief Creates a new TypoExpr AST node.
TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
- TypoDiagnosticGenerator TDG);
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC);
// \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
//
CXXScopeSpec *SS,
std::unique_ptr<CorrectionCandidateCallback> CCC,
TypoDiagnosticGenerator TDG,
- CorrectTypoKind Mode,
+ TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext = nullptr,
bool EnteringContext = false,
const ObjCObjectPointerType *OPT = nullptr);
#include "clang/AST/DeclCXX.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
// 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())
/// \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.
///
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
std::unique_ptr<CorrectionCandidateCallback> CCC,
- TypoDiagnosticGenerator TDG, CorrectTypoKind Mode,
+ TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
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) {
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
}
-TypoExpr *
-Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
- TypoDiagnosticGenerator TDG) {
+TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> 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;
}