248 lines · cpp
1// RUN: %clang_cc1 %s -triple=x86_64 -std=c++2c -fsyntax-only -verify2// RUN: %clang_cc1 %s -triple=x86_64 -std=c++2c -fsyntax-only -verify -fexperimental-new-constant-interpreter3 4 5struct S0 {};6struct S1 {int a;};7struct S2 {int a; int b; static int c;};8struct S3 {double a; int b; int c;};9struct S4 {int a: 1; int b :2;};10struct S5 {int : 1; int b :2;};11struct S6 {union {int a;}; }; // #note-anon-union12struct S7 {int a[];};13 14 15 16struct SD : S1 {};17struct SE1 : S1 { int b;};18 19class P1 {int a;}; // #note-private20 21union U1 {};22union U2 {int a;};23 24template <typename T>25concept is_destructurable = requires {26 { __builtin_structured_binding_size(T) };27};28 29static_assert(__builtin_structured_binding_size(S0) == 0);30static_assert(__is_same_as(decltype(__builtin_structured_binding_size(S0)), decltype(sizeof(void*))));31 32static_assert(__builtin_structured_binding_size(S1) == 0);33// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S1) == 0'}} \34// expected-note@-1 {{expression evaluates to '1 == 0'}}35static_assert(__builtin_structured_binding_size(S1) == 1);36static_assert(__builtin_structured_binding_size(S2) == 2);37static_assert(__builtin_structured_binding_size(S3) == 3);38static_assert(__builtin_structured_binding_size(S4) == 2);39static_assert(__builtin_structured_binding_size(S5) == 2);40// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \41// expected-note@-1 {{expression evaluates to '1 == 2'}}42static_assert(__builtin_structured_binding_size(S6) == 2);43// expected-error@-1 {{cannot bind class type 'S6' because it has an anonymous union member}} \44// expected-error@-1 {{type 'S6' cannot be bound}} \45// expected-error@-1 {{static assertion expression is not an integral constant expression}} \46// expected-note@#note-anon-union {{declared here}}47static_assert(__builtin_structured_binding_size(S7) == 1);48 49 50static_assert(__builtin_structured_binding_size(SD) == 1);51static_assert(__builtin_structured_binding_size(SE1) == 1);52// expected-error@-1 {{cannot bind class type 'SE1': both it and its base class 'S1' have non-static data members}} \53// expected-error@-1 {{type 'SE1' cannot be bound}} \54// expected-error@-1 {{static assertion expression is not an integral constant expression}}55 56static_assert(__builtin_structured_binding_size(U1) == 0);57// expected-error@-1 {{type 'U1' cannot be bound}} \58// expected-error@-1 {{static assertion expression is not an integral constant expression}}59static_assert(__builtin_structured_binding_size(U2) == 0);60// expected-error@-1 {{type 'U2' cannot be bound}} \61// expected-error@-1 {{static assertion expression is not an integral constant expression}}62 63 64 65static_assert(__builtin_structured_binding_size(int[0]) == 0);66static_assert(__builtin_structured_binding_size(int[1]) == 1);67static_assert(__builtin_structured_binding_size(int[42]) == 42);68 69using vec2 = int __attribute__((__vector_size__(2 * sizeof(int))));70using vec3 = int __attribute__((__vector_size__(3 * sizeof(int))));71static_assert(__builtin_structured_binding_size(vec2) == 2);72static_assert(__builtin_structured_binding_size(vec3) == 3);73static_assert(__builtin_structured_binding_size(decltype(__builtin_complex(0., 0.))) == 2);74 75 76int VLASize; // expected-note {{declared here}}77static_assert(__builtin_structured_binding_size(int[VLASize]) == 42);78// expected-error@-1 {{type 'int[VLASize]' cannot be bound}} \79// expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} \80// expected-note@-1 {{read of non-const variable 'VLASize' is not allowed in a constant expression}} \81// expected-error@-1 {{static assertion expression is not an integral constant expression}}82 83 84struct Incomplete; // expected-note {{forward declaration of 'Incomplete'}}85static_assert(__builtin_structured_binding_size(Incomplete) == 1);86// expected-error@-1 {{incomplete type 'Incomplete' where a complete type is required}} \87// expected-error@-1 {{type 'Incomplete' cannot be bound}} \88// expected-error@-1 {{static assertion expression is not an integral constant expression}}89static_assert(__builtin_structured_binding_size(Incomplete[]) == 1);90// expected-error@-1 {{type 'Incomplete[]' cannot be bound}} \91// expected-error@-1 {{static assertion expression is not an integral constant expression}}92static_assert(__builtin_structured_binding_size(Incomplete[0]) == 0);93static_assert(__builtin_structured_binding_size(Incomplete[1]) == 1);94static_assert(__builtin_structured_binding_size(Incomplete[42]) == 42);95 96 97static_assert(__builtin_structured_binding_size(P1) == 0);98// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(P1) == 0'}} \99// expected-note@-1 {{expression evaluates to '1 == 0'}} \100// expected-error@-1 {{cannot bind private member 'a' of 'P1}} \101// expected-note@#note-private {{implicitly declared private here}}102 103 104void func(int array[14], int x = __builtin_structured_binding_size(decltype(array)));105//expected-error@-1 {{type 'decltype(array)' (aka 'int *') cannot be bound}}106 107struct SM {108 static int array[14];109 static_assert(__builtin_structured_binding_size(decltype(array)) == 14);110};111 112template <typename Ty, int N = __builtin_structured_binding_size(Ty)> // #tpl-1113struct T {114 static constexpr int value = N;115};116 117T<int> t1;118// expected-error@#tpl-1 {{type 'int' cannot be bound}} \119// expected-error@#tpl-1 {{non-type template argument is not a constant expression}} \120// expected-note@-1 {{in instantiation of default argument for 'T<int>' required here}} \121// expected-note@-1 {{while checking a default template argument used here}} \122 123static_assert(T<S3>::value == 3);124 125static_assert(is_destructurable<S0>);126static_assert(is_destructurable<const S0>);127static_assert(is_destructurable<volatile S0>);128static_assert(!is_destructurable<S0&>);129static_assert(is_destructurable<S1>);130static_assert(!is_destructurable<S1&>);131static_assert(!is_destructurable<SE1>);132static_assert(!is_destructurable<int>);133static_assert(!is_destructurable<int[]>);134static_assert(is_destructurable<int[1]>);135static_assert(!is_destructurable<P1>);136 137template <typename T>138constexpr int f() {return 0;};139template <typename T>140requires is_destructurable<T>141constexpr int f() {return 1;};142 143static_assert(f<int>() == 0);144static_assert(f<S0>() == 1);145 146struct T0;147struct T1;148struct T42;149struct TSizeError;150 151namespace std {152 153template <typename>154struct tuple_size;155 156template <>157struct tuple_size<T0> {158 static constexpr int value = 0;159};160 161template <>162struct tuple_size<T1> {163 static constexpr int value = 1;164};165 166template <>167struct tuple_size<T42> {168 static constexpr int value = 42;169};170 171template <>172struct tuple_size<TSizeError> {173 static constexpr void* value = nullptr;174};175 176static_assert(__builtin_structured_binding_size(T0) == 0);177 178static_assert(is_destructurable<const T0>);179static_assert(is_destructurable<volatile T0>);180static_assert(!is_destructurable<T0&>);181 182 183static_assert(__builtin_structured_binding_size(T1) == 1);184static_assert(__builtin_structured_binding_size(T42) == 42);185static_assert(__builtin_structured_binding_size(TSizeError) == 42);186// expected-error@-1 {{cannot bind this type; 'std::tuple_size<TSizeError>::value' is not a valid integral constant expression}} \187// expected-error@-1 {{type 'TSizeError' cannot be bound}} \188// expected-error@-1 {{static assertion expression is not an integral constant expression}}189static_assert(!is_destructurable<TSizeError>);190}191 192 193struct S {194 int x;195 int y;196 static_assert(__builtin_structured_binding_size(S) == 2);197 //expected-error@-1 {{incomplete type 'S' where a complete type is required}} \198 // expected-error@-1 {{type 'S' cannot be bound}} \199 // expected-error@-1 {{static assertion expression is not an integral constant expression}} \200 // expected-note@-4 {{definition of 'S' is not complete until the closing '}'}}201};202 203// Check we can implement std::exec::tag_of_t204template <typename T>205struct type_identity {206 using type = T;207};208template<typename T> T &&declval();209 210template <typename T>211requires (__builtin_structured_binding_size(T) >=2)212consteval auto tag_of_impl(T& t) {213 auto && [tag, ..._] = t;214 return type_identity<decltype(auto(tag))>{};215}216 217template <typename T>218requires (__builtin_structured_binding_size(T) >=2) // #tag-of-constr219using tag_of_t = decltype(tag_of_impl(declval<T&>()))::type;220 221static_assert(__is_same_as(tag_of_t<S2>, int));222static_assert(__is_same_as(tag_of_t<S3>, double));223 224 225static_assert(__is_same_as(tag_of_t<S1>, int));226// expected-error@-1 {{constraints not satisfied for alias template 'tag_of_t' [with T = S1]}} \227// expected-note@#tag-of-constr {{because '__builtin_structured_binding_size(S1) >= 2' (1 >= 2) evaluated to false}}228 229static_assert(__is_same_as(tag_of_t<int>, int)); // error230// expected-error@-1 {{constraints not satisfied for alias template 'tag_of_t' [with T = int]}}231// expected-note@#tag-of-constr {{because substituted constraint expression is ill-formed: type 'int' cannot be bound}}232 233struct MinusOne;234template <> struct ::std::tuple_size<MinusOne> {235 static constexpr int value = -1;236};237int minus_one = __builtin_structured_binding_size(MinusOne);238// expected-error@-1 {{cannot bind this type; 'std::tuple_size<MinusOne>::value' is not a valid size: -1}}239// expected-error@-2 {{type 'MinusOne' cannot be bound}}240 241struct UintMax;242template <> struct ::std::tuple_size<UintMax> {243 static constexpr unsigned value = -1;244};245int uint_max = __builtin_structured_binding_size(UintMax);246// expected-error@-1 {{cannot bind this type; 'std::tuple_size<UintMax>::value' is not a valid size: 4294967295}}247// expected-error@-2 {{type 'UintMax' cannot be bound}}248