Reset the found-virtual-base state unless the *current* base produces a path,
not *any* base up to now has produced a path. Fixes PR 6254. I'll do the access-control part of this patch RSN. llvm-svn: 95638
This commit is contained in:
parent
89261502cb
commit
6f891400c2
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue