]> granicus.if.org Git - clang/commitdiff
When typo-correcting a member using-declaration, only consider members of base classes.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Apr 2014 18:03:21 +0000 (18:03 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Apr 2014 18:03:21 +0000 (18:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207680 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/using-decl-1.cpp

index d49e68e027e5fe5ad45fff8e5463b3d1c66632ea..b1b67a648b18bb04d660ed9954b31028d50d3962 100644 (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)){
index d5e793bbb5a83ac94d009d8fd40b0c7a51a12ef1..2ce0b10908630964892ab90fe7fb86c66552a4f8 100644 (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'{{$}}}}
 };