https://gcc.gnu.org/g:8eab5064d54f41054b6a50d233a1a78a935b1c2a

commit r15-1906-g8eab5064d54f41054b6a50d233a1a78a935b1c2a
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Tue Jul 9 09:37:16 2024 +0200

    c++: Implement C++26 CWG2819 - Allow cv void * null pointer value 
conversion to object types in constant expressions
    
    The following patch implements CWG2819 (which wasn't a DR because
    it changes behavior of C++26 only).
    
    2024-07-09  Jakub Jelinek  <ja...@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.

Diff:
---
 gcc/cp/constexpr.cc                             | 37 ++++++++++---------------
 gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C    |  4 +--
 gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C    |  1 -
 gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C | 13 +++++++++
 4 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0cdac0af7de0..14bbdea2546d 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8157,10 +8157,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
                    || 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)
                  {
@@ -8169,26 +8172,16 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
                  }
                if (!ctx->quiet)
                  {
-                   if (TREE_CODE (sop) == ADDR_EXPR)
-                     {
-                       auto_diagnostic_group d;
-                       error_at (loc, "cast from %qT is not allowed in a "
-                                 "constant expression because "
-                                 "pointed-to type %qT is not similar to %qT",
-                                 TREE_TYPE (op), TREE_TYPE (TREE_TYPE (sop)),
-                                 TREE_TYPE (type));
-                       tree obj = build_fold_indirect_ref (sop);
-                       inform (DECL_SOURCE_LOCATION (obj),
-                               "pointed-to object declared here");
-                     }
-                   else
-                     {
-                       gcc_assert (integer_zerop (sop));
-                       error_at (loc, "cast from %qT is not allowed in a "
-                                 "constant expression because "
-                                 "%qE does not point to an object",
-                                 TREE_TYPE (op), oldop);
-                     }
+                   gcc_assert (TREE_CODE (sop) == ADDR_EXPR);
+                   auto_diagnostic_group d;
+                   error_at (loc, "cast from %qT is not allowed in a "
+                             "constant expression because "
+                             "pointed-to type %qT is not similar to %qT",
+                             TREE_TYPE (op), TREE_TYPE (TREE_TYPE (sop)),
+                             TREE_TYPE (type));
+                   tree obj = build_fold_indirect_ref (sop);
+                   inform (DECL_SOURCE_LOCATION (obj),
+                           "pointed-to object declared here");
                  }
                *non_constant_p = true;
                return t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C
index 3efbd92f0439..71ec08f36137 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
index 884b6a53e3b6..324c8e392767 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
@@ -8,4 +8,3 @@ constexpr float* pf = static_cast<float*>(vpr);  // { dg-error 
"cast from .void\
 
 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 }
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C 
b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C
new file mode 100644
index 000000000000..67728b2bae97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C
@@ -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);

Reply via email to