aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaelyn Uhrain <rikka@google.com>2012-02-16 22:40:59 +0000
committerKaelyn Uhrain <rikka@google.com>2012-02-16 22:40:59 +0000
commit3336353578a02eb7dc35926c2440577993196e36 (patch)
treee02b41d04d084323bf1b8e569ab7fd46e3bdefb9
parentad901a6cf3c57d7dd3d7b400835440992e99cff8 (diff)
Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration.
Don't try to typo-correct a method redeclaration to declarations not in the current record as it could lead to infinite recursion if CorrectTypo finds more than one correction candidate in a parent record. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150735 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp20
-rw-r--r--test/SemaCXX/typo-correction.cpp10
2 files changed, 28 insertions, 2 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 64a67d9a64..796d2a2bb3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4439,11 +4439,26 @@ namespace {
namespace {
// Callback to only accept typo corrections that have a non-zero edit distance.
+// Also only accept corrections that have the same parent decl.
class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
public:
+ DifferentNameValidatorCCC(CXXRecordDecl *Parent)
+ : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
+
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- return candidate.getEditDistance() > 0;
+ if (candidate.getEditDistance() == 0)
+ return false;
+
+ if (CXXMethodDecl *MD = candidate.getCorrectionDeclAs<CXXMethodDecl>()) {
+ CXXRecordDecl *Parent = MD->getParent();
+ return Parent && Parent->getCanonicalDecl() == ExpectedParent;
+ }
+
+ return !ExpectedParent;
}
+
+ private:
+ CXXRecordDecl *ExpectedParent;
};
}
@@ -4477,7 +4492,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
SemaRef.LookupQualifiedName(Prev, NewDC);
assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
- DifferentNameValidatorCCC Validator;
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+ DifferentNameValidatorCCC Validator(MD ? MD->getParent() : 0);
if (!Prev.empty()) {
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index 556e654a2d..55fead5c62 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -157,3 +157,13 @@ bool begun(R);
void RangeTest() {
for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}}
}
+
+// PR 12019 - Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration
+// by not trying to typo-correct a method redeclaration to declarations not
+// in the current record.
+class Parent {
+ void set_types(int index, int value);
+ void add_types(int value);
+};
+class Child: public Parent {};
+void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}}