From caa902613a96f63c3855b3a0bcd82d1b1db49408 Mon Sep 17 00:00:00 2001 From: offsetof <131769984+offsetof@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:23:50 +0000 Subject: [clang] Allow constexpr cast from `void*` in more cases (#89484) [[expr.const]/5.14](https://eel.is/c++draft/expr.const#5.14) says that constexpr cast from *cv* void\* 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). --------- Co-authored-by: Vlad Serebrennikov --- clang/lib/AST/ExprConstant.cpp | 7 +-- clang/test/CXX/drs/dr25xx.cpp | 2 +- clang/test/CXX/drs/dr28xx.cpp | 10 +++- clang/test/CXX/expr/expr.const/p5-26.cpp | 7 +++ clang/www/cxx_dr_status.html | 82 ++++++++++++++++++++++---------- clang/www/make_cxx_dr_status | 2 +- 6 files changed, 78 insertions(+), 32 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ea3e730..71b5f91 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/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 481ae09..8bca58f 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -130,7 +130,7 @@ struct D3 : B { #endif #if __cplusplus >= 202302L -namespace cwg2561 { // cwg2561: no +namespace cwg2561 { // cwg2561: no tentatively ready 2024-03-18 struct C { constexpr C(auto) { } }; diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp index 1967e8b..be35d36 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 tentatively ready 2023-12-01 +#if __cpp_constexpr >= 202306L + constexpr void* p = nullptr; + constexpr int* q = static_cast(p); + static_assert(q == nullptr); +#endif +} + namespace cwg2847 { // cwg2847: 19 review 2024-03-01 #if __cplusplus >= 202002L @@ -59,7 +67,7 @@ void B::g() requires true; } // namespace cwg2847 -namespace cwg2858 { // cwg2858: 19 +namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05 #if __cplusplus > 202302L diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp index 3624b1e..7513b11 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(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 19d29cb..875521b 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -1433,11 +1433,11 @@ accessible? Is indirection through a null pointer undefined behavior? Unknown - + 233 tentatively ready References vs pointers in UDC overload resolution - Unknown + Not resolved 234 @@ -15170,11 +15170,11 @@ and POD class Parameter type determination in a requirement-parameter-list Unknown - + 2561 tentatively ready Conversion to function pointer for lambda with explicit object parameter - No + Not Resolved* 2562 @@ -15332,11 +15332,11 @@ and POD class Visible side effects and initial value of an object Not resolved - + 2588 tentatively ready friend declarations and module linkage - Unknown + Not resolved 2589 @@ -16172,11 +16172,11 @@ and POD class Importing header units synthesized from source files Not resolved - + 2728 tentatively ready Evaluation of conversions in a delete-expression - Unknown + Not resolved 2729 @@ -16713,17 +16713,17 @@ objects sizeof(abstract class) is underspecified Not resolved - + 2818 tentatively ready Use of predefined reserved identifiers - Unknown + Not resolved - + 2819 tentatively ready Cast from null pointer value in a constant expression - Unknown + Not Resolved* 2820 @@ -16953,17 +16953,17 @@ objects Argument-dependent lookup with incomplete class types Unknown - + 2858 tentatively ready Declarative nested-name-specifiers and pack-index-specifiers - Clang 19 + Not Resolved* - + 2859 tentatively ready Value-initialization with multiple default constructors - Unknown + Not resolved 2860 @@ -16971,29 +16971,29 @@ objects Remove and fix the term "vacuous initialization" Unknown - + 2861 tentatively ready dynamic_cast on bad pointer value - Unknown + Not resolved - + 2862 tentatively ready Unclear boundaries of template declarations - Unknown + Not resolved - + 2863 tentatively ready Unclear synchronization requirements for object lifetime rules - Unknown + Not resolved - + 2864 tentatively ready Narrowing floating-point conversions - Unknown + Not resolved 2865 @@ -17031,11 +17031,11 @@ objects Combining absent encoding-prefixes Not resolved - + 2871 tentatively ready User-declared constructor templates inhibiting default constructors - Unknown + Not resolved 2872 @@ -17096,6 +17096,36 @@ objects open Type restrictions for the explicit object parameter of a lambda Not resolved + + + 2882 + open + Unclear treatment of conversion to void + Not resolved + + + 2883 + open + Definition of "odr-usable" ignores lambda scopes + Not resolved + + + 2884 + open + Qualified declarations of partial specializations + Not resolved + + + 2885 + open + Non-eligible trivial default constructors + Not resolved + + + 2886 + open + Temporaries and trivial potentially-throwing special member functions + Not resolved diff --git a/clang/www/make_cxx_dr_status b/clang/www/make_cxx_dr_status index 57f1dc8..47c8b3b 100755 --- a/clang/www/make_cxx_dr_status +++ b/clang/www/make_cxx_dr_status @@ -236,7 +236,7 @@ for dr in drs: avail = 'Extension' avail_style = '' - elif dr.status in ('open', 'drafting', 'review'): + elif dr.status in ('open', 'drafting', 'review', 'tentatively ready'): row_style = ' class="open"' try: avail, avail_style, unresolved_status = availability(dr.issue) -- cgit v1.1