281 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify -Wno-unused-value2 3template<typename T, typename U>4constexpr bool is_same_v = false;5 6template<typename T>7constexpr bool is_same_v<T, T> = true;8 9// We use a hack in this file to make the compiler print out the requires10// expression after it has been instantiated - we put false_v<requires {...}> as11// the requires clause of a class template, then instantiate the template.12// The requirement will not be satisfied, and the explaining diagnostic will13// print out false_v<requires {...}> in its raw form (the false_v serves to14// prevent the diagnostic from elaborating on why the requires expr wasn't15// satisfied).16 17template<bool v>18constexpr bool false_v = false;19 20template<typename... Ts>21using void_t = void;22 23// Check that requires parameters are instantiated correctly.24 25template<typename T> requires26false_v<requires (T t) { requires is_same_v<decltype(t), int>; }>27// expected-note@-1 {{because 'false_v<requires (int t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}28// expected-note@-2 {{because 'false_v<requires (char t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}29struct r1 {};30 31using r1i1 = r1<int>; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}}32using r1i2 = r1<char>; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}}33 34// Check that parameter packs work.35 36template<typename... Ts> requires37false_v<requires (Ts... ts) {requires ((sizeof(ts) == 2) && ...);}>38// expected-note@-1 {{because 'false_v<requires (short ts, unsigned short ts) { requires (sizeof (ts) == 2) && (sizeof (ts) == 2); }>'}}39// expected-note@-2 {{because 'false_v<requires (short ts) { requires (sizeof (ts) == 2); }>' evaluated to false}}40struct r2 {};41 42using r2i1 = r2<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short, unsigned short>]}}43using r2i2 = r2<short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short>]}}44 45template<typename... Ts> requires46false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)>47// expected-note@-1 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; } && requires (unsigned short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}48// expected-note@-2 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}49struct r3 {};50 51using r3i1 = r3<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short, unsigned short>]}}52using r3i2 = r3<short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short>]}}53 54template<typename T>55struct identity { using type = T; };56 57namespace type_requirement {58 struct A {};59 60 // check that nested name specifier is instantiated correctly.61 template<typename T> requires false_v<requires { typename T::type; }> // expected-note{{because 'false_v<requires { typename identity<int>::type; }>' evaluated to false}}62 struct r1 {};63 64 using r1i = r1<identity<int>>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity<int>]}}65 66 // check that template argument list is instantiated correctly.67 template<typename T>68 struct contains_template {69 template<typename U> requires is_same_v<contains_template<T>, U>70 using temp = int;71 };72 73 template<typename T> requires74 false_v<requires { typename T::template temp<T>; }>75 // expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::template temp<contains_template<int>>; }>' evaluated to false}}76 // expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::template temp<contains_template<short>>; }>' evaluated to false}}77 struct r2 {};78 79 using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = contains_template<int>]}}80 using r2i2 = r2<contains_template<short>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = contains_template<short>]}}81 82 // substitution error occurs, then requires expr is instantiated again83 84 template<typename T>85 struct a {86 template<typename U> requires (requires { typename T::a::a; }, false)87 // expected-note@-1{{because 'requires { <<error-type>>; } , false' evaluated to false}}88 struct r {};89 };90 91 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}92 93 // Parameter pack inside expr94 template<typename... Ts> requires95 false_v<(requires { typename Ts::type; } && ...)>96 // expected-note@-1 {{because 'false_v<requires { typename identity<short>::type; } && requires { typename identity<int>::type; } && requires { <<error-type>>; }>' evaluated to false}}97 struct r5 {};98 99 using r5i = r5<identity<short>, identity<int>, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <identity<short>, identity<int>, short>]}}100 template<typename... Ts> requires101 false_v<(requires { typename void_t<Ts>; } && ...)> // expected-note{{because 'false_v<requires { typename void_t<int>; } && requires { typename void_t<short>; }>' evaluated to false}}102 struct r6 {};103 104 using r6i = r6<int, short>; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = <int, short>]}}105 106 template<typename... Ts> requires107 false_v<(requires { typename Ts::template aaa<Ts>; } && ...)>108 // expected-note@-1 {{because 'false_v<requires { <<error-type>>; } && requires { <<error-type>>; }>' evaluated to false}}109 struct r7 {};110 111 using r7i = r7<int, A>; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = <int, A>]}}112}113 114namespace expr_requirement {115 // check that compound/simple requirements are instantiated correctly.116 117 template<typename T> requires false_v<requires { sizeof(T); { sizeof(T) }; }>118 // expected-note@-1 {{because 'false_v<requires { sizeof(int); { sizeof(int) }; }>' evaluated to false}}119 // expected-note@-2 {{because 'false_v<requires { <<error-expression>>; { sizeof(T) }; }>' evaluated to false}}120 struct r1 {};121 122 using r1i1 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}123 using r1i2 = r1<void>; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}}124 125 // substitution error occurs in expr, then expr is instantiated again.126 127 template<typename T>128 struct a {129 template<typename U> requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <<error-expression>>; } , false' evaluated to false}}130 struct r {};131 };132 133 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}134 135 // check that the return-type-requirement is instantiated correctly.136 137 template<typename T, typename U = int>138 concept C1 = is_same_v<T, U>;139 140 template<typename T> requires false_v<requires(T t) { { t } -> C1<T>; }>141 // expected-note@-1 {{because 'false_v<requires (int t) { { t } -> C1<int>; }>' evaluated to false}}142 // expected-note@-2 {{because 'false_v<requires (double t) { { t } -> C1<double>; }>' evaluated to false}}143 struct r2 {};144 145 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}146 using r2i2 = r2<double>; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}}147 148 149 // substitution error occurs in return type requirement, then requires expr is150 // instantiated again.151 152 template<typename T>153 struct b {154 template<typename U> requires (requires { { 0 } -> C1<typename T::a>; }, false) // expected-note{{because 'requires { { 0 } -> <<error-type>>; } , false' evaluated to false}}155 struct r {};156 };157 158 using bri = b<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}159 160 161 template<typename... Ts> requires162 false_v<(requires { { 0 } noexcept -> C1<Ts>; } && ...)>163 // expected-note@-1 {{because 'false_v<requires { { 0 } noexcept -> C1<int>; } && requires { { 0 } noexcept -> C1<unsigned int>; }>' evaluated to false}}164 struct r3 {};165 166 using r3i = r3<int, unsigned int>; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = <int, unsigned int>]}}167 168 template<typename T>169 struct r4 {170 constexpr int foo() {171 if constexpr (requires { this->invalid(); })172 return 1;173 else174 return 0;175 }176 177 constexpr void invalid() requires false { }178 };179 static_assert(r4<int>{}.foo() == 0);180}181 182namespace nested_requirement {183 // check that constraint expression is instantiated correctly184 template<typename T> requires false_v<requires { requires sizeof(T) == 2; }> // expected-note{{because 'false_v<requires { requires sizeof(int) == 2; }>' evaluated to false}}185 struct r1 {};186 187 using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}188 189 // substitution error occurs in expr, then expr is instantiated again.190 template<typename T>191 struct a {192 template<typename U> requires193 (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <<error-expression>>; } , false' evaluated to false}}194 struct r {};195 };196 197 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}198 199 // Parameter pack inside expr200 template<typename... Ts> requires201 false_v<(requires { requires sizeof(Ts) == 0; } && ...)>202 // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; } && requires { requires sizeof(short) == 0; }>' evaluated to false}}203 struct r2 {};204 205 using r2i = r2<int, short>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, short>]}}206}207 208// Parameter pack inside multiple requirements209template<typename... Ts> requires210false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)>211// expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; sizeof(Ts); } && requires { requires sizeof(short) == 0; sizeof(Ts); }>' evaluated to false}}212struct r4 {};213 214using r4i = r4<int, short>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int, short>]}}215 216template<typename... Ts> requires217false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)>218// expected-note@-1 {{because 'false_v<requires (int t) { requires sizeof (t) == 0; t++; } && requires (short t) { requires sizeof (t) == 0; t++; }>' evaluated to false}}219struct r5 {};220 221using r5i = r5<int, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <int, short>]}}222 223template<typename T> requires224false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context.225// expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}}226struct r6 {};227 228using r6i = r6<int>;229// expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}230 231namespace GH73885 {232 233template <class> // expected-error {{extraneous}}234template <class T> requires(T{})235constexpr bool e_v = true;236 237static_assert(e_v<bool>);238 239} // namespace GH73885240 241namespace GH84020 {242 243struct B {244 template <typename S> void foo();245 void bar();246};247 248template <typename T, typename S> struct A : T {249 void foo() {250 static_assert(requires { T::template foo<S>(); });251 static_assert(requires { T::bar(); });252 }253};254 255template class A<B, double>;256 257} // namespace GH84020258 259namespace GH110785 {260 261struct Foo {262 static void f(auto) requires(false) {}263 void f(int) {}264 265 static_assert([](auto v) {266 return requires { f(v); };267 } (0) == false);268};269 270} // namespace GH110785271 272namespace sugared_instantiation {273 template <class C1> concept C = requires { C1{}; };274 template <class D1> concept D = requires { new D1; };275 276 // Test that 'deduced auto' doesn't get confused with 'undeduced auto'.277 auto f() { return 0; }278 static_assert(requires { { f() } -> C; });279 static_assert(requires { { f() } -> D; });280} // namespace sugared_instantiation281