diff mbox series

c++: Implement C++26 CWG2819 - Allow cv void * null pointer value conversion to object types in constant expressions

Message ID ZoVijSB8BjnAIV+2@tucnak
State New
Headers show
Series c++: Implement C++26 CWG2819 - Allow cv void * null pointer value conversion to object types in constant expressions | expand

Commit Message

Jakub Jelinek July 3, 2024, 2:39 p.m. UTC
Hi!

The following patch implements CWG2819 (which wasn't a DR because
it changes behavior of C++26 only).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-07-03  Jakub Jelinek  <jakub@redhat.com>

	* constexpr.cc (cxx_eval_constant_expression): CWG2819 - Allow
	cv void * null pointer value conversion to object types in constant
	expressions.

	* g++.dg/cpp26/constexpr-voidptr3.C: New test.
	* g++.dg/cpp0x/constexpr-cast2.C: Adjust expected diagnostics for
	C++26.
	* g++.dg/cpp0x/constexpr-cast4.C: Likewise.


	Jakub

Comments

Jason Merrill July 3, 2024, 3:35 p.m. UTC | #1
On 7/3/24 10:39 AM, Jakub Jelinek wrote:
> Hi!
> 
> The following patch implements CWG2819 (which wasn't a DR because
> it changes behavior of C++26 only).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2024-07-03  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* constexpr.cc (cxx_eval_constant_expression): CWG2819 - Allow
> 	cv void * null pointer value conversion to object types in constant
> 	expressions.
> 
> 	* g++.dg/cpp26/constexpr-voidptr3.C: New test.
> 	* g++.dg/cpp0x/constexpr-cast2.C: Adjust expected diagnostics for
> 	C++26.
> 	* g++.dg/cpp0x/constexpr-cast4.C: Likewise.
> 
> --- gcc/cp/constexpr.cc.jj	2024-07-02 22:09:52.493176541 +0200
> +++ gcc/cp/constexpr.cc	2024-07-03 12:46:57.255025849 +0200
> @@ -8157,10 +8157,13 @@ cxx_eval_constant_expression (const cons
>   		    || DECL_NAME (decl) == heap_vec_uninit_identifier))
>   	      /* OK */;
>   	    /* P2738 (C++26): a conversion from a prvalue P of type "pointer to
> -	       cv void" to a pointer-to-object type T unless P points to an
> -	       object whose type is similar to T.  */
> +	       cv void" to a pointer-to-object type T unless P is a null
> +	       pointer value or points to an object whose type is similar to
> +	       T.  */
>   	    else if (cxx_dialect > cxx23)
>   	      {
> +		if (integer_zerop (sop))
> +		  return build_int_cst (type, 0);

This patch should also remove the integer_zerop diagnostic lower in the 
function, which becomes dead code with this change.

>   		r = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), sop);
>   		if (r)
>   		  {
> --- gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C.jj	2024-07-03 12:35:56.301762995 +0200
> +++ gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C	2024-07-03 12:35:51.577825446 +0200
> @@ -0,0 +1,13 @@
> +// CWG 2819 - Cast from null pointer value in a constant expression
> +// { dg-do compile { target c++26 } }
> +
> +struct S { int s; };
> +
> +constexpr S *
> +foo ()
> +{
> +  void *p = nullptr;
> +  return static_cast<S *> (p);
> +}
> +
> +static_assert (foo () == nullptr);
> --- gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C.jj	2023-07-17 09:07:42.104283529 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C	2024-07-03 16:22:33.294916937 +0200
> @@ -5,9 +5,9 @@
>   static int i;
>   constexpr void *vp0 = nullptr;
>   constexpr void *vpi = &i;
> -constexpr int *p1 = (int *) vp0; // { dg-error "cast from .void\\*. is not allowed" }
> +constexpr int *p1 = (int *) vp0; // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
>   constexpr int *p2 = (int *) vpi; // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
> -constexpr int *p3 = static_cast<int *>(vp0); // { dg-error "cast from .void\\*. is not allowed" }
> +constexpr int *p3 = static_cast<int *>(vp0); // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
>   constexpr int *p4 = static_cast<int *>(vpi); // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
>   constexpr void *p5 = vp0;
>   constexpr void *p6 = vpi;
> --- gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C.jj	2023-11-02 07:39:18.679201173 +0100
> +++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C	2024-07-03 16:23:29.424197809 +0200
> @@ -8,4 +8,3 @@ constexpr float* pf = static_cast<float*
>   
>   constexpr void* vnp = nullptr;
>   constexpr int* pi2 = static_cast<int*>(vnp);  // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
> -// { dg-error "cast from .void\\*. is not allowed in a constant expression because .vnp. does not point to an object" "" { target c++26 } .-1 }
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/cp/constexpr.cc.jj	2024-07-02 22:09:52.493176541 +0200
+++ gcc/cp/constexpr.cc	2024-07-03 12:46:57.255025849 +0200
@@ -8157,10 +8157,13 @@  cxx_eval_constant_expression (const cons
 		    || DECL_NAME (decl) == heap_vec_uninit_identifier))
 	      /* OK */;
 	    /* P2738 (C++26): a conversion from a prvalue P of type "pointer to
-	       cv void" to a pointer-to-object type T unless P points to an
-	       object whose type is similar to T.  */
+	       cv void" to a pointer-to-object type T unless P is a null
+	       pointer value or points to an object whose type is similar to
+	       T.  */
 	    else if (cxx_dialect > cxx23)
 	      {
+		if (integer_zerop (sop))
+		  return build_int_cst (type, 0);
 		r = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), sop);
 		if (r)
 		  {
--- gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C.jj	2024-07-03 12:35:56.301762995 +0200
+++ gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C	2024-07-03 12:35:51.577825446 +0200
@@ -0,0 +1,13 @@ 
+// CWG 2819 - Cast from null pointer value in a constant expression
+// { dg-do compile { target c++26 } }
+
+struct S { int s; };
+
+constexpr S *
+foo ()
+{
+  void *p = nullptr;
+  return static_cast<S *> (p);
+}
+
+static_assert (foo () == nullptr);
--- gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C.jj	2023-07-17 09:07:42.104283529 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C	2024-07-03 16:22:33.294916937 +0200
@@ -5,9 +5,9 @@ 
 static int i;
 constexpr void *vp0 = nullptr;
 constexpr void *vpi = &i;
-constexpr int *p1 = (int *) vp0; // { dg-error "cast from .void\\*. is not allowed" }
+constexpr int *p1 = (int *) vp0; // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
 constexpr int *p2 = (int *) vpi; // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
-constexpr int *p3 = static_cast<int *>(vp0); // { dg-error "cast from .void\\*. is not allowed" }
+constexpr int *p3 = static_cast<int *>(vp0); // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
 constexpr int *p4 = static_cast<int *>(vpi); // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
 constexpr void *p5 = vp0;
 constexpr void *p6 = vpi;
--- gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C.jj	2023-11-02 07:39:18.679201173 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C	2024-07-03 16:23:29.424197809 +0200
@@ -8,4 +8,3 @@  constexpr float* pf = static_cast<float*
 
 constexpr void* vnp = nullptr;
 constexpr int* pi2 = static_cast<int*>(vnp);  // { dg-error "cast from .void\\*. is not allowed" "" { target c++23_down } }
-// { dg-error "cast from .void\\*. is not allowed in a constant expression because .vnp. does not point to an object" "" { target c++26 } .-1 }