diff options
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 21 | ||||
-rw-r--r-- | clang/test/SemaCXX/using-decl-1.cpp | 11 |
2 files changed, 15 insertions, 17 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d49e68e027e..b1b67a648b1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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)){ diff --git a/clang/test/SemaCXX/using-decl-1.cpp b/clang/test/SemaCXX/using-decl-1.cpp index d5e793bbb5a..2ce0b109086 100644 --- a/clang/test/SemaCXX/using-decl-1.cpp +++ b/clang/test/SemaCXX/using-decl-1.cpp @@ -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'{{$}}}} }; |