aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-07-09 09:37:16 +0200
committerJakub Jelinek <jakub@redhat.com>2024-07-09 09:38:50 +0200
commit8eab5064d54f41054b6a50d233a1a78a935b1c2a (patch)
tree47d8806cafdbbc96041821444d9abe4b6008dc26
parent23ab7f632f4f5bae67fb53cf7b18fea7ba7242c4 (diff)
downloadgcc-8eab5064d54f41054b6a50d233a1a78a935b1c2a.zip
gcc-8eab5064d54f41054b6a50d233a1a78a935b1c2a.tar.gz
gcc-8eab5064d54f41054b6a50d233a1a78a935b1c2a.tar.bz2
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 <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.
-rw-r--r--gcc/cp/constexpr.cc37
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-cast2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp26/constexpr-voidptr3.C13
4 files changed, 30 insertions, 25 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0cdac0a..14bbdea 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 3efbd92..71ec08f 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 884b6a5..324c8e3 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 0000000..67728b2
--- /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);