diff mbox series

[committed] c++: Handle ARRAY_TYPE in check_bit_cast_type [PR114706]

Message ID Zh4rdPhoa6v972gl@tucnak
State New
Headers show
Series [committed] c++: Handle ARRAY_TYPE in check_bit_cast_type [PR114706] | expand

Commit Message

Jakub Jelinek April 16, 2024, 7:40 a.m. UTC
Hi!

https://eel.is/c++draft/bit.cast#3 says that std::bit_cast isn't constexpr
if To, From and the types of all subobjects have certain properties which the
check_bit_cast_type checks (such as it isn't a pointer, reference, union,
member pointer, volatile).  The function doesn't cp_walk_tree though, so
I've missed one important case, for ARRAY_TYPEs we need to recurse on the
element type.  I think we don't need to handle VECTOR_TYPEs/COMPLEX_TYPEs,
because those will not have a pointer/reference/union/member pointer in
the element type and if the element type is volatile, I think the whole
derived type is volatile as well.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk
as obvious.

2024-04-16  Jakub Jelinek  <jakub@redhat.com>

	PR c++/114706
	* constexpr.cc (check_bit_cast_type): Handle ARRAY_TYPE.

	* g++.dg/cpp2a/bit-cast17.C: New test.


	Jakub
diff mbox series

Patch

--- gcc/cp/constexpr.cc.jj	2024-04-12 19:57:58.792749776 +0200
+++ gcc/cp/constexpr.cc	2024-04-15 17:24:00.181449078 +0200
@@ -4843,6 +4843,8 @@  check_bit_cast_type (const constexpr_ctx
       if (TREE_CODE (field) == FIELD_DECL
 	  && check_bit_cast_type (ctx, loc, TREE_TYPE (field), orig_type))
 	return true;
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    return check_bit_cast_type (ctx, loc, TREE_TYPE (type), orig_type);
   return false;
 }
 
--- gcc/testsuite/g++.dg/cpp2a/bit-cast17.C.jj	2024-04-15 17:13:20.192052326 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bit-cast17.C	2024-04-15 17:38:04.758093926 +0200
@@ -0,0 +1,31 @@ 
+// PR c++/114706
+// { dg-do compile { target c++20 } }
+
+namespace std {
+template<typename T, typename F>
+constexpr T
+bit_cast (const F& f) noexcept
+{
+  return __builtin_bit_cast (T, f);
+}
+}
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const A' contains a union type" "" { target *-*-* } .-3 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'A' contains a union type" "" { target *-*-* } .-4 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const C' contains a union type" "" { target *-*-* } .-5 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'C' contains a union type" "" { target *-*-* } .-6 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const E' contains a pointer type" "" { target *-*-* } .-7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'E' contains a pointer type" "" { target *-*-* } .-8 }
+
+union U { int a; int b; };
+struct A { U c[2]; };
+struct B { int d[2]; };
+struct C { U e[2][2]; };
+struct D { int f[2][2]; };
+struct E { int *g[3]; };
+struct F { char h[sizeof (int *) * 3]; };
+constexpr B i = std::bit_cast<B> (A{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }
+constexpr A j = std::bit_cast<A> (B{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }
+constexpr D k = std::bit_cast<D> (C{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }
+constexpr C l = std::bit_cast<C> (D{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }
+constexpr F m = std::bit_cast<F> (E{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }
+constexpr E n = std::bit_cast<E> (F{});	// { dg-message "in 'constexpr' expansion of 'std::bit_cast<" }