llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (offsetof) <details> <summary>Changes</summary> [[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). --- Full diff: https://github.com/llvm/llvm-project/pull/89484.diff 4 Files Affected: - (modified) clang/lib/AST/ExprConstant.cpp (+4-3) - (modified) clang/test/CXX/drs/dr28xx.cpp (+8) - (modified) clang/test/CXX/expr/expr.const/p5-26.cpp (+7) - (modified) clang/www/cxx_dr_status.html (+1-1) ``````````diff 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@-1 {{constant expression}} +// cxx23-note@-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> `````````` </details> https://github.com/llvm/llvm-project/pull/89484 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits