[PATCH] c++: __builtin_bit_cast To C array target type [PR103140]

Will Wray wjwray@gmail.com
Mon Nov 8 20:03:07 GMT 2021


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



More information about the Gcc-patches mailing list