https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/228484

>From 64681630d072590d800cacb6160c1ba0bc099d28 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Fri, 2 Oct 2026 08:24:02 -0700
Subject: [PATCH] [CIR] Fix base-class index in const-record when there is a
 vbase

buidlRecordHelper didn't skip the 'virtual' bases like APValue did, so
the presence of a virtual base alone was enough to throw the index off.

This patch gets us slightly more in line with how this is done in
classic codegen.

It is really only reachable in C++26 because of the relaxed constexpr
rules iwth virtual bases, so it needs its own test.

Fixes: #228302
---
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp   |  7 +++++--
 .../test/CIR/CodeGen/const-init-multi-base.cpp | 18 ++++++++++++++++++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/const-init-multi-base.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 46aabba5b567a..7543bfb75abf7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -338,7 +338,8 @@ mlir::Attribute buildRecordHelper(ConstantEmitter &emitter,
                                    apOp.getNameAttr(), indices);
     }
 
-    for (auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
+    unsigned baseNo = 0;
+    for (const CXXBaseSpecifier &base : cxxrd->bases()) {
       // Our init-list implementation here just skips bases because classic
       // compiler does (see the comment in buildRecord). We perhaps COULD do
       // this, but for now we'll skip them.
@@ -350,10 +351,12 @@ mlir::Attribute buildRecordHelper(ConstantEmitter 
&emitter,
 
       const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
 
+      unsigned curBaseNo = baseNo++;
+
       if (!cirLayout.hasNonVirtualBaseCIRField(baseDecl))
         continue;
 
-      APValue baseValue = inits.getBase(idx);
+      APValue baseValue = inits.getBase(curBaseNo);
 
       const ASTRecordLayout &derivedLayout =
           cgm.getASTContext().getASTRecordLayout(cxxrd);
diff --git a/clang/test/CIR/CodeGen/const-init-multi-base.cpp 
b/clang/test/CIR/CodeGen/const-init-multi-base.cpp
new file mode 100644
index 0000000000000..aeb2368c97102
--- /dev/null
+++ b/clang/test/CIR/CodeGen/const-init-multi-base.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct X { int a; };
+struct Y { int b; };
+struct Z : X, Y { int c; };
+
+Z z = {{1}, {2}, 3};
+
+// CIR: cir.global external @z = 
#cir.const_record<{#cir.const_record<{#cir.int<1> : !s32i}> : !rec_X, 
#cir.const_record<{#cir.int<2> : !s32i}> : !rec_Y, #cir.int<3> : !s32i}> : 
!rec_Z
+
+// LLVM: @z = global %struct.Z { %struct.X { i32 1 }, %struct.Y { i32 2 }, i32 
3 }
+
+// OGCG: @z = global { i32, i32, i32 } { i32 1, i32 2, i32 3 }

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

Reply via email to