diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-16 22:01:39 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-16 22:01:39 +0000 |
commit | a7d7e428cf6497d79dc3a557586cf9c7fe7b4839 (patch) | |
tree | f9cfd0ab7eb05c52d7bb5308953b5801c8313766 /test/CXX | |
parent | 6b961fe8684f1594ae5fb2c77e68d9960b3b5427 (diff) |
PR40329: [adl] Fix determination of associated classes when searching a
member enum and then its enclosing class.
There are situations where ADL will collect a class but not the complete
set of associated classes / namespaces of that class. When that
happened, and we later tried to collect those associated classes /
namespaces, we would previously short-circuit the lookup and not find
them. Eg, for:
struct A : B { enum E; };
if we first looked for associated classes/namespaces of A::E, we'd find
only A. But if we then tried to also collect associated
classes/namespaces of A (which should include the base class B), we
would not add B because we had already visited A.
This also fixes a minor issue where we would fail to collect associated
classes from an overloaded class member access expression naming a
static member function.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351382 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX')
-rw-r--r-- | test/CXX/drs/dr0xx.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index 048187814d..911aab1747 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -413,6 +413,36 @@ namespace dr33 { // dr33: yes void g(X::S); template<typename Z> Z g(Y::T); void h() { f(&g); } // expected-error {{ambiguous}} + + template<typename T> void t(X::S); + template<typename T, typename U = void> void u(X::S); // expected-error 0-1{{default template argument}} + void templ() { f(t<int>); f(u<int>); } + + // Even though v<int> cannot select the first overload, ADL considers it + // and adds namespace Z to the set of associated namespaces, and then picks + // Z::f even though that function has nothing to do with any associated type. + namespace Z { struct Q; void f(void(*)()); } + template<int> Z::Q v(); + template<typename> void v(); + void unrelated_templ() { f(v<int>); } + + namespace dependent { + struct X {}; + template<class T> struct Y { + friend int operator+(X, void(*)(Y)) {} + }; + + template<typename T> void f(Y<T>); + int use = X() + f<int>; // expected-error {{invalid operands}} + } + + namespace member { + struct Q {}; + struct Y { friend int operator+(Q, Y (*)()); }; + struct X { template<typename> static Y f(); }; + int m = Q() + X().f<int>; // ok + int n = Q() + (&(X().f<int>)); // ok + } } // dr34: na |