https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/206408

Differentiating the base initializers from the field initializers just by their 
type is obviously nonsense.

>From 5182b64b940b82f56a76c2520db8fb0895226c89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Mon, 29 Jun 2026 08:42:24 +0200
Subject: [PATCH] [clang][bytecode] Fix initializing record bases from init
 lists

---
 clang/lib/AST/ByteCode/Compiler.cpp | 52 +++++++++++++++--------------
 clang/test/AST/ByteCode/cxx17.cpp   | 16 +++++++++
 2 files changed, 43 insertions(+), 25 deletions(-)

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);
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to