r222549 - Use the full-Expr filter to disambiguate equidistant correction
Kaelyn Takata
rikka at google.com
Fri Nov 21 10:47:58 PST 2014
Author: rikka
Date: Fri Nov 21 12:47:58 2014
New Revision: 222549
URL: http://llvm.org/viewvc/llvm-project?rev=222549&view=rev
Log:
Use the full-Expr filter to disambiguate equidistant correction
candidates.
Modified:
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=222549&r1=222548&r2=222549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Nov 21 12:47:58 2014
@@ -5992,7 +5992,7 @@ class TransformTypos : public TreeTransf
typedef TreeTransform<TransformTypos> BaseTransform;
llvm::function_ref<ExprResult(Expr *)> ExprFilter;
- llvm::SmallSetVector<TypoExpr *, 2> TypoExprs;
+ llvm::SmallSetVector<TypoExpr *, 2> TypoExprs, AmbiguousTypoExprs;
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution;
@@ -6059,6 +6059,15 @@ class TransformTypos : public TreeTransf
return nullptr;
}
+ ExprResult TryTransform(Expr *E) {
+ Sema::SFINAETrap Trap(SemaRef);
+ ExprResult Res = TransformExpr(E);
+ if (Trap.hasErrorOccurred() || Res.isInvalid())
+ return ExprError();
+
+ return ExprFilter(Res.get());
+ }
+
public:
TransformTypos(Sema &SemaRef, llvm::function_ref<ExprResult(Expr *)> Filter)
: BaseTransform(SemaRef), ExprFilter(Filter) {}
@@ -6079,30 +6088,42 @@ public:
ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
ExprResult Transform(Expr *E) {
- ExprResult res;
- bool error = false;
+ ExprResult Res;
while (true) {
- Sema::SFINAETrap Trap(SemaRef);
- res = TransformExpr(E);
- error = Trap.hasErrorOccurred();
-
- if (!(error || res.isInvalid()))
- res = ExprFilter(res.get());
+ Res = TryTransform(E);
// Exit if either the transform was valid or if there were no TypoExprs
// to transform that still have any untried correction candidates..
- if (!(error || res.isInvalid()) ||
+ if (!Res.isInvalid() ||
!CheckAndAdvanceTypoExprCorrectionStreams())
break;
}
+ // Ensure none of the TypoExprs have multiple typo correction candidates
+ // with the same edit length that pass all the checks and filters.
+ // TODO: Properly handle various permutations of possible corrections when
+ // there is more than one potentially ambiguous typo correction.
+ while (!AmbiguousTypoExprs.empty()) {
+ auto TE = AmbiguousTypoExprs.back();
+ auto Cached = TransformCache[TE];
+ AmbiguousTypoExprs.pop_back();
+ TransformCache.erase(TE);
+ if (!TryTransform(E).isInvalid()) {
+ SemaRef.getTypoExprState(TE).Consumer->resetCorrectionStream();
+ TransformCache.erase(TE);
+ Res = ExprError();
+ break;
+ } else
+ TransformCache[TE] = Cached;
+ }
+
// Ensure that all of the TypoExprs within the current Expr have been found.
- if (!res.isUsable())
+ if (!Res.isUsable())
FindTypoExprs(TypoExprs).TraverseStmt(E);
EmitAllDiagnostics();
- return res;
+ return Res;
}
ExprResult TransformTypoExpr(TypoExpr *E) {
@@ -6124,21 +6145,15 @@ public:
State.RecoveryHandler(SemaRef, E, TC) :
attemptRecovery(SemaRef, *State.Consumer, TC);
if (!NE.isInvalid()) {
- // Check whether there is a second viable correction with the same edit
- // distance--in which case do not suggest anything since both are
- // equally good candidates for correcting the typo.
- Sema::SFINAETrap LocalTrap(SemaRef);
+ // Check whether there may be a second viable correction with the same
+ // edit distance; if so, remember this TypoExpr may have an ambiguous
+ // correction so it can be more thoroughly vetted later.
TypoCorrection Next;
- while ((Next = State.Consumer->peekNextCorrection()) &&
- Next.getEditDistance(false) == TC.getEditDistance(false)) {
- ExprResult Res =
- State.RecoveryHandler
- ? State.RecoveryHandler(SemaRef, E, Next)
- : attemptRecovery(SemaRef, *State.Consumer, Next);
- if (!Res.isInvalid()) {
- NE = ExprError();
- State.Consumer->getNextCorrection();
- }
+ if ((Next = State.Consumer->peekNextCorrection()) &&
+ Next.getEditDistance(false) == TC.getEditDistance(false)) {
+ AmbiguousTypoExprs.insert(E);
+ } else {
+ AmbiguousTypoExprs.remove(E);
}
assert(!NE.isUnset() &&
"Typo was transformed into a valid-but-null ExprResult");
Modified: cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp?rev=222549&r1=222548&r2=222549&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp Fri Nov 21 12:47:58 2014
@@ -48,3 +48,14 @@ void testNoCandidates() {
callee(xxxxxx, // expected-error-re {{use of undeclared identifier 'xxxxxx'{{$}}}}
zzzzzz); // expected-error-re {{use of undeclared identifier 'zzzzzz'{{$}}}}
}
+
+class string {};
+struct Item {
+ void Nest();
+ string text();
+ Item* next(); // expected-note {{'next' declared here}}
+};
+void testExprFilter(Item *i) {
+ Item *j;
+ j = i->Next(); // expected-error {{no member named 'Next' in 'Item'; did you mean 'next'?}}
+}
More information about the cfe-commits
mailing list