[clang] [clang][bytecode] Fix initializing record bases from init lists (PR #206408)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 28 23:51:51 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
Differentiating the base initializers from the field initializers just by their type is obviously nonsense.
---
Full diff: https://github.com/llvm/llvm-project/pull/206408.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+27-25)
- (modified) clang/test/AST/ByteCode/cxx17.cpp (+16)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 20b110b38ff78..62dc74c3f8f9c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2153,43 +2153,45 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
}
assert(!R->isUnion());
- unsigned InitIndex = 0;
- for (const Expr *Init : Inits) {
- // Skip unnamed bitfields.
- while (InitIndex < R->getNumFields() &&
- R->getField(InitIndex)->isUnnamedBitField())
- ++InitIndex;
+ for (unsigned BI = 0; BI != R->getNumBases(); ++BI) {
+ const Expr *Init = Inits[BI];
+ const Record::Base *B = R->getBase(BI);
+ if (!this->emitGetPtrBase(B->Offset, Init))
+ return false;
+
+ if (!this->visitInitializerPop(Init))
+ return false;
+ }
+
+ unsigned FieldIndex = 0;
+ for (unsigned FI = R->getNumBases(); FI != Inits.size();) {
+ const Record::Field *FieldToInit = R->getField(FieldIndex);
+ if (FieldToInit->isUnnamedBitField()) {
+ ++FieldIndex;
+ continue;
+ }
+ const Expr *Init = Inits[FI];
// If this is a child of a DesignatedInitUpdateExpr, skip elements which
// aren't supposed to be modified.
if (isa<NoInitExpr>(Init)) {
- ++InitIndex;
+ ++FieldIndex;
continue;
}
if (OptPrimType T = classify(Init)) {
- const Record::Field *FieldToInit = R->getField(InitIndex);
if (!initPrimitiveField(FieldToInit, Init, *T))
return false;
- ++InitIndex;
- } else {
- // Initializer for a direct base class.
- if (const Record::Base *B = R->getBase(Init->getType())) {
- if (!this->emitGetPtrBase(B->Offset, Init))
- return false;
-
- if (!this->visitInitializerPop(Init))
- return false;
- // Base initializers don't increase InitIndex, since they don't count
- // into the Record's fields.
- } else {
- const Record::Field *FieldToInit = R->getField(InitIndex);
- if (!initCompositeField(FieldToInit, Init))
- return false;
- ++InitIndex;
- }
+ } else if (!initCompositeField(FieldToInit, Init)) {
+ return false;
}
+
+ ++FI;
+ ++FieldIndex;
}
+
+ assert(R->getNumVirtualBases() == 0);
+
return this->emitFinishInit(E);
}
diff --git a/clang/test/AST/ByteCode/cxx17.cpp b/clang/test/AST/ByteCode/cxx17.cpp
index 5d6e925eab32d..9168f0d34d872 100644
--- a/clang/test/AST/ByteCode/cxx17.cpp
+++ b/clang/test/AST/ByteCode/cxx17.cpp
@@ -178,3 +178,19 @@ namespace ZeroInCheckInvoke {
thread_local const auto &[s, t, u] = foo(C{}); // both-warning {{thread_local}}
#endif
}
+
+namespace InitListBaseInit {
+ struct A {
+ int m;
+ constexpr A(int m) : m(m) {}
+ };
+
+ struct B : A {
+ A a;
+ int i;
+ };
+ constexpr B b{42, 43};
+ static_assert(b.m == 42);
+ static_assert(b.a.m == 43);
+ static_assert(b.i == 0);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/206408
More information about the cfe-commits
mailing list