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);