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.

llvm-svn: 150735
This commit is contained in:
Kaelyn Uhrain 2012-02-16 22:40:59 +00:00
parent 33c364b12b
commit 7c019177b0
2 changed files with 28 additions and 2 deletions

View File

@ -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) {

View File

@ -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'}}