| Richard Smith | 22a250c | 2016-12-19 04:08:53 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -std=c++1z -verify %s |
| 2 | |
| 3 | // Test that we cope with failure to expand a pack. |
| 4 | template<typename ...T> struct Unexpanded : T... { |
| 5 | using T::f; // expected-error {{unexpanded}} |
| 6 | using typename T::type; // expected-error {{unexpanded}} |
| 7 | template<typename ...U> void g(U ...u) { f(u...); } // expected-error {{undeclared identifier 'f'}} |
| 8 | void h() { |
| 9 | Unexpanded<type...> *p; // expected-error {{undeclared identifier 'type'}} |
| 10 | } |
| 11 | }; |
| 12 | void test_Unexpanded() { |
| 13 | struct A { void f(); }; // expected-note {{must qualify}} |
| 14 | struct B { void f(int); }; // expected-note {{must qualify}} |
| 15 | Unexpanded<A, B>().g(0); // expected-note {{instantiation of}} |
| 16 | } |
| 17 | |
| 18 | // Test using non-type members from pack of base classes. |
| 19 | template<typename ...T> struct A : T... { // expected-note 2{{candidate}} |
| 20 | using T::T ...; // expected-note 6{{inherited here}} |
| 21 | using T::operator() ...; |
| 22 | using T::operator T* ...; |
| 23 | using T::h ...; |
| 24 | |
| 25 | void f(int n) { h(n); } // expected-error {{ambiguous}} |
| 26 | void f(int n, int m) { h(n, m); } // expected-error {{member using declaration 'h' instantiates to an empty pack}} |
| 27 | void g(int n) { (*this)(n); } // expected-error {{ambiguous}} |
| 28 | void g(int n, int m) { (*this)(n, m); } // expected-error {{does not provide a call operator}} |
| 29 | }; |
| 30 | |
| 31 | namespace test_A { |
| 32 | struct X { // expected-note 2{{candidate}} |
| 33 | X(); |
| 34 | X(int); // expected-note {{candidate}} |
| 35 | void operator()(int); // expected-note 2{{candidate}} |
| 36 | operator X *(); |
| 37 | void h(int); // expected-note {{candidate}} |
| 38 | }; |
| 39 | struct Y { |
| 40 | Y(); |
| 41 | Y(int, int); |
| 42 | void operator()(int, int); |
| 43 | operator Y *(); |
| 44 | void h(int, int); // expected-note {{not viable}} |
| 45 | }; |
| 46 | struct Z { // expected-note 2{{candidate}} |
| 47 | Z(); |
| 48 | Z(int); // expected-note {{candidate}} |
| 49 | void operator()(int); // expected-note 2{{candidate}} |
| 50 | operator Z *(); |
| 51 | void h(int); // expected-note {{candidate}} |
| 52 | }; |
| 53 | |
| 54 | void f() { |
| 55 | A<> a; |
| 56 | a.f(0, 0); // expected-note {{instantiation of}} |
| 57 | a.g(0, 0); // expected-note {{instantiation of}} |
| 58 | |
| 59 | A<X, Y> axy(0); |
| 60 | A<X, Y>(0, 0); |
| 61 | axy.f(0); |
| 62 | axy.f(0, 0); |
| 63 | axy.g(0); |
| 64 | axy.g(0, 0); |
| 65 | axy(0); |
| 66 | axy(0, 0); |
| 67 | |
| 68 | A<X, Y, Z>(0); // expected-error {{ambiguous}} |
| 69 | A<X, Y, Z> axyz(0, 0); |
| 70 | axyz.f(0); // expected-note {{instantiation of}} |
| 71 | axyz.f(0, 0); |
| 72 | axyz.g(0); // expected-note {{instantiation of}} |
| 73 | axyz.g(0, 0); |
| 74 | axyz(0); // expected-error {{ambiguous}} |
| 75 | axyz(0, 0); |
| 76 | |
| 77 | X *x; |
| 78 | x = a; // expected-error {{incompatible}} |
| 79 | x = axy; |
| 80 | x = axyz; |
| 81 | x = a.operator X*(); // expected-error {{no member}} |
| 82 | x = axy.operator X*(); |
| 83 | x = axyz.operator X*(); |
| 84 | |
| 85 | Z *z; |
| 86 | z = axyz; |
| 87 | z = axyz.operator Z*(); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // Test using pack of non-type members from single base class. |
| 92 | template<typename X, typename Y, typename ...T> struct B : X, Y { |
| 93 | using X::operator T* ...; |
| 94 | }; |
| 95 | |
| 96 | namespace test_B { |
| 97 | struct X { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}} |
| 98 | struct Y { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}} |
| 99 | B<X, Y, int, float> bif; |
| 100 | int *pi = bif; |
| 101 | float *pf = bif; |
| 102 | char *pc = bif; // expected-error {{ambiguous}} |
| 103 | } |
| 104 | |
| 105 | // Test using type member from pack of base classes. |
| 106 | template<typename ...T> struct C : T... { |
| 107 | using typename T::type ...; // expected-error {{target of using declaration conflicts}} |
| 108 | void f() { type value; } // expected-error {{member using declaration 'type' instantiates to an empty pack}} |
| 109 | }; |
| 110 | |
| 111 | namespace test_C { |
| 112 | struct X { typedef int type; }; |
| 113 | struct Y { typedef int type; }; // expected-note {{conflicting}} |
| 114 | struct Z { typedef float type; }; // expected-note {{target}} |
| 115 | |
| 116 | void f() { |
| 117 | C<> c; |
| 118 | c.f(); // expected-note {{instantiation of}} |
| 119 | |
| 120 | C<X, Y> cxy; |
| 121 | cxy.f(); |
| 122 | |
| 123 | C<X, Y, Z> cxyz; // expected-note {{instantiation of}} |
| 124 | cxyz.f(); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | // Test using pack of non-types at block scope. |
| 129 | template<typename ...T> int fn1() { |
| 130 | using T::e ...; // expected-error 2{{class member}} expected-note 2{{instead}} |
| 131 | // expected-error@-1 2{{produces multiple values}} |
| 132 | return e; // expected-error {{using declaration 'e' instantiates to an empty pack}} |
| 133 | } |
| 134 | |
| 135 | namespace test_fn1 { |
| 136 | struct X { static int e; }; |
| 137 | struct Y { typedef int e; }; |
| 138 | inline namespace P { enum E { e }; } |
| 139 | inline namespace Q { enum F { e }; } |
| 140 | void f() { |
| 141 | fn1<>(); // expected-note {{instantiation of}} |
| 142 | fn1<X>(); // expected-note {{instantiation of}} |
| 143 | fn1<Y>(); // expected-note {{instantiation of}} |
| 144 | fn1<E>(); |
| 145 | fn1<E, F>(); // expected-note {{instantiation of}} |
| 146 | fn1<E, X>(); // expected-note {{instantiation of}} |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | // Test using pack of types at block scope. |
| 151 | template<typename ...T> void fn2() { |
| 152 | // This cannot ever be valid: in order for T::type to be a type, T must be a |
| 153 | // class, and a class member cannot be named by a block-scope using declaration. |
| 154 | using typename T::type ...; // expected-error {{class member}} |
| 155 | type x; // expected-error {{unknown type name 'type'}} |
| 156 | } |
| 157 | |
| 158 | // Test partial substitution into class-scope pack. |
| 159 | template<typename ...T> auto lambda1() { |
| 160 | return [](auto x) { |
| 161 | struct A : T::template X<decltype(x)>... { // expected-note 1+{{instantiation of}} |
| 162 | using T::template X<decltype(x)>::f ...; |
| 163 | using typename T::template X<decltype(x)>::type ...; |
| 164 | void g(int n) { f(n); } // expected-error {{empty pack}} expected-error {{expected 2, have 1}} expected-error {{ambiguous}} |
| 165 | void h() { type value; } // expected-error {{empty pack}} |
| 166 | }; |
| 167 | return A(); |
| 168 | }; |
| 169 | } |
| 170 | |
| 171 | namespace test_lambda1 { |
| 172 | struct A { |
| 173 | template<typename> struct X { |
| 174 | void f(int); // expected-note {{candidate}} |
| 175 | using type = int; |
| 176 | }; |
| 177 | }; |
| 178 | struct B { |
| 179 | template<typename> struct X { |
| 180 | void f(int, int); // expected-note {{declared here}} expected-note {{not viable}} |
| 181 | using type = int; |
| 182 | }; |
| 183 | }; |
| 184 | struct C { |
| 185 | template<typename> struct X { |
| 186 | void f(int); // expected-note {{candidate}} |
| 187 | void f(int, int); // expected-note {{not viable}} |
| 188 | using type = int; |
| 189 | }; |
| 190 | }; |
| 191 | |
| 192 | void f() { |
| 193 | lambda1<>() // expected-note 2{{instantiation of}} |
| 194 | (0) |
| 195 | // FIXME: This is poor error recovery |
| 196 | .g(0); // expected-error {{no member named 'g'}} |
| 197 | lambda1<A>() |
| 198 | (0) |
| 199 | .g(0); |
| 200 | lambda1<B>() |
| 201 | (0) // expected-note {{instantiation of}} |
| 202 | .g(0); |
| 203 | lambda1<A, B, C>() |
| 204 | (0) // expected-note {{instantiation of}} |
| 205 | .g(0); |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | namespace p0195r2_example { |
| 210 | template<typename ...Ts> |
| 211 | struct Overloader : Ts... { |
| 212 | using Ts::operator() ...; |
| 213 | }; |
| 214 | |
| 215 | template<typename ...Ts> |
| 216 | constexpr auto make_overloader(Ts &&...ts) { |
| 217 | return Overloader<Ts...>{static_cast<Ts&&>(ts)...}; |
| 218 | } |
| 219 | |
| 220 | void test() { |
| 221 | auto o = make_overloader( |
| 222 | [&](int &r) -> int & { return r; }, // expected-note {{candidate function}} |
| 223 | [&](float &r) -> float & { return r; } // expected-note {{candidate function}} |
| 224 | ); |
| 225 | int a; float f; double d; |
| 226 | int &ra = o(a); |
| 227 | float &rf = o(f); |
| 228 | double &rd = o(d); // expected-error {{no matching function}} |
| 229 | } |
| 230 | } |