// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify // RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify -fexperimental-new-constant-interpreter struct S0 {}; struct S1 {int a;}; struct S2 {int a; int b; static int c;}; struct S3 {double a; int b; int c;}; struct S4 {int a: 1; int b :2;}; struct S5 {int : 1; int b :2;}; struct S6 {union {int a;}; }; // #note-anon-union struct S7 {int a[];}; struct SD : S1 {}; struct SE1 : S1 { int b;}; class P1 {int a;}; // #note-private union U1 {}; union U2 {int a;}; template concept is_destructurable = requires { { __builtin_structured_binding_size(T) }; }; static_assert(__builtin_structured_binding_size(S0) == 0); static_assert(__is_same_as(decltype(__builtin_structured_binding_size(S0)), decltype(sizeof(void*)))); static_assert(__builtin_structured_binding_size(S1) == 0); // expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S1) == 0'}} \ // expected-note@-1 {{expression evaluates to '1 == 0'}} static_assert(__builtin_structured_binding_size(S1) == 1); static_assert(__builtin_structured_binding_size(S2) == 2); static_assert(__builtin_structured_binding_size(S3) == 3); static_assert(__builtin_structured_binding_size(S4) == 2); static_assert(__builtin_structured_binding_size(S5) == 2); // expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \ // expected-note@-1 {{expression evaluates to '1 == 2'}} static_assert(__builtin_structured_binding_size(S6) == 2); // expected-error@-1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \ // expected-error@-1 {{type 'S6' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} \ // expected-note@#note-anon-union {{declared here}} static_assert(__builtin_structured_binding_size(S7) == 1); static_assert(__builtin_structured_binding_size(SD) == 1); static_assert(__builtin_structured_binding_size(SE1) == 1); // expected-error@-1 {{cannot decompose class type 'SE1': both it and its base class 'S1' have non-static data members}} \ // expected-error@-1 {{type 'SE1' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(__builtin_structured_binding_size(U1) == 0); // expected-error@-1 {{type 'U1' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(__builtin_structured_binding_size(U2) == 0); // expected-error@-1 {{type 'U2' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(__builtin_structured_binding_size(int[0]) == 0); static_assert(__builtin_structured_binding_size(int[1]) == 1); static_assert(__builtin_structured_binding_size(int[42]) == 42); using vec2 = int __attribute__((__vector_size__(2 * sizeof(int)))); using vec3 = int __attribute__((__vector_size__(3 * sizeof(int)))); static_assert(__builtin_structured_binding_size(vec2) == 2); static_assert(__builtin_structured_binding_size(vec3) == 3); static_assert(__builtin_structured_binding_size(decltype(__builtin_complex(0., 0.))) == 2); int VLASize; // expected-note {{declared here}} static_assert(__builtin_structured_binding_size(int[VLASize]) == 42); // expected-error@-1 {{type 'int[VLASize]' cannot be decomposed}} \ // expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} \ // expected-note@-1 {{read of non-const variable 'VLASize' is not allowed in a constant expression}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} struct Incomplete; // expected-note {{forward declaration of 'Incomplete'}} static_assert(__builtin_structured_binding_size(Incomplete) == 1); // expected-error@-1 {{incomplete type 'Incomplete' where a complete type is required}} \ // expected-error@-1 {{type 'Incomplete' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(__builtin_structured_binding_size(Incomplete[]) == 1); // expected-error@-1 {{type 'Incomplete[]' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(__builtin_structured_binding_size(Incomplete[0]) == 0); static_assert(__builtin_structured_binding_size(Incomplete[1]) == 1); static_assert(__builtin_structured_binding_size(Incomplete[42]) == 42); static_assert(__builtin_structured_binding_size(P1) == 0); // expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(P1) == 0'}} \ // expected-note@-1 {{expression evaluates to '1 == 0'}} \ // expected-error@-1 {{cannot decompose private member 'a' of 'P1}} \ // expected-note@#note-private {{implicitly declared private here}} void func(int array[14], int x = __builtin_structured_binding_size(decltype(array))); //expected-error@-1 {{type 'decltype(array)' (aka 'int *') cannot be decomposed}} struct SM { static int array[14]; static_assert(__builtin_structured_binding_size(decltype(array)) == 14); }; template // #tpl-1 struct T { static constexpr int value = N; }; T t1; // expected-error@#tpl-1 {{type 'int' cannot be decomposed}} \ // expected-error@#tpl-1 {{non-type template argument is not a constant expression}} \ // expected-note@-1 {{in instantiation of default argument for 'T' required here}} \ // expected-note@-1 {{while checking a default template argument used here}} \ static_assert(T::value == 3); static_assert(is_destructurable); static_assert(is_destructurable); static_assert(is_destructurable); static_assert(!is_destructurable); static_assert(is_destructurable); static_assert(!is_destructurable); static_assert(!is_destructurable); static_assert(!is_destructurable); static_assert(!is_destructurable); static_assert(is_destructurable); static_assert(!is_destructurable); template constexpr int f() {return 0;}; template requires is_destructurable constexpr int f() {return 1;}; static_assert(f() == 0); static_assert(f() == 1); struct T0; struct T1; struct T42; struct TSizeError; namespace std { template struct tuple_size; template <> struct tuple_size { static constexpr int value = 0; }; template <> struct tuple_size { static constexpr int value = 1; }; template <> struct tuple_size { static constexpr int value = 42; }; template <> struct tuple_size { static constexpr void* value = nullptr; }; static_assert(__builtin_structured_binding_size(T0) == 0); static_assert(is_destructurable); static_assert(is_destructurable); static_assert(!is_destructurable); static_assert(__builtin_structured_binding_size(T1) == 1); static_assert(__builtin_structured_binding_size(T42) == 42); static_assert(__builtin_structured_binding_size(TSizeError) == 42); // expected-error@-1 {{cannot decompose this type; 'std::tuple_size::value' is not a valid integral constant expression}} \ // expected-error@-1 {{type 'TSizeError' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} static_assert(!is_destructurable); } struct S { int x; int y; static_assert(__builtin_structured_binding_size(S) == 2); //expected-error@-1 {{incomplete type 'S' where a complete type is required}} \ // expected-error@-1 {{type 'S' cannot be decomposed}} \ // expected-error@-1 {{static assertion expression is not an integral constant expression}} \ // expected-note@-4 {{definition of 'S' is not complete until the closing '}'}} }; // Check we can implement std::exec::tag_of_t template struct type_identity { using type = T; }; template T &&declval(); template requires (__builtin_structured_binding_size(T) >=2) consteval auto tag_of_impl(T& t) { auto && [tag, ..._] = t; return type_identity{}; } template requires (__builtin_structured_binding_size(T) >=2) // #tag-of-constr using tag_of_t = decltype(tag_of_impl(declval()))::type; static_assert(__is_same_as(tag_of_t, int)); static_assert(__is_same_as(tag_of_t, double)); static_assert(__is_same_as(tag_of_t, int)); // expected-error@-1 {{constraints not satisfied for alias template 'tag_of_t' [with T = S1]}} \ // expected-note@#tag-of-constr {{because '__builtin_structured_binding_size(S1) >= 2' (1 >= 2) evaluated to false}} static_assert(__is_same_as(tag_of_t, int)); // error // expected-error@-1 {{constraints not satisfied for alias template 'tag_of_t' [with T = int]}} // expected-note@#tag-of-constr {{because substituted constraint expression is ill-formed: type 'int' cannot be decomposed}}