[clang] f2452d4 - [clang][Interp] Implement zero-init for record types
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 29 04:02:56 PDT 2024
Author: Timm Bäder
Date: 2024-04-29T13:02:31+02:00
New Revision: f2452d4b689469b6da63d9e8ffa96eaf4b39ac5d
URL: https://github.com/llvm/llvm-project/commit/f2452d4b689469b6da63d9e8ffa96eaf4b39ac5d
DIFF: https://github.com/llvm/llvm-project/commit/f2452d4b689469b6da63d9e8ffa96eaf4b39ac5d.diff
LOG: [clang][Interp] Implement zero-init for record types
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 588ffa55c11e61..aebefd716e27cc 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -924,8 +924,31 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
if (std::optional<PrimType> T = classify(QT))
return this->visitZeroInitializer(*T, QT, E);
- if (QT->isRecordType())
- return false;
+ if (QT->isRecordType()) {
+ const RecordDecl *RD = QT->getAsRecordDecl();
+ assert(RD);
+ if (RD->isInvalidDecl())
+ return false;
+ if (RD->isUnion()) {
+ // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
+ // object's first non-static named data member is zero-initialized
+ // FIXME
+ return false;
+ }
+
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ CXXRD && CXXRD->getNumVBases() > 0) {
+ // TODO: Diagnose.
+ return false;
+ }
+
+ const Record *R = getRecord(QT);
+ if (!R)
+ return false;
+
+ assert(Initializing);
+ return this->visitZeroRecordInitializer(R, E);
+ }
if (QT->isIncompleteArrayType())
return true;
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 9307b9c090c5dd..ba5c58c96c7bf5 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -90,8 +90,7 @@ struct Ints2 {
int a = 10;
int b;
};
-constexpr Ints2 ints22; // both-error {{without a user-provided default constructor}} \
- // expected-error {{must be initialized by a constant expression}}
+constexpr Ints2 ints22; // both-error {{without a user-provided default constructor}}
constexpr Ints2 I2 = Ints2{12, 25};
static_assert(I2.a == 12, "");
@@ -1409,3 +1408,15 @@ namespace VirtualBases {
static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, "");
}
}
+
+namespace ZeroInit {
+ struct S3 {
+ S3() = default;
+ S3(const S3&) = default;
+ S3(S3&&) = default;
+ constexpr S3(int n) : n(n) {}
+ int n;
+ };
+ constexpr S3 s3d; // both-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}
+ static_assert(s3d.n == 0, "");
+}
More information about the cfe-commits
mailing list