This patch allows __builtin_bit_cast to materialize a C array as its To type.
It was developed as part of an implementation of P1997, array copy-semantics, but is independent, so makes sense to submit, review and merge ahead of it. gcc/cp/ChangeLog: * constexpr.c (check_bit_cast_type): handle ARRAY_TYPE check, (cxx_eval_bit_cast): handle ARRAY_TYPE copy. * semantics.c (cp_build_bit_cast): warn only on unbounded/VLA. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/bit-cast2.C: update XFAIL tests. * g++.dg/cpp2a/bit-cast-to-array1.C: New test. --- gcc/cp/constexpr.c | 8 ++++- gcc/cp/semantics.c | 7 ++--- gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C | 40 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/bit-cast2.C | 8 ++--- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 453007c686b..be1cdada6f8 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4124,6 +4124,11 @@ static bool check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type, tree orig_type) { + if (TREE_CODE (type) == ARRAY_TYPE) + return check_bit_cast_type (ctx, loc, + TYPE_MAIN_VARIANT (TREE_TYPE (type)), + orig_type); + if (TREE_CODE (type) == UNION_TYPE) { if (!ctx->quiet) @@ -4280,7 +4285,8 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, tree r = NULL_TREE; if (can_native_interpret_type_p (TREE_TYPE (t))) r = native_interpret_expr (TREE_TYPE (t), ptr, len); - else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE) + else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) { r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len); if (r != NULL_TREE) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2443d032749..b3126b12abc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -11562,13 +11562,10 @@ cp_build_bit_cast (location_t loc, tree type, tree arg, { if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)) return error_mark_node; - if (TREE_CODE (type) == ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) { - /* std::bit_cast for destination ARRAY_TYPE is not possible, - as functions may not return an array, so don't bother trying - to support this (and then deal with VLAs etc.). */ error_at (loc, "%<__builtin_bit_cast%> destination type %qT " - "is an array type", type); + "is a VLA variable-length array type", type); return error_mark_node; } if (!trivially_copyable_p (type)) diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C new file mode 100644 index 00000000000..e6e50c06389 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C @@ -0,0 +1,40 @@ +// { dg-do compile } + +class S { int s; }; +S s(); +class U { int a, b; }; +U u(); + +void +foo (int *q) +{ + __builtin_bit_cast (int [1], 0); + __builtin_bit_cast (S [1], 0); + __builtin_bit_cast (U [1], u); +} + +template <int N> +void +bar (int *q) +{ + int intN[N] = {}; + int int2N[2*N] = {}; + __builtin_bit_cast (int [N], intN); + __builtin_bit_cast (S [N], intN); + __builtin_bit_cast (U [N], int2N); +} + +template <typename T1, typename T2, typename T3> +void +baz (T1 ia, T2 sa, T3 ua) +{ + __builtin_bit_cast (T1, *ia); + __builtin_bit_cast (T2, *sa); + __builtin_bit_cast (T3, *ua); +} + +void +qux (S* sp, int *ip, U* up) +{ + baz <int[1], S[1], U[1]> (ip, sp, up); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C index 6bb1760e621..7f1836ee4e9 100644 --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C @@ -14,7 +14,7 @@ foo (int *q) __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" } __builtin_bit_cast (S, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" } __builtin_bit_cast (int &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" } - __builtin_bit_cast (int [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" } + __builtin_bit_cast (S [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is not trivially copyable" } __builtin_bit_cast (V, 0); // { dg-error "invalid use of incomplete type 'struct V'" } __builtin_bit_cast (int, v); __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" } @@ -29,7 +29,7 @@ bar (int *q) __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" } __builtin_bit_cast (S, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" } __builtin_bit_cast (int &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" } - __builtin_bit_cast (int [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" } + __builtin_bit_cast (S [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is not trivially copyable" } __builtin_bit_cast (V, 0); // { dg-error "invalid use of incomplete type 'struct V'" } __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" } __builtin_bit_cast (U, 0); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" } @@ -43,7 +43,7 @@ baz (T3 s, T4 *p, T1 *q) __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" } __builtin_bit_cast (T3, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" } __builtin_bit_cast (T1 &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" } - __builtin_bit_cast (T2, 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" } + __builtin_bit_cast (T2, 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is not trivially copyable" } __builtin_bit_cast (T4, 0); // { dg-error "invalid use of incomplete type 'struct V'" } __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" } __builtin_bit_cast (U, (T1) 0); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" } @@ -53,5 +53,5 @@ baz (T3 s, T4 *p, T1 *q) void qux (int *q) { - baz <int, int [1], S, V> (s, p, q); + baz <int, S [1], S, V> (s, p, q); } -- 2.31.1