Skip to content

Commit 3f64899

Browse files
authored
[clang][bytecode] Fix initing incomplete arrays from ImplicitValueIni… (#128729)
…tExpr If the ImplicitValueInitExpr is of incomplete array type, we ignore it in its Visit function. This is a special case here, so pull out the element type and zero the elements.
1 parent 8dd6095 commit 3f64899

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3277,6 +3277,8 @@ bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
32773277
return this->emitCall(F, 0, E);
32783278
}
32793279

3280+
// FIXME: This function has become rather unwieldy, especially
3281+
// the part where we initialize an array allocation of dynamic size.
32803282
template <class Emitter>
32813283
bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
32823284
assert(classifyPrim(E->getType()) == PT_Ptr);
@@ -3457,7 +3459,16 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
34573459
if (!this->emitArrayElemPtr(SizeT, E))
34583460
return false;
34593461

3460-
if (DynamicInit) {
3462+
if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&
3463+
DynamicInit->getType()->isArrayType()) {
3464+
QualType ElemType =
3465+
DynamicInit->getType()->getAsArrayTypeUnsafe()->getElementType();
3466+
PrimType InitT = classifyPrim(ElemType);
3467+
if (!this->visitZeroInitializer(InitT, ElemType, E))
3468+
return false;
3469+
if (!this->emitStorePop(InitT, E))
3470+
return false;
3471+
} else if (DynamicInit) {
34613472
if (std::optional<PrimType> InitT = classify(DynamicInit)) {
34623473
if (!this->visit(DynamicInit))
34633474
return false;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s
2+
// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s
3+
4+
/// This used to cause problems because the heap-allocated array
5+
/// is initialized by an ImplicitValueInitExpr of incomplete array type.
6+
7+
inline namespace {
8+
template < class _Tp >
9+
using __add_lvalue_reference_t = __add_lvalue_reference(_Tp);
10+
template < class _Tp > using __remove_extent_t = __remove_extent(_Tp);
11+
}
12+
inline namespace {
13+
template < class > class unique_ptr;
14+
template < class _Tp > struct unique_ptr< _Tp[] > {
15+
_Tp *__ptr_;
16+
17+
template <
18+
class _Tag, class _Ptr>
19+
constexpr unique_ptr(_Tag, _Ptr __ptr, unsigned) : __ptr_(__ptr){}
20+
constexpr ~unique_ptr() { delete[] __ptr_; }
21+
constexpr __add_lvalue_reference_t< _Tp >
22+
operator[](decltype(sizeof(int)) __i) {
23+
return __ptr_[__i];
24+
}};
25+
constexpr unique_ptr< int[] > make_unique(decltype(sizeof(int)) __n) {
26+
return unique_ptr< int[] >(int(), new __remove_extent_t< int>[__n](), __n);
27+
}}
28+
29+
constexpr bool test() {
30+
auto p1 = make_unique(5);
31+
(p1[0] == 0); // both-warning {{expression result unused}}
32+
return true;
33+
}
34+
static_assert(test());

0 commit comments

Comments
 (0)