// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify -Wno-unused-value template constexpr bool is_same_v = false; template constexpr bool is_same_v = true; // We use a hack in this file to make the compiler print out the requires // expression after it has been instantiated - we put false_v as // the requires clause of a class template, then instantiate the template. // The requirement will not be satisfied, and the explaining diagnostic will // print out false_v in its raw form (the false_v serves to // prevent the diagnostic from elaborating on why the requires expr wasn't // satisfied). template constexpr bool false_v = false; template using void_t = void; // Check that requires parameters are instantiated correctly. template requires false_v; }> // expected-note@-1 {{because 'false_v; }>' evaluated to false}} // expected-note@-2 {{because 'false_v; }>' evaluated to false}} struct r1 {}; using r1i1 = r1; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}} using r1i2 = r1; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}} // Check that parameter packs work. template requires false_v // expected-note@-1 {{because 'false_v'}} // expected-note@-2 {{because 'false_v' evaluated to false}} struct r2 {}; using r2i1 = r2; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = ]}} using r2i2 = r2; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = ]}} template requires false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)> // expected-note@-1 {{because 'false_v' evaluated to false}} // expected-note@-2 {{because 'false_v' evaluated to false}} struct r3 {}; using r3i1 = r3; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = ]}} using r3i2 = r3; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = ]}} template struct identity { using type = T; }; namespace type_requirement { struct A {}; // check that nested name specifier is instantiated correctly. template requires false_v // expected-note{{because 'false_v::type; }>' evaluated to false}} struct r1 {}; using r1i = r1>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity]}} // check that template argument list is instantiated correctly. template struct contains_template { template requires is_same_v, U> using temp = int; }; template requires false_v; }> // expected-note@-1 {{because 'false_v::temp >; }>' evaluated to false}} // expected-note@-2 {{because 'false_v::temp >; }>' evaluated to false}} struct r2 {}; using r2i1 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} using r2i2 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} // substitution error occurs, then requires expr is instantiated again template struct a { template requires (requires { typename T::a::a; }, false) // expected-note@-1{{because 'requires { <>; } , false' evaluated to false}} struct r {}; }; using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} // Parameter pack inside expr template requires false_v<(requires { typename Ts::type; } && ...)> // expected-note@-1 {{because 'false_v::type; } && requires { typename identity::type; } && requires { <>; }>' evaluated to false}} struct r5 {}; using r5i = r5, identity, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = , identity, short>]}} template requires false_v<(requires { typename void_t; } && ...)> // expected-note{{because 'false_v; } && requires { typename void_t; }>' evaluated to false}} struct r6 {}; using r6i = r6; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = ]}} template requires false_v<(requires { typename Ts::template aaa; } && ...)> // expected-note@-1 {{because 'false_v>; } && requires { <>; }>' evaluated to false}} struct r7 {}; using r7i = r7; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = ]}} } namespace expr_requirement { // check that compound/simple requirements are instantiated correctly. template requires false_v // expected-note@-1 {{because 'false_v' evaluated to false}} // expected-note@-2 {{because 'false_v>; { sizeof(T) }; }>' evaluated to false}} struct r1 {}; using r1i1 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} using r1i2 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}} // substitution error occurs in expr, then expr is instantiated again. template struct a { template requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <>; } , false' evaluated to false}} struct r {}; }; using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} // check that the return-type-requirement is instantiated correctly. template concept C1 = is_same_v; template requires false_v C1; }> // expected-note@-1 {{because 'false_v C1; }>' evaluated to false}} // expected-note@-2 {{because 'false_v C1; }>' evaluated to false}} struct r2 {}; using r2i1 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} using r2i2 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}} // substitution error occurs in return type requirement, then requires expr is // instantiated again. template struct b { template requires (requires { { 0 } -> C1; }, false) // expected-note{{because 'requires { { 0 } -> <>; } , false' evaluated to false}} struct r {}; }; using bri = b::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} template requires false_v<(requires { { 0 } noexcept -> C1; } && ...)> // expected-note@-1 {{because 'false_v C1; } && requires { { 0 } noexcept -> C1; }>' evaluated to false}} struct r3 {}; using r3i = r3; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = ]}} template struct r4 { constexpr int foo() { if constexpr (requires { this->invalid(); }) return 1; else return 0; } constexpr void invalid() requires false { } }; static_assert(r4{}.foo() == 0); } namespace nested_requirement { // check that constraint expression is instantiated correctly template requires false_v // expected-note{{because 'false_v' evaluated to false}} struct r1 {}; using r1i = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} // substitution error occurs in expr, then expr is instantiated again. template struct a { template requires (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <>; } , false' evaluated to false}} struct r {}; }; using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} // Parameter pack inside expr template requires false_v<(requires { requires sizeof(Ts) == 0; } && ...)> // expected-note@-1 {{because 'false_v' evaluated to false}} struct r2 {}; using r2i = r2; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = ]}} } // Parameter pack inside multiple requirements template requires false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)> // expected-note@-1 {{because 'false_v' evaluated to false}} struct r4 {}; using r4i = r4; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = ]}} template requires false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)> // expected-note@-1 {{because 'false_v' evaluated to false}} struct r5 {}; using r5i = r5; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = ]}} template requires false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context. // expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}} struct r6 {}; using r6i = r6; // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}