forked from OSchip/llvm-project
When typo correction produces an overloaded result when looking up a member,
return all the overloads instead of just picking the first possible declaration. This removes an invalid note (and on occasion other invalid diagnostics) and also makes clang's parsing recovery behave as if the text from its fixit were applied. llvm-svn: 181370
This commit is contained in:
parent
3610139ac5
commit
d1b0df46f5
|
@ -116,7 +116,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Gets the pointer to the declaration of the typo correction
|
/// \brief Gets the pointer to the declaration of the typo correction
|
||||||
NamedDecl* getCorrectionDecl() const {
|
NamedDecl *getCorrectionDecl() const {
|
||||||
return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
|
return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
|
||||||
}
|
}
|
||||||
template <class DeclClass>
|
template <class DeclClass>
|
||||||
|
|
|
@ -605,19 +605,33 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
|
||||||
R.getLookupKind(), NULL,
|
R.getLookupKind(), NULL,
|
||||||
&SS, Validator, DC);
|
&SS, Validator, DC);
|
||||||
R.clear();
|
R.clear();
|
||||||
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
|
if (Corrected.isResolved() && !Corrected.isKeyword()) {
|
||||||
std::string CorrectedStr(
|
std::string CorrectedStr(
|
||||||
Corrected.getAsString(SemaRef.getLangOpts()));
|
Corrected.getAsString(SemaRef.getLangOpts()));
|
||||||
std::string CorrectedQuotedStr(
|
std::string CorrectedQuotedStr(
|
||||||
Corrected.getQuoted(SemaRef.getLangOpts()));
|
Corrected.getQuoted(SemaRef.getLangOpts()));
|
||||||
|
|
||||||
R.setLookupName(Corrected.getCorrection());
|
R.setLookupName(Corrected.getCorrection());
|
||||||
R.addDecl(ND);
|
for (TypoCorrection::decl_iterator DI = Corrected.begin(),
|
||||||
|
DIEnd = Corrected.end();
|
||||||
|
DI != DIEnd; ++DI) {
|
||||||
|
R.addDecl(*DI);
|
||||||
|
}
|
||||||
|
R.resolveKind();
|
||||||
|
|
||||||
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
|
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
|
||||||
<< Name << DC << CorrectedQuotedStr << SS.getRange()
|
<< Name << DC << CorrectedQuotedStr << SS.getRange()
|
||||||
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
|
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
|
||||||
CorrectedStr);
|
CorrectedStr);
|
||||||
SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
|
|
||||||
<< ND->getDeclName();
|
// If we're typo-correcting to an overloaded name, we don't yet have enough
|
||||||
|
// information to do overload resolution, so we don't know which previous
|
||||||
|
// declaration to point to.
|
||||||
|
if (!Corrected.isOverloaded()) {
|
||||||
|
NamedDecl *ND = Corrected.getCorrectionDecl();
|
||||||
|
SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
|
||||||
|
<< ND->getDeclName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -239,7 +239,7 @@ void test() {
|
||||||
|
|
||||||
namespace PR13387 {
|
namespace PR13387 {
|
||||||
struct A {
|
struct A {
|
||||||
void CreateFoo(float, float); // expected-note {{'CreateFoo' declared here}}
|
void CreateFoo(float, float);
|
||||||
void CreateBar(float, float);
|
void CreateBar(float, float);
|
||||||
};
|
};
|
||||||
struct B : A {
|
struct B : A {
|
||||||
|
@ -260,3 +260,45 @@ struct T {
|
||||||
void f() {
|
void f() {
|
||||||
data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}}
|
data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace b6956809_test1 {
|
||||||
|
struct A {};
|
||||||
|
struct B {};
|
||||||
|
|
||||||
|
struct S1 {
|
||||||
|
void method(A*); // no note here
|
||||||
|
void method(B*);
|
||||||
|
};
|
||||||
|
|
||||||
|
void test1() {
|
||||||
|
B b;
|
||||||
|
S1 s;
|
||||||
|
s.methodd(&b); // expected-error{{no member named 'methodd' in 'b6956809_test1::S1'; did you mean 'method'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S2 {
|
||||||
|
S2();
|
||||||
|
void method(A*) const; // expected-note{{candidate function not viable}}
|
||||||
|
private:
|
||||||
|
void method(B*); // expected-note{{candidate function not viable}}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test2() {
|
||||||
|
B b;
|
||||||
|
const S2 s;
|
||||||
|
s.methodd(&b); // expected-error{{no member named 'methodd' in 'b6956809_test1::S2'; did you mean 'method'}} expected-error{{no matching member function for call to 'method'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace b6956809_test2 {
|
||||||
|
template<typename T> struct Err { typename T::error n; }; // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}}
|
||||||
|
struct S {
|
||||||
|
template<typename T> typename Err<T>::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}} expected-note{{while substituting deduced template arguments into function template 'method' [with T = void *]}}
|
||||||
|
template<typename T> int method(T *);
|
||||||
|
};
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
S s;
|
||||||
|
int k = s.methodd((void*)0); // expected-error{{no member named 'methodd' in 'b6956809_test2::S'; did you mean 'method'?}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue