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

Richard Smith richard-llvm at metafoo.co.uk
Wed Apr 30 11:03:22 PDT 2014


Author: rsmith
Date: Wed Apr 30 13:03:21 2014
New Revision: 207680

URL: http://llvm.org/viewvc/llvm-project?rev=207680&view=rev
Log:
When typo-correcting a member using-declaration, only consider members of base classes.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/using-decl-1.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=207680&r1=207679&r2=207680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr 30 13:03:21 2014
@@ -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(S
   // 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)){

Modified: cfe/trunk/test/SemaCXX/using-decl-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-decl-1.cpp?rev=207680&r1=207679&r2=207680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/using-decl-1.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-decl-1.cpp Wed Apr 30 13:03:21 2014
@@ -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'{{$}}}}
 };





More information about the cfe-commits mailing list