[clang] [clang] Allow constexpr cast from `void*` in more cases (PR #89484)

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 19 19:47:11 PDT 2024


https://github.com/offsetof created https://github.com/llvm/llvm-project/pull/89484

[[expr.const]/5.14](https://eel.is/c++draft/expr.const#5.14) says that constexpr cast from <code>*cv* void\*</code> to `T*` is OK if the pointee type is similar to `T`, but Clang currently only permits the conversion if the types are the same except top-level cv-qualifiers.

This patch also allows casting `(void*)nullptr`, implementing the resolution of [CWG2819](https://cplusplus.github.io/CWG/issues/2819).


>From 5985dbe47e052505278d60628bbb5ca751cc3b6c Mon Sep 17 00:00:00 2001
From: offsetof <131769984+offsetof at users.noreply.github.com>
Date: Sat, 20 Apr 2024 02:35:09 +0000
Subject: [PATCH] [clang] Allow constexpr cast from "void*" in more cases

When converting from "cv void*" to "T*" in a constant expression, check
that the actual pointee type is similar to "T" (as opposed to requiring
that the types are the same except top-level qualifiers).

Also implement the resolution of the tentatively ready CWG issue 2819,
adding support for the case when the operand is a null pointer.
---
 clang/lib/AST/ExprConstant.cpp           | 7 ++++---
 clang/test/CXX/drs/dr28xx.cpp            | 8 ++++++++
 clang/test/CXX/expr/expr.const/p5-26.cpp | 7 +++++++
 clang/www/cxx_dr_status.html             | 2 +-
 4 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 73ae8d8efb23a2..d7aee8c92b83d5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9237,9 +9237,10 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
       bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
                             !Result.IsNullPtr;
       bool VoidPtrCastMaybeOK =
-          HasValidResult &&
-          Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx),
-                                          E->getType()->getPointeeType());
+          Result.IsNullPtr ||
+          (HasValidResult &&
+           Info.Ctx.hasSimilarType(Result.Designator.getType(Info.Ctx),
+                                   E->getType()->getPointeeType()));
       // 1. We'll allow it in std::allocator::allocate, and anything which that
       //    calls.
       // 2. HACK 2022-03-28: Work around an issue with libstdc++'s
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 4d9b0c76758d53..591bf7abfd872d 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -10,6 +10,14 @@
 // expected-no-diagnostics
 #endif
 
+namespace cwg2819 { // cwg2819: 19 review 2023-12-01
+#if __cpp_constexpr >= 202306L
+  constexpr void* p = nullptr;
+  constexpr int* q = static_cast<int*>(p);
+  static_assert(q == nullptr);
+#endif
+}
+
 namespace cwg2847 { // cwg2847: 19
 
 #if __cplusplus >= 202002L
diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp
index 3624b1e5a3e3df..7513b11c09aa01 100644
--- a/clang/test/CXX/expr/expr.const/p5-26.cpp
+++ b/clang/test/CXX/expr/expr.const/p5-26.cpp
@@ -37,3 +37,10 @@ void err() {
                                                 // cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}} \
                                                 // cxx26-note {{cast from 'void *' is not allowed in a constant expression because the pointed object type 'T' is not similar to the target type 'S'}}
 }
+
+int* p;
+constexpr int** pp = &p;
+constexpr void* vp = pp;
+constexpr auto cvp = static_cast<const int* volatile*>(vp);
+// cxx23-error at -1 {{constant expression}}
+// cxx23-note at -2 {{cast from 'void *' is not allowed in a constant expression}}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 83b71e7c122d1e..2677364065b2f2 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -16722,7 +16722,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://cplusplus.github.io/CWG/issues/2819.html">2819</a></td>
     <td>review</td>
     <td>Cast from null pointer value in a constant expression</td>
-    <td align="center">Not resolved</td>
+    <td title="Clang 19 implements 2023-12-01 resolution" align="center">Not Resolved*</td>
   </tr>
   <tr class="open" id="2820">
     <td><a href="https://cplusplus.github.io/CWG/issues/2820.html">2820</a></td>



More information about the cfe-commits mailing list