| 1 | // RUN: %clang_cc1 -std=c++11 -verify %s |
| 2 | |
| 3 | typedef int (*fp)(int); |
| 4 | int surrogate(int); |
| 5 | struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} \ |
| 6 | // expected-note {{forward declaration of 'Incomplete'}} |
| 7 | |
| 8 | struct X { |
| 9 | X() = default; // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}} |
| 10 | X(const X&) = default; // expected-note{{candidate constructor not viable: no known conversion from 'bool' to 'const X' for 1st argument}} |
| 11 | X(bool b) __attribute__((enable_if(b, "chosen when 'b' is true"))); // expected-note{{candidate disabled: chosen when 'b' is true}} |
| 12 | |
| 13 | void f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); |
| 14 | void f(int n) __attribute__((enable_if(n == 1, "chosen when 'n' is one"))); // expected-note{{member declaration nearly matches}} expected-note 2{{candidate disabled: chosen when 'n' is one}} |
| 15 | |
| 16 | void g(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note{{candidate disabled: chosen when 'n' is zero}} |
| 17 | |
| 18 | void h(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} |
| 19 | |
| 20 | static void s(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note2{{candidate disabled: chosen when 'n' is zero}} |
| 21 | |
| 22 | void conflict(int n) __attribute__((enable_if(n+n == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}} |
| 23 | void conflict(int n) __attribute__((enable_if(n*2 == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}} |
| 24 | |
| 25 | void hidden_by_argument_conversion(Incomplete n, int m = 0) __attribute__((enable_if(m == 10, "chosen when 'm' is ten"))); |
| 26 | Incomplete hidden_by_incomplete_return_value(int n = 0) __attribute__((enable_if(n == 10, "chosen when 'n' is ten"))); // expected-note{{'hidden_by_incomplete_return_value' declared here}} |
| 27 | |
| 28 | operator long() __attribute__((enable_if(true, "chosen on your platform"))); |
| 29 | operator int() __attribute__((enable_if(false, "chosen on other platform"))); |
| 30 | |
| 31 | operator fp() __attribute__((enable_if(false, "never enabled"))) { return surrogate; } // expected-note{{conversion candidate of type 'int (*)(int)'}} // FIXME: the message is not displayed |
| 32 | }; |
| 33 | |
| 34 | void X::f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))) // expected-note{{member declaration nearly matches}} expected-note 2{{candidate disabled: chosen when 'n' is zero}} |
| 35 | { |
| 36 | } |
| 37 | |
| 38 | void X::f(int n) __attribute__((enable_if(n == 2, "chosen when 'n' is two"))) // expected-error{{out-of-line definition of 'f' does not match any declaration in 'X'}} |
| 39 | { |
| 40 | } |
| 41 | |
| 42 | X x1(true); |
| 43 | X x2(false); // expected-error{{no matching constructor for initialization of 'X'}} |
| 44 | |
| 45 | __attribute__((deprecated)) constexpr int old() { return 0; } // expected-note2{{'old' has been explicitly marked deprecated here}} |
| 46 | void deprec1(int i) __attribute__((enable_if(old() == 0, "chosen when old() is zero"))); // expected-warning{{'old' is deprecated}} |
| 47 | void deprec2(int i) __attribute__((enable_if(old() == 0, "chosen when old() is zero"))); // expected-warning{{'old' is deprecated}} |
| 48 | |
| 49 | void overloaded(int); |
| 50 | void overloaded(long); |
| 51 | |
| 52 | struct Int { |
| 53 | constexpr Int(int i) : i(i) { } |
| 54 | constexpr operator int() const { return i; } |
| 55 | int i; |
| 56 | }; |
| 57 | |
| 58 | void default_argument(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} |
| 59 | void default_argument_promotion(int n, int m = Int(0)) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} |
| 60 | |
| 61 | struct Nothing { }; |
| 62 | template<typename T> void typedep(T t) __attribute__((enable_if(t, ""))); // expected-note{{candidate disabled:}} expected-error{{value of type 'Nothing' is not contextually convertible to 'bool'}} |
| 63 | template<int N> void valuedep() __attribute__((enable_if(N == 1, ""))); |
| 64 | |
| 65 | // FIXME: we skip potential constant expression evaluation on value dependent |
| 66 | // enable-if expressions |
| 67 | int not_constexpr(); |
| 68 | template<int N> void valuedep() __attribute__((enable_if(N == not_constexpr(), ""))); |
| 69 | |
| 70 | template <typename T> void instantiationdep() __attribute__((enable_if(sizeof(sizeof(T)) != 0, ""))); |
| 71 | |
| 72 | void test() { |
| 73 | X x; |
| 74 | x.f(0); |
| 75 | x.f(1); |
| 76 | x.f(2); // expected-error{{no matching member function for call to 'f'}} |
| 77 | x.f(3); // expected-error{{no matching member function for call to 'f'}} |
| 78 | |
| 79 | x.g(0); |
| 80 | x.g(1); // expected-error{{no matching member function for call to 'g'}} |
| 81 | |
| 82 | x.h(0); |
| 83 | x.h(1, 2); // expected-error{{no matching member function for call to 'h'}} |
| 84 | |
| 85 | x.s(0); |
| 86 | x.s(1); // expected-error{{no matching member function for call to 's'}} |
| 87 | |
| 88 | X::s(0); |
| 89 | X::s(1); // expected-error{{no matching member function for call to 's'}} |
| 90 | |
| 91 | x.conflict(5); // expected-error{{call to member function 'conflict' is ambiguous}} |
| 92 | |
| 93 | x.hidden_by_argument_conversion(10); // expected-error{{argument type 'Incomplete' is incomplete}} |
| 94 | x.hidden_by_incomplete_return_value(10); // expected-error{{calling 'hidden_by_incomplete_return_value' with incomplete return type 'Incomplete'}} |
| 95 | |
| 96 | deprec2(0); |
| 97 | |
| 98 | overloaded(x); |
| 99 | |
| 100 | default_argument(0); |
| 101 | default_argument(1, 2); // expected-error{{no matching function for call to 'default_argument'}} |
| 102 | |
| 103 | default_argument_promotion(0); |
| 104 | default_argument_promotion(1, 2); // expected-error{{no matching function for call to 'default_argument_promotion'}} |
| 105 | |
| 106 | int i = x(1); // expected-error{{no matching function for call to object of type 'X'}} |
| 107 | |
| 108 | Nothing n; |
| 109 | typedep(0); // expected-error{{no matching function for call to 'typedep'}} |
| 110 | typedep(1); |
| 111 | typedep(n); // expected-note{{in instantiation of function template specialization 'typedep<Nothing>' requested here}} |
| 112 | } |
| 113 | |
| 114 | template <typename T> class C { |
| 115 | void f() __attribute__((enable_if(T::expr == 0, ""))) {} |
| 116 | void g() { f(); } |
| 117 | }; |
| 118 | |
| 119 | int fn3(bool b) __attribute__((enable_if(b, ""))); // FIXME: This test should net 0 error messages. |
| 120 | template <class T> void test3() { |
| 121 | fn3(sizeof(T) == 1); // expected-error{{no matching function for call to 'fn3'}} expected-note@-2{{candidate disabled}} |
| 122 | } |
| 123 | |
| 124 | template <typename T> |
| 125 | struct Y { |
| 126 | T h(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} |
| 127 | }; |
| 128 | |
| 129 | void test4() { |
| 130 | Y<int> y; |
| 131 | |
| 132 | int t0 = y.h(0); |
| 133 | int t1 = y.h(1, 2); // expected-error{{no matching member function for call to 'h'}} |
| 134 | } |
| 135 | |
| 136 | // FIXME: issue an error (without instantiation) because ::h(T()) is not |
| 137 | // convertible to bool, because return types aren't overloadable. |
| 138 | void h(int); |
| 139 | template <typename T> void outer() { |
| 140 | void local_function() __attribute__((enable_if(::h(T()), ""))); |
| 141 | local_function(); // expected-error{{no matching function for call to 'local_function'}} expected-note@-1{{candidate disabled}} |
| 142 | }; |
| 143 | |
| 144 | namespace PR20988 { |
| 145 | struct Integer { |
| 146 | Integer(int); |
| 147 | }; |
| 148 | |
| 149 | int fn1(const Integer &) __attribute__((enable_if(true, ""))); |
| 150 | template <class T> void test1() { |
| 151 | int &expr = T::expr(); |
| 152 | fn1(expr); |
| 153 | } |
| 154 | |
| 155 | int fn2(const Integer &) __attribute__((enable_if(false, ""))); // expected-note{{candidate disabled}} |
| 156 | template <class T> void test2() { |
| 157 | int &expr = T::expr(); |
| 158 | fn2(expr); // expected-error{{no matching function for call to 'fn2'}} |
| 159 | } |
| 160 | |
| 161 | int fn3(bool b) __attribute__((enable_if(b, ""))); // FIXME: This test should net 0 error messages. |
| 162 | template <class T> void test3() { |
| 163 | fn3(sizeof(T) == 1); // expected-error{{no matching function for call to 'fn3'}} expected-note@-2{{candidate disabled}} |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | namespace FnPtrs { |
| 168 | int ovlFoo(int m) __attribute__((enable_if(m > 0, ""))); |
| 169 | int ovlFoo(int m); |
| 170 | |
| 171 | void test() { |
| 172 | // Assignment gives us a different code path than declarations, and `&foo` |
| 173 | // gives us a different code path than `foo` |
| 174 | int (*p)(int) = ovlFoo; |
| 175 | int (*p2)(int) = &ovlFoo; |
| 176 | int (*a)(int); |
| 177 | a = ovlFoo; |
| 178 | a = &ovlFoo; |
| 179 | } |
| 180 | |
| 181 | int ovlBar(int) __attribute__((enable_if(true, ""))); |
| 182 | int ovlBar(int m) __attribute__((enable_if(false, ""))); |
| 183 | void test2() { |
| 184 | int (*p)(int) = ovlBar; |
| 185 | int (*p2)(int) = &ovlBar; |
| 186 | int (*a)(int); |
| 187 | a = ovlBar; |
| 188 | a = &ovlBar; |
| 189 | } |
| 190 | |
| 191 | int ovlConflict(int m) __attribute__((enable_if(true, ""))); |
| 192 | int ovlConflict(int m) __attribute__((enable_if(1, ""))); |
| 193 | void test3() { |
| 194 | int (*p)(int) = ovlConflict; // expected-error{{address of overloaded function 'ovlConflict' is ambiguous}} expected-note@191{{candidate function}} expected-note@192{{candidate function}} |
| 195 | int (*p2)(int) = &ovlConflict; // expected-error{{address of overloaded function 'ovlConflict' is ambiguous}} expected-note@191{{candidate function}} expected-note@192{{candidate function}} |
| 196 | int (*a)(int); |
| 197 | a = ovlConflict; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@191{{candidate function}} expected-note@192{{candidate function}} |
| 198 | a = &ovlConflict; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@191{{candidate function}} expected-note@192{{candidate function}} |
| 199 | } |
| 200 | |
| 201 | template <typename T> |
| 202 | T templated(T m) __attribute__((enable_if(true, ""))) { return T(); } |
| 203 | template <typename T> |
| 204 | T templated(T m) __attribute__((enable_if(false, ""))) { return T(); } |
| 205 | void test4() { |
| 206 | int (*p)(int) = templated<int>; |
| 207 | int (*p2)(int) = &templated<int>; |
| 208 | int (*a)(int); |
| 209 | a = templated<int>; |
| 210 | a = &templated<int>; |
| 211 | } |
| 212 | |
| 213 | template <typename T> |
| 214 | T templatedBar(T m) __attribute__((enable_if(m > 0, ""))) { return T(); } |
| 215 | void test5() { |
| 216 | int (*p)(int) = templatedBar<int>; // expected-error{{address of overloaded function 'templatedBar' does not match required type 'int (int)'}} expected-note@214{{candidate function made ineligible by enable_if}} |
| 217 | int (*p2)(int) = &templatedBar<int>; // expected-error{{address of overloaded function 'templatedBar' does not match required type 'int (int)'}} expected-note@214{{candidate function made ineligible by enable_if}} |
| 218 | int (*a)(int); |
| 219 | a = templatedBar<int>; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@214{{candidate function made ineligible by enable_if}} |
| 220 | a = &templatedBar<int>; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@214{{candidate function made ineligible by enable_if}} |
| 221 | } |
| 222 | |
| 223 | template <typename T> |
| 224 | T templatedConflict(T m) __attribute__((enable_if(false, ""))) { return T(); } |
| 225 | template <typename T> |
| 226 | T templatedConflict(T m) __attribute__((enable_if(true, ""))) { return T(); } |
| 227 | template <typename T> |
| 228 | T templatedConflict(T m) __attribute__((enable_if(1, ""))) { return T(); } |
| 229 | void test6() { |
| 230 | int (*p)(int) = templatedConflict<int>; // expected-error{{address of overloaded function 'templatedConflict' is ambiguous}} expected-note@224{{candidate function made ineligible by enable_if}} expected-note@226{{candidate function}} expected-note@228{{candidate function}} |
| 231 | int (*p0)(int) = &templatedConflict<int>; // expected-error{{address of overloaded function 'templatedConflict' is ambiguous}} expected-note@224{{candidate function made ineligible by enable_if}} expected-note@226{{candidate function}} expected-note@228{{candidate function}} |
| 232 | int (*a)(int); |
| 233 | a = templatedConflict<int>; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@226{{candidate function}} expected-note@228{{candidate function}} |
| 234 | a = &templatedConflict<int>; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@226{{candidate function}} expected-note@228{{candidate function}} |
| 235 | } |
| 236 | |
| 237 | int ovlNoCandidate(int m) __attribute__((enable_if(false, ""))); |
| 238 | int ovlNoCandidate(int m) __attribute__((enable_if(0, ""))); |
| 239 | void test7() { |
| 240 | int (*p)(int) = ovlNoCandidate; // expected-error{{address of overloaded function 'ovlNoCandidate' does not match required type}} expected-note@237{{made ineligible by enable_if}} expected-note@238{{made ineligible by enable_if}} |
| 241 | int (*p2)(int) = &ovlNoCandidate; // expected-error{{address of overloaded function 'ovlNoCandidate' does not match required type}} expected-note@237{{made ineligible by enable_if}} expected-note@238{{made ineligible by enable_if}} |
| 242 | int (*a)(int); |
| 243 | a = ovlNoCandidate; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@237{{made ineligible by enable_if}} expected-note@238{{made ineligible by enable_if}} |
| 244 | a = &ovlNoCandidate; // expected-error{{assigning to 'int (*)(int)' from incompatible type '<overloaded function type>'}} expected-note@237{{made ineligible by enable_if}} expected-note@238{{made ineligible by enable_if}} |
| 245 | } |
| 246 | |
| 247 | int noOvlNoCandidate(int m) __attribute__((enable_if(false, ""))); |
| 248 | void test8() { |
| 249 | int (*p)(int) = noOvlNoCandidate; // expected-error{{cannot take address of function 'noOvlNoCandidate' because it has one or more non-tautological enable_if conditions}} |
| 250 | int (*p2)(int) = &noOvlNoCandidate; // expected-error{{cannot take address of function 'noOvlNoCandidate' because it has one or more non-tautological enable_if conditions}} |
| 251 | int (*a)(int); |
| 252 | a = noOvlNoCandidate; // expected-error{{cannot take address of function 'noOvlNoCandidate' because it has one or more non-tautological enable_if conditions}} |
| 253 | a = &noOvlNoCandidate; // expected-error{{cannot take address of function 'noOvlNoCandidate' because it has one or more non-tautological enable_if conditions}} |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | namespace casting { |
| 258 | using VoidFnTy = void (*)(); |
| 259 | |
| 260 | void foo(void *c) __attribute__((enable_if(0, ""))); |
| 261 | void foo(int *c) __attribute__((enable_if(c, ""))); |
| 262 | void foo(char *c) __attribute__((enable_if(1, ""))); |
| 263 | |
| 264 | void testIt() { |
| 265 | auto A = reinterpret_cast<VoidFnTy>(foo); |
| 266 | auto AAmp = reinterpret_cast<VoidFnTy>(&foo); |
| 267 | |
| 268 | using VoidFooTy = void (*)(void *); |
| 269 | auto B = reinterpret_cast<VoidFooTy>(foo); |
| 270 | auto BAmp = reinterpret_cast<VoidFooTy>(&foo); |
| 271 | |
| 272 | using IntFooTy = void (*)(int *); |
| 273 | auto C = reinterpret_cast<IntFooTy>(foo); |
| 274 | auto CAmp = reinterpret_cast<IntFooTy>(&foo); |
| 275 | |
| 276 | using CharFooTy = void (*)(void *); |
| 277 | auto D = reinterpret_cast<CharFooTy>(foo); |
| 278 | auto DAmp = reinterpret_cast<CharFooTy>(&foo); |
| 279 | } |
| 280 | |
| 281 | void testItCStyle() { |
| 282 | auto A = (VoidFnTy)foo; |
| 283 | auto AAmp = (VoidFnTy)&foo; |
| 284 | |
| 285 | using VoidFooTy = void (*)(void *); |
| 286 | auto B = (VoidFooTy)foo; |
| 287 | auto BAmp = (VoidFooTy)&foo; |
| 288 | |
| 289 | using IntFooTy = void (*)(int *); |
| 290 | auto C = (IntFooTy)foo; |
| 291 | auto CAmp = (IntFooTy)&foo; |
| 292 | |
| 293 | using CharFooTy = void (*)(void *); |
| 294 | auto D = (CharFooTy)foo; |
| 295 | auto DAmp = (CharFooTy)&foo; |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | namespace casting_templates { |
| 300 | template <typename T> void foo(T) {} // expected-note 4 {{candidate function}} |
| 301 | |
| 302 | void foo(int *c) __attribute__((enable_if(c, ""))); //expected-note 4 {{candidate function}} |
| 303 | void foo(char *c) __attribute__((enable_if(c, ""))); //expected-note 4 {{candidate function}} |
| 304 | |
| 305 | void testIt() { |
| 306 | using IntFooTy = void (*)(int *); |
| 307 | auto A = reinterpret_cast<IntFooTy>(foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 308 | auto ARef = reinterpret_cast<IntFooTy>(&foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 309 | auto AExplicit = reinterpret_cast<IntFooTy>(foo<int*>); |
| 310 | |
| 311 | using CharFooTy = void (*)(char *); |
| 312 | auto B = reinterpret_cast<CharFooTy>(foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 313 | auto BRef = reinterpret_cast<CharFooTy>(&foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 314 | auto BExplicit = reinterpret_cast<CharFooTy>(foo<char*>); |
| 315 | } |
| 316 | |
| 317 | void testItCStyle() { |
| 318 | // constexpr is usable here because all of these should become static_casts. |
| 319 | using IntFooTy = void (*)(int *); |
| 320 | constexpr auto A = (IntFooTy)foo; |
| 321 | constexpr auto ARef = (IntFooTy)&foo; |
| 322 | constexpr auto AExplicit = (IntFooTy)foo<int*>; |
| 323 | |
| 324 | using CharFooTy = void (*)(char *); |
| 325 | constexpr auto B = (CharFooTy)foo; |
| 326 | constexpr auto BRef = (CharFooTy)&foo; |
| 327 | constexpr auto BExplicit = (CharFooTy)foo<char*>; |
| 328 | |
| 329 | static_assert(A == ARef && ARef == AExplicit, ""); |
| 330 | static_assert(B == BRef && BRef == BExplicit, ""); |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | namespace multiple_matches { |
| 335 | using NoMatchTy = void (*)(); |
| 336 | |
| 337 | void foo(float *c); //expected-note 4 {{candidate function}} |
| 338 | void foo(int *c) __attribute__((enable_if(1, ""))); //expected-note 4 {{candidate function}} |
| 339 | void foo(char *c) __attribute__((enable_if(1, ""))); //expected-note 4 {{candidate function}} |
| 340 | |
| 341 | void testIt() { |
| 342 | auto A = reinterpret_cast<NoMatchTy>(foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 343 | auto ARef = reinterpret_cast<NoMatchTy>(&foo); // expected-error{{reinterpret_cast cannot resolve overloaded function 'foo' to type}} |
| 344 | |
| 345 | auto C = (NoMatchTy)foo; // expected-error{{address of overloaded function 'foo' does not match required type 'void ()'}} |
| 346 | auto CRef = (NoMatchTy)&foo; // expected-error{{address of overloaded function 'foo' does not match required type 'void ()'}} |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | namespace PR27122 { |
| 351 | // (slightly reduced) code that motivated the bug... |
| 352 | namespace ns { |
| 353 | void Function(int num) |
| 354 | __attribute__((enable_if(num != 0, ""))); |
| 355 | void Function(int num, int a0) |
| 356 | __attribute__((enable_if(num != 1, ""))); |
| 357 | } // namespace ns |
| 358 | |
| 359 | using ns::Function; // expected-note 3{{declared here}} |
| 360 | void Run() { |
| 361 | Functioon(0); // expected-error{{use of undeclared identifier}} expected-error{{too few arguments}} |
| 362 | Functioon(0, 1); // expected-error{{use of undeclared identifier}} |
| 363 | Functioon(0, 1, 2); // expected-error{{use of undeclared identifier}} |
| 364 | } |
| 365 | |
| 366 | // Extra tests |
| 367 | void regularEnableIf(int a) __attribute__((enable_if(a, ""))); // expected-note 3{{declared here}} expected-note 3{{candidate function not viable}} |
| 368 | void runRegularEnableIf() { |
| 369 | regularEnableIf(0, 2); // expected-error{{no matching function}} |
| 370 | regularEnableIf(1, 2); // expected-error{{no matching function}} |
| 371 | regularEnableIf(); // expected-error{{no matching function}} |
| 372 | |
| 373 | // Test without getting overload resolution involved |
| 374 | ::PR27122::regularEnableIf(0, 2); // expected-error{{too many arguments}} |
| 375 | ::PR27122::regularEnableIf(1, 2); // expected-error{{too many arguments}} |
| 376 | ::PR27122::regularEnableIf(); // expected-error{{too few arguments}} |
| 377 | } |
| 378 | |
| 379 | struct Foo { |
| 380 | void bar(int i) __attribute__((enable_if(i, ""))); // expected-note 2{{declared here}} |
| 381 | }; |
| 382 | |
| 383 | void runFoo() { |
| 384 | Foo f; |
| 385 | f.bar(); // expected-error{{too few arguments}} |
| 386 | f.bar(1, 2); // expected-error{{too many arguments}} |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | // Ideally, we should be able to handle value-dependent expressions sanely. |
| 391 | // Sadly, that isn't the case at the moment. |
| 392 | namespace dependent { |
| 393 | int error(int N) __attribute__((enable_if(N, ""))); // expected-note{{candidate disabled}} |
| 394 | int error(int N) __attribute__((enable_if(!N, ""))); // expected-note{{candidate disabled}} |
| 395 | template <int N> int callUnavailable() { |
| 396 | return error(N); // expected-error{{no matching function for call to 'error'}} |
| 397 | } |
| 398 | |
| 399 | constexpr int noError(int N) __attribute__((enable_if(N, ""))) { return -1; } |
| 400 | constexpr int noError(int N) __attribute__((enable_if(!N, ""))) { return -1; } |
| 401 | constexpr int noError(int N) { return 0; } |
| 402 | |
| 403 | template <int N> |
| 404 | constexpr int callNoError() { return noError(N); } |
| 405 | static_assert(callNoError<0>() == 0, ""); |
| 406 | static_assert(callNoError<1>() == 0, ""); |
| 407 | |
| 408 | template <int N> constexpr int templated() __attribute__((enable_if(N, ""))) { |
| 409 | return 1; |
| 410 | } |
| 411 | |
| 412 | constexpr int A = templated<0>(); // expected-error{{no matching function for call to 'templated'}} expected-note@-4{{candidate disabled}} |
| 413 | static_assert(templated<1>() == 1, ""); |
| 414 | |
| 415 | template <int N> constexpr int callTemplated() { return templated<N>(); } |
| 416 | |
| 417 | constexpr int B = 10 + // the carat for the error should be pointing to the problematic call (on the next line), not here. |
| 418 | callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-3{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-10{{candidate disabled}} |
| 419 | static_assert(callTemplated<1>() == 1, ""); |
| 420 | } |
| 421 | |
| 422 | namespace variadic { |
| 423 | void foo(int a, int b = 0, ...) __attribute__((enable_if(a && b, ""))); // expected-note 6{{disabled}} |
| 424 | |
| 425 | void testFoo() { |
| 426 | foo(1, 1); |
| 427 | foo(1, 1, 2); |
| 428 | foo(1, 1, 2, 3); |
| 429 | |
| 430 | foo(1, 0); // expected-error{{no matching}} |
| 431 | foo(1, 0, 2); // expected-error{{no matching}} |
| 432 | foo(1, 0, 2, 3); // expected-error{{no matching}} |
| 433 | |
| 434 | int m; |
| 435 | foo(1, 1); |
| 436 | foo(1, 1, m); |
| 437 | foo(1, 1, m, 3); |
| 438 | |
| 439 | foo(1, 0); // expected-error{{no matching}} |
| 440 | foo(1, 0, m); // expected-error{{no matching}} |
| 441 | foo(1, 0, m, 3); // expected-error{{no matching}} |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | // Tests that we emit errors at the point of the method call, rather than the |
| 446 | // beginning of the expression that happens to be a member call. |
| 447 | namespace member_loc { |
| 448 | struct Foo { void bar() __attribute__((enable_if(0, ""))); }; // expected-note{{disabled}} |
| 449 | void testFoo() { |
| 450 | Foo() |
| 451 | .bar(); // expected-error{{no matching member function}} |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | // Prior bug: we wouldn't properly convert conditions to bools when |
| 456 | // instantiating templates in some cases. |
| 457 | namespace template_instantiation { |
| 458 | template <typename T> |
| 459 | struct Foo { |
| 460 | void bar(int a) __attribute__((enable_if(a, ""))); // expected-note{{disabled}} |
| 461 | }; |
| 462 | |
| 463 | void runFoo() { |
| 464 | Foo<double>().bar(0); // expected-error{{no matching}} |
| 465 | Foo<double>().bar(1); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | namespace instantiate_constexpr_in_enable_if { |
| 470 | template<typename T> struct X { |
| 471 | static constexpr bool ok() { return true; } |
| 472 | void f() __attribute__((enable_if(ok(), ""))); |
| 473 | }; |
| 474 | void g() { X<int>().f(); } |
| 475 | } |
| 476 | |
| 477 | namespace PR31934 { |
| 478 | int foo(int a) __attribute__((enable_if(a, ""))); |
| 479 | int runFn(int (&)(int)); |
| 480 | |
| 481 | void run() { |
| 482 | { |
| 483 | int (&bar)(int) = foo; // expected-error{{cannot take address of function 'foo'}} |
| 484 | int baz = runFn(foo); // expected-error{{cannot take address of function 'foo'}} |
| 485 | } |
| 486 | |
| 487 | { |
| 488 | int (&bar)(int) = (foo); // expected-error{{cannot take address of function 'foo'}} |
| 489 | int baz = runFn((foo)); // expected-error{{cannot take address of function 'foo'}} |
| 490 | } |
| 491 | |
| 492 | { |
| 493 | int (&bar)(int) = static_cast<int (&)(int)>(foo); // expected-error{{cannot take address of function 'foo'}} |
| 494 | int baz = runFn(static_cast<int (&)(int)>(foo)); // expected-error{{cannot take address of function 'foo'}} |
| 495 | } |
| 496 | |
| 497 | { |
| 498 | int (&bar)(int) = static_cast<int (&)(int)>((foo)); // expected-error{{cannot take address of function 'foo'}} |
| 499 | int baz = runFn(static_cast<int (&)(int)>((foo))); // expected-error{{cannot take address of function 'foo'}} |
| 500 | } |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | namespace TypeOfFn { |
| 505 | template <typename T, typename U> |
| 506 | struct is_same; |
| 507 | |
| 508 | template <typename T> struct is_same<T, T> { |
| 509 | enum { value = 1 }; |
| 510 | }; |
| 511 | |
| 512 | void foo(int a) __attribute__((enable_if(a, ""))); |
| 513 | void foo(float a) __attribute__((enable_if(1, ""))); |
| 514 | |
| 515 | static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, ""); |
| 516 | } |
| 517 | |
| 518 | namespace InConstantContext { |
| 519 | void foo(const char *s) __attribute__((enable_if(((void)__builtin_constant_p(*s), true), "trap"))) {} |
| 520 | |
| 521 | void test() { |
| 522 | InConstantContext::foo("abc"); |
| 523 | } |
| 524 | } // namespace InConstantContext |
| 525 | |