When typo-correcting a member using-declaration, only consider members of base classes.

llvm-svn: 207680
This commit is contained in:
Richard Smith 2014-04-30 18:03:21 +00:00
parent 307625c974
commit 21866c3267
2 changed files with 15 additions and 17 deletions
clang

View File

@ -7318,9 +7318,9 @@ namespace {
class UsingValidatorCCC : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
bool RequireMember)
CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
IsInstantiation(IsInstantiation), RequireMemberOf(RequireMemberOf) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
@ -7329,13 +7329,14 @@ public:
if (!ND || isa<NamespaceDecl>(ND))
return false;
// FIXME: We should check if ND is member of base class of class having
// using declaration and direct base class in case using declaration names
// a constructor.
if (RequireMember && !ND->isCXXClassMember())
return false;
if (RequireMemberOf) {
auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext());
if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD))
return false;
// FIXME: Check that the base class member is accessible?
}
if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
if (RequireMemberOf && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
!isa<TypeDecl>(ND))
return false;
@ -7352,7 +7353,7 @@ public:
private:
bool HasTypenameKeyword;
bool IsInstantiation;
bool RequireMember;
CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
@ -7476,7 +7477,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Try to correct typos if possible.
if (R.empty()) {
UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation,
CurContext->isRecord());
dyn_cast<CXXRecordDecl>(CurContext));
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), S, &SS, CCC,
CTK_ErrorRecovery)){

View File

@ -207,7 +207,7 @@ struct Y : S {
using S::S; // expected-error {{no member named 'S' in 'S'}}
};
// [namespace.udecl] Para3: In a using-declaration used as a member-declaration,
// [namespace.udecl]p3: In a using-declaration used as a member-declaration,
// the nested-name-specifier shall name a base class of the class being defined.
// If such a using-declaration names a constructor, the nested-name-specifier
// shall name a direct base class of the class being defined;
@ -216,14 +216,11 @@ struct Y : S {
struct PR19171_B { }; // expected-note {{'PR19171_B' declared here}}
struct PR19171_C : PR19171_B { };
struct PR19171_D : PR19171_C {
using PR19171_B::PR19171_C; // expected-error{{no member named 'PR19171_C' in 'PR19171_B'; did you mean 'PR19171_B'?}}
using PR19171_B::PR19171_C; // expected-error{{no member named 'PR19171_C' in 'PR19171_B'; did you mean 'PR19171_B'?}}
};
// FIXME: Typo correction should only consider member of base classes
struct PR19171_E { };
struct PR19171_EE { int EE; }; // expected-note {{'PR19171_EE::EE' declared here}} \
// expected-note {{target of using declaration}}
struct PR19171_EE { int EE; };
struct PR19171_F : PR19171_E {
using PR19171_E::EE; // expected-error{{no member named 'EE' in 'PR19171_E'; did you mean 'PR19171_EE::EE'?}} \
// expected-error{{using declaration refers into 'PR19171_E::', which is not a base class of 'PR19171_F'}}
using PR19171_E::EE; // expected-error-re{{no member named 'EE' in 'PR19171_E'{{$}}}}
};