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 | 58bd01fcb63b9e2fc1117dce15b9d924cc60e171 (patch) | |
| tree | 67b48f2f51ac1ec07f951611fe542f4c97733408 /clang/test | |
| parent | 59abdf5f3fea8becf17618ba54e25948b715f84c (diff) | |
| download | bcm5719-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.cpp | 30 | ||||
| -rw-r--r-- | clang/test/SemaCXX/adl.cpp | 20 |
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; +} |

