summaryrefslogtreecommitdiffstats
path: root/clang/test
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
commit58bd01fcb63b9e2fc1117dce15b9d924cc60e171 (patch)
tree67b48f2f51ac1ec07f951611fe542f4c97733408 /clang/test
parent59abdf5f3fea8becf17618ba54e25948b715f84c (diff)
downloadbcm5719-llvm-58bd01fcb63b9e2fc1117dce15b9d924cc60e171.tar.gz
bcm5719-llvm-58bd01fcb63b9e2fc1117dce15b9d924cc60e171.zip
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. llvm-svn: 351382
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/drs/dr0xx.cpp30
-rw-r--r--clang/test/SemaCXX/adl.cpp20
2 files changed, 50 insertions, 0 deletions
diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp
index 048187814db..911aab17474 100644
--- a/clang/test/CXX/drs/dr0xx.cpp
+++ b/clang/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
diff --git a/clang/test/SemaCXX/adl.cpp b/clang/test/SemaCXX/adl.cpp
new file mode 100644
index 00000000000..392ddddcb4e
--- /dev/null
+++ b/clang/test/SemaCXX/adl.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+namespace PR40329 {
+ struct A {
+ A(int);
+ friend int operator->*(A, A);
+ };
+ struct B : A {
+ B();
+ enum E { e };
+ };
+ // Associated classes for B are {B, A}
+ // Associated classes for B::E are {B} (non-transitive in this case)
+ //
+ // If we search B::E first, we must not mark B "visited" and shortcircuit
+ // visiting it later, or we won't find the associated class A.
+ int k0 = B::e ->* B::e; // expected-error {{non-pointer-to-member type}}
+ int k1 = B::e ->* B();
+ int k2 = B() ->* B::e;
+}
OpenPOWER on IntegriCloud