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;
};
}
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) {
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'}}