Author: Timm Baeder
Date: 2026-06-29T12:02:15+02:00
New Revision: 0155172db818f7c3592b96bfc75cb61ae3fd57c0

URL: 
https://github.com/llvm/llvm-project/commit/0155172db818f7c3592b96bfc75cb61ae3fd57c0
DIFF: 
https://github.com/llvm/llvm-project/commit/0155172db818f7c3592b96bfc75cb61ae3fd57c0.diff

LOG: [clang][bytecode] Fix initializing record bases from init lists (#206408)

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

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/test/AST/ByteCode/cxx17.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 020b2fc0143c5..c9db50b33935e 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;
+        ++FI;
         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