summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaelyn Takata <rikka@google.com>2015-01-27 22:01:39 +0000
committerKaelyn Takata <rikka@google.com>2015-01-27 22:01:39 +0000
commit7a503694febda8648e39417ba9039e3adeed5e36 (patch)
tree24fe377dfc277e6b0b601debe2038f235b5a2017
parent1ac935652407c3042e3cf23614b6da5d188bff70 (diff)
downloadbcm5719-llvm-7a503694febda8648e39417ba9039e3adeed5e36.tar.gz
bcm5719-llvm-7a503694febda8648e39417ba9039e3adeed5e36.zip
Fix a think-o in handling ambiguous corrections for a TypoExpr.
Under certain circumstances, the identifier mentioned in the diagnostic won't match the intended correction even though the replacement expression and the note pointing to the decl are both correct. Basically, the TreeTransform assumes the TypoExpr's Consumer points to the correct TypoCorrection, but the handling of typos that appear to be ambiguous from the point of view of TransformTypoExpr would cause that assumption to be violated by altering the Consumer's correction stream. This fix allows the Consumer's correction stream to be reset to the right TypoCorrection after successfully resolving the percieved ambiguity. Included is a fix to suppress correcting the RHS of an assignment to the LHS of that assignment for non-C++ code, to prevent a regression in test/SemaObjC/provisional-ivar-lookup.m. This fixes PR22297. llvm-svn: 227251
-rw-r--r--clang/include/clang/Sema/SemaInternal.h14
-rw-r--r--clang/lib/Sema/SemaExpr.cpp20
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp11
-rw-r--r--clang/test/SemaCXX/typo-correction-delayed.cpp10
4 files changed, 49 insertions, 6 deletions
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 045bacf2136..005d882c341 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -101,7 +101,7 @@ public:
DeclContext *MemberContext,
bool EnteringContext)
: Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
- SemaRef(SemaRef), S(S),
+ SavedTCIndex(0), SemaRef(SemaRef), S(S),
SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr),
CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
Result(SemaRef, TypoName, LookupKind),
@@ -187,6 +187,17 @@ public:
CurrentTCIndex >= ValidatedCorrections.size();
}
+ /// \brief Save the current position in the correction stream (overwriting any
+ /// previously saved position).
+ void saveCurrentPosition() {
+ SavedTCIndex = CurrentTCIndex;
+ }
+
+ /// \brief Restore the saved position in the correction stream.
+ void restoreSavedPosition() {
+ CurrentTCIndex = SavedTCIndex;
+ }
+
ASTContext &getContext() const { return SemaRef.Context; }
const LookupResult &getLookupResult() const { return Result; }
@@ -267,6 +278,7 @@ private:
SmallVector<TypoCorrection, 4> ValidatedCorrections;
size_t CurrentTCIndex;
+ size_t SavedTCIndex;
Sema &SemaRef;
Scope *S;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2b507141e97..e75daa412fb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9459,6 +9459,18 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
}
}
+static NamedDecl *getDeclFromExpr(Expr *E) {
+ if (!E)
+ return nullptr;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getDecl();
+ if (auto *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ if (auto *IRE = dyn_cast<ObjCIvarRefExpr>(E))
+ return IRE->getDecl();
+ return nullptr;
+}
+
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
@@ -9496,7 +9508,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
LHS = CorrectDelayedTyposInExpr(LHSExpr);
- RHS = CorrectDelayedTyposInExpr(RHSExpr);
+ RHS = CorrectDelayedTyposInExpr(RHSExpr, [Opc, LHS](Expr *E) {
+ if (Opc != BO_Assign)
+ return ExprResult(E);
+ // Avoid correcting the RHS to the same Expr as the LHS.
+ Decl *D = getDeclFromExpr(E);
+ return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
+ });
if (!LHS.isUsable() || !RHS.isUsable())
return ExprError();
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bf4ab267a41..9477c7f2f9e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6165,15 +6165,18 @@ public:
while (!AmbiguousTypoExprs.empty()) {
auto TE = AmbiguousTypoExprs.back();
auto Cached = TransformCache[TE];
- AmbiguousTypoExprs.pop_back();
+ auto &State = SemaRef.getTypoExprState(TE);
+ State.Consumer->saveCurrentPosition();
TransformCache.erase(TE);
if (!TryTransform(E).isInvalid()) {
- SemaRef.getTypoExprState(TE).Consumer->resetCorrectionStream();
+ State.Consumer->resetCorrectionStream();
TransformCache.erase(TE);
Res = ExprError();
break;
- } else
- TransformCache[TE] = Cached;
+ }
+ AmbiguousTypoExprs.remove(TE);
+ State.Consumer->restoreSavedPosition();
+ TransformCache[TE] = Cached;
}
// Ensure that all of the TypoExprs within the current Expr have been found.
diff --git a/clang/test/SemaCXX/typo-correction-delayed.cpp b/clang/test/SemaCXX/typo-correction-delayed.cpp
index f09dd330dbb..516b600f422 100644
--- a/clang/test/SemaCXX/typo-correction-delayed.cpp
+++ b/clang/test/SemaCXX/typo-correction-delayed.cpp
@@ -175,3 +175,13 @@ namespace PR22250 {
// expected-error@+1 {{expected ';' after top level declarator}}
int getenv_s(size_t *y, char(&z)) {}
}
+
+namespace PR22297 {
+double pow(double x, double y);
+struct TimeTicks {
+ static void Now(); // expected-note {{'Now' declared here}}
+};
+void f() {
+ TimeTicks::now(); // expected-error {{no member named 'now' in 'PR22297::TimeTicks'; did you mean 'Now'?}}
+}
+}
OpenPOWER on IntegriCloud