summaryrefslogtreecommitdiffstats
path: root/test/CXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-01-16 22:01:39 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-01-16 22:01:39 +0000
commita7d7e428cf6497d79dc3a557586cf9c7fe7b4839 (patch)
treef9cfd0ab7eb05c52d7bb5308953b5801c8313766 /test/CXX
parent6b961fe8684f1594ae5fb2c77e68d9960b3b5427 (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.cpp30
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