// RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s template concept C1 = true; // expected-note{{template is declared here}} static_assert(C1); static_assert(C1); // expected-error@-1{{use of concept 'C1' requires template arguments}} template concept C2 = sizeof(T) == 4; static_assert(C2); static_assert(!C2); static_assert(C2); static_assert(!C2); template concept C3 = sizeof(*T{}) == 4; static_assert(C3); static_assert(!C3); struct A { static constexpr int add(int a, int b) { return a + b; } }; struct B { static int add(int a, int b) { // expected-note{{declared here}} return a + b; } }; template concept C4 = U::add(1, 2) == 3; // expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}} // expected-note@-2{{non-constexpr function 'add' cannot be used in a constant expression}} static_assert(C4); static_assert(!C4); // expected-note {{while checking the satisfaction of concept 'C4' requested here}} template constexpr bool is_same_v = false; template constexpr bool is_same_v = true; template concept Same = is_same_v; static_assert(Same); static_assert(Same); static_assert(!Same); static_assert(!Same); static_assert(Same); static_assert(Same)>); static_assert(Same)>); static_assert(Same)>); static_assert(Same)>); template concept C5 = T{}; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}} constexpr bool x = C5; // expected-note {{while checking the satisfaction of concept 'C5' requested here}} template concept IsEven = (x % 2) == 0; static_assert(IsEven<20>); static_assert(!IsEven<11>); template typename P> concept IsTypePredicate = is_same_v::value), const bool> && is_same_v::value), const bool> && is_same_v::value), const bool>; template struct T1 {}; template struct T2 { static constexpr bool value = sizeof(T) == 2; }; static_assert(IsTypePredicate); static_assert(!IsTypePredicate); template concept OneOf = (Same || ...); static_assert(OneOf); static_assert(!OneOf); namespace piecewise_substitution { template concept True = true; template concept A = True || T::value; template concept B = (True || T::value); template concept C = !True && T::value || true; template concept D = (!True && T::value) || true; template concept E = T::value || True; template concept F = (T::value || True); template concept G = T::value && !True || true; template concept H = (T::value && !True) || true; template concept I = T::value; static_assert(A); static_assert(B); static_assert(C); static_assert(D); static_assert(E); static_assert(F); static_assert(G); static_assert(H); static_assert(!I); } // Short ciruiting template struct T3 { using type = typename T::type; }; // expected-error@-1{{type 'char' cannot be used prior to '::' because it has no members}} // expected-error@-2{{type 'short' cannot be used prior to '::' because it has no members}} template concept C6 = sizeof(T) == 1 && sizeof(typename T3::type) == 1; // expected-note@-1{{while substituting template arguments into constraint expression here}} // expected-note@-2{{in instantiation of template class 'T3' requested here}} template concept C7 = sizeof(T) == 1 || sizeof( // expected-note@-1{{while substituting template arguments into constraint expression here}} typename T3 // expected-note@-1{{in instantiation of template class 'T3' requested here}} ::type) == 1; static_assert(!C6); static_assert(!C6); // expected-note{{while checking the satisfaction of concept 'C6' requested here}} static_assert(C7); static_assert(!C7); // expected-note{{while checking the satisfaction of concept 'C7' requested here}} // Make sure argument list is converted when instantiating a CSE. template concept SameSize = sizeof(T) == sizeof(U); template struct X { static constexpr bool a = SameSize; }; static_assert(X::a); // static_assert concept diagnostics template concept Large = sizeof(T) > 100; // expected-note@-1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}} struct small { }; static_assert(Large); // expected-error@-1 {{static_assert failed}} // expected-note@-2 {{because 'small' does not satisfy 'Large'}} static_assert(Large, "small isn't large"); // expected-error@-1 {{static_assert failed "small isn't large"}} // expected-note@-2 {{because 'small' does not satisfy 'Large'}} // Make sure access-checking can fail a concept specialization class T4 { static constexpr bool f = true; }; template concept AccessPrivate = T{}.f; // expected-note@-1{{because substituted constraint expression is ill-formed: 'f' is a private member of 'T4'}} static_assert(AccessPrivate); // expected-error@-1{{static_assert failed}} // expected-note@-2{{because 'T4' does not satisfy 'AccessPrivate'}} template // expected-note@-1{{template parameter is declared here}} concept C8 = sizeof(T) > sizeof(U); template constexpr bool B8 = C8; // expected-error@-1{{pack expansion used as argument for non-pack parameter of concept}} // Make sure we correctly check for containsUnexpandedParameterPack template concept C9 = true; template using invoke = typename Fn::template invoke; template // The converted argument here will not containsUnexpandedParameterPack, but the // as-written one will. requires (C9> &&...) struct S { };