Skip to content

Commit 5985dbe

Browse files
committed
[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.
1 parent 6fedc18 commit 5985dbe

File tree

4 files changed

+20
-4
lines changed

4 files changed

+20
-4
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9237,9 +9237,10 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
92379237
bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
92389238
!Result.IsNullPtr;
92399239
bool VoidPtrCastMaybeOK =
9240-
HasValidResult &&
9241-
Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx),
9242-
E->getType()->getPointeeType());
9240+
Result.IsNullPtr ||
9241+
(HasValidResult &&
9242+
Info.Ctx.hasSimilarType(Result.Designator.getType(Info.Ctx),
9243+
E->getType()->getPointeeType()));
92439244
// 1. We'll allow it in std::allocator::allocate, and anything which that
92449245
// calls.
92459246
// 2. HACK 2022-03-28: Work around an issue with libstdc++'s

clang/test/CXX/drs/dr28xx.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
// expected-no-diagnostics
1111
#endif
1212

13+
namespace cwg2819 { // cwg2819: 19 review 2023-12-01
14+
#if __cpp_constexpr >= 202306L
15+
constexpr void* p = nullptr;
16+
constexpr int* q = static_cast<int*>(p);
17+
static_assert(q == nullptr);
18+
#endif
19+
}
20+
1321
namespace cwg2847 { // cwg2847: 19
1422

1523
#if __cplusplus >= 202002L

clang/test/CXX/expr/expr.const/p5-26.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ void err() {
3737
// cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}} \
3838
// 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'}}
3939
}
40+
41+
int* p;
42+
constexpr int** pp = &p;
43+
constexpr void* vp = pp;
44+
constexpr auto cvp = static_cast<const int* volatile*>(vp);
45+
// cxx23-error@-1 {{constant expression}}
46+
// cxx23-note@-2 {{cast from 'void *' is not allowed in a constant expression}}

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16722,7 +16722,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1672216722
<td><a href="https://cplusplus.github.io/CWG/issues/2819.html">2819</a></td>
1672316723
<td>review</td>
1672416724
<td>Cast from null pointer value in a constant expression</td>
16725-
<td align="center">Not resolved</td>
16725+
<td title="Clang 19 implements 2023-12-01 resolution" align="center">Not Resolved*</td>
1672616726
</tr>
1672716727
<tr class="open" id="2820">
1672816728
<td><a href="https://cplusplus.github.io/CWG/issues/2820.html">2820</a></td>

0 commit comments

Comments
 (0)