Skip to content

Commit 8095b09

Browse files
committed
[clang][Interp] Array initialization via CXXConstructExpr
Differential Revision: https://reviews.llvm.org/D136920
1 parent b9e53b9 commit 8095b09

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,37 @@ bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
945945
assert(false && "default initializer for non-primitive type");
946946
}
947947

948+
return true;
949+
} else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) {
950+
const ConstantArrayType *CAT =
951+
Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
952+
assert(CAT);
953+
size_t NumElems = CAT->getSize().getZExtValue();
954+
const Function *Func = getFunction(Ctor->getConstructor());
955+
if (!Func || !Func->isConstexpr())
956+
return false;
957+
958+
// FIXME(perf): We're calling the constructor once per array element here,
959+
// in the old intepreter we had a special-case for trivial constructors.
960+
for (size_t I = 0; I != NumElems; ++I) {
961+
if (!this->emitDupPtr(Initializer))
962+
return false;
963+
if (!this->emitConstUint64(I, Initializer))
964+
return false;
965+
if (!this->emitAddOffsetUint64(Initializer))
966+
return false;
967+
if (!this->emitNarrowPtr(Initializer))
968+
return false;
969+
970+
// Constructor arguments.
971+
for (const auto *Arg : Ctor->arguments()) {
972+
if (!this->visit(Arg))
973+
return false;
974+
}
975+
976+
if (!this->emitCall(Func, Initializer))
977+
return false;
978+
}
948979
return true;
949980
}
950981

clang/test/AST/Interp/arrays.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,40 @@ namespace DefaultInit {
185185
}
186186
};
187187

188+
class A {
189+
public:
190+
int a;
191+
constexpr A(int m = 2) : a(10 + m) {}
192+
};
193+
class AU {
194+
public:
195+
int a;
196+
constexpr AU() : a(5 / 0) {} // expected-warning {{division by zero is undefined}} \
197+
// expected-note {{division by zero}} \
198+
// ref-error {{never produces a constant expression}} \
199+
// ref-note 2{{division by zero}} \
200+
// ref-warning {{division by zero is undefined}}
201+
};
202+
class B {
203+
public:
204+
A a[2];
205+
constexpr B() {}
206+
};
207+
constexpr B b;
208+
static_assert(b.a[0].a == 12, "");
209+
static_assert(b.a[1].a == 12, "");
210+
211+
class BU {
212+
public:
213+
AU a[2];
214+
constexpr BU() {} // expected-note {{in call to 'AU()'}} \
215+
// ref-note {{in call to 'AU()'}}
216+
};
217+
constexpr BU bu; // expected-error {{must be initialized by a constant expression}} \
218+
// expected-note {{in call to 'BU()'}} \
219+
// ref-error {{must be initialized by a constant expression}} \
220+
// ref-note {{in call to 'BU()'}}
221+
188222
namespace IncDec {
189223
// FIXME: Pointer arithmethic needs to be supported in inc/dec
190224
// unary operators

0 commit comments

Comments
 (0)