================ @@ -0,0 +1,210 @@ +// 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 <typename T> +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 {{static assertion failed due to requirement '__builtin_structured_binding_size(S6) == 2'}} \ +// expected-error@-1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \ +// expected-note@-1 {{expression evaluates to '1 == 2'}} +// 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}} + + +static_assert(is_destructurable<S0>); +static_assert(is_destructurable<const S0>); +static_assert(is_destructurable<volatile S0>); +static_assert(!is_destructurable<S0&>); +static_assert(is_destructurable<S1>); +static_assert(!is_destructurable<S1&>); +static_assert(!is_destructurable<SE1>); +static_assert(!is_destructurable<int>); +static_assert(!is_destructurable<int[]>); +static_assert(is_destructurable<int[1]>); +static_assert(!is_destructurable<P1>); + +template <typename T> +constexpr int f() {return 0;}; +template <typename T> +requires is_destructurable<T> +constexpr int f() {return 1;}; + +static_assert(f<int>() == 0); +static_assert(f<S0>() == 1); + +struct T0; +struct T1; +struct T42; +struct TSizeError; + +namespace std { + +template <typename> +struct tuple_size; + +template <> +struct tuple_size<T0> { + static constexpr int value = 0; +}; + +template <> +struct tuple_size<T1> { + static constexpr int value = 1; +}; + +template <> +struct tuple_size<T42> { + static constexpr int value = 42; +}; + +template <> +struct tuple_size<TSizeError> { + static constexpr void* value = nullptr; +}; + +static_assert(__builtin_structured_binding_size(T0) == 0); + +static_assert(is_destructurable<const T0>); +static_assert(is_destructurable<volatile T0>); +static_assert(!is_destructurable<T0&>); + + +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<TSizeError>::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<TSizeError>); +} + + +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 '}'}} +}; + ---------------- AaronBallman wrote:
Some other edge case tests: ``` void func(int array[14], int x = __builtin_structured_binding_size(array)); // Is x 14? struct S { static int array[14]; int x = __builtin_structured_binding_size(array); // Is x 14? }; template <typename Ty, int N = __builtin_structured_binding_size(Ty)> struct T { static constexpr int value = N; }; T<int> t1; // Error static_assert(T<S3>::value == 3); ``` https://github.com/llvm/llvm-project/pull/131515 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits