[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