Skip to content

Commit f2452d4

Browse files
committed
[clang][Interp] Implement zero-init for record types
1 parent 5b18775 commit f2452d4

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -924,8 +924,31 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
924924
if (std::optional<PrimType> T = classify(QT))
925925
return this->visitZeroInitializer(*T, QT, E);
926926

927-
if (QT->isRecordType())
928-
return false;
927+
if (QT->isRecordType()) {
928+
const RecordDecl *RD = QT->getAsRecordDecl();
929+
assert(RD);
930+
if (RD->isInvalidDecl())
931+
return false;
932+
if (RD->isUnion()) {
933+
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
934+
// object's first non-static named data member is zero-initialized
935+
// FIXME
936+
return false;
937+
}
938+
939+
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
940+
CXXRD && CXXRD->getNumVBases() > 0) {
941+
// TODO: Diagnose.
942+
return false;
943+
}
944+
945+
const Record *R = getRecord(QT);
946+
if (!R)
947+
return false;
948+
949+
assert(Initializing);
950+
return this->visitZeroRecordInitializer(R, E);
951+
}
929952

930953
if (QT->isIncompleteArrayType())
931954
return true;

clang/test/AST/Interp/records.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ struct Ints2 {
9090
int a = 10;
9191
int b;
9292
};
93-
constexpr Ints2 ints22; // both-error {{without a user-provided default constructor}} \
94-
// expected-error {{must be initialized by a constant expression}}
93+
constexpr Ints2 ints22; // both-error {{without a user-provided default constructor}}
9594

9695
constexpr Ints2 I2 = Ints2{12, 25};
9796
static_assert(I2.a == 12, "");
@@ -1409,3 +1408,15 @@ namespace VirtualBases {
14091408
static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, "");
14101409
}
14111410
}
1411+
1412+
namespace ZeroInit {
1413+
struct S3 {
1414+
S3() = default;
1415+
S3(const S3&) = default;
1416+
S3(S3&&) = default;
1417+
constexpr S3(int n) : n(n) {}
1418+
int n;
1419+
};
1420+
constexpr S3 s3d; // both-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}
1421+
static_assert(s3d.n == 0, "");
1422+
}

0 commit comments

Comments
 (0)