]> granicus.if.org Git - clang/commitdiff
Reset the found-virtual-base state unless the *current* base produces a path,
authorJohn McCall <rjmccall@apple.com>
Tue, 9 Feb 2010 00:57:12 +0000 (00:57 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 9 Feb 2010 00:57:12 +0000 (00:57 +0000)
not *any* base up to now has produced a path.  Fixes PR 6254.

I'll do the access-control part of this patch RSN.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95638 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/CXXInheritance.cpp
test/CXX/conv/conv.mem/p4.cpp [new file with mode: 0644]

index 720832869266f5e33f47c76f6ba70c1df9651f5d..7d9e553eaf809881a81842ddb3e240ff4bd9489f 100644 (file)
@@ -215,10 +215,13 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
         Paths.ScratchPath.Access
           = MergeAccess(AccessToHere, BaseSpec->getAccessSpecifier());
     }
-        
+    
+    // Track whether there's a path involving this specific base.
+    bool FoundPathThroughBase = false;
+    
     if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
       // We've found a path that terminates at this base.
-      FoundPath = true;
+      FoundPath = FoundPathThroughBase = true;
       if (Paths.isRecordingPaths()) {
         // We have a path. Make a copy of it before moving on.
         Paths.Paths.push_back(Paths.ScratchPath);
@@ -240,7 +243,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
         
         // There is a path to a base class that meets the criteria. If we're 
         // not collecting paths or finding ambiguities, we're done.
-        FoundPath = true;
+        FoundPath = FoundPathThroughBase = true;
         if (!Paths.isFindingAmbiguities())
           return FoundPath;
       }
@@ -253,7 +256,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
     }
 
     // If we set a virtual earlier, and this isn't a path, forget it again.
-    if (SetVirtual && !FoundPath) {
+    if (SetVirtual && !FoundPathThroughBase) {
       Paths.DetectedVirtual = 0;
     }
   }
diff --git a/test/CXX/conv/conv.mem/p4.cpp b/test/CXX/conv/conv.mem/p4.cpp
new file mode 100644 (file)
index 0000000..d782cde
--- /dev/null
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s
+
+struct Base {
+  int data;
+  int method();
+};
+int (Base::*data_ptr) = &Base::data;
+int (Base::*method_ptr)() = &Base::method;
+
+namespace test0 {
+  struct Derived : Base {};
+  void test() {
+    int (Derived::*d) = data_ptr;
+    int (Derived::*m)() = method_ptr;
+  }
+}
+
+// FIXME: can't be inaccessible.
+namespace test1 {
+  struct Derived : private Base {};
+  void test() {
+    int (Derived::*d) = data_ptr; // error
+    int (Derived::*m)() = method_ptr; // error
+  }
+};
+
+// Can't be ambiguous.
+namespace test2 {
+  struct A : Base {};
+  struct B : Base {};
+  struct Derived : A, B {};
+  void test() {
+    int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}}
+    int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}}
+  }
+}
+
+// Can't be virtual.
+namespace test3 {
+  struct Derived : virtual Base {};
+  void test() {
+    int (Derived::*d) = data_ptr;  // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}}
+    int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}}
+  }
+}
+
+// Can't be virtual even if there's a non-virtual path.
+namespace test4 {
+  struct A : Base {};
+  struct Derived : Base, virtual A {};
+  void test() {
+    int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}}
+    int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}}
+  }
+}
+
+// PR6254: don't get thrown off by a virtual base.
+namespace test5 {
+  struct A {};
+  struct Derived : Base, virtual A {};
+  void test() {
+    int (Derived::*d) = data_ptr;
+    int (Derived::*m)() = method_ptr;
+  }
+}