[clang] [CIR] Pass only 'this' to an inherited ctor from a virtual base (PR #229516)
Adam Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 6 11:50:01 PDT 2026
https://github.com/adams381 created https://github.com/llvm/llvm-project/pull/229516
The base-object variant of an inheriting constructor whose inherited constructor lives in a virtual base takes no arguments, since it doesn't construct that base. We were hitting an NYI here. This change passes just 'this', as classic codegen does.
Depends on #229514.
Assisted-by: Claude Code / Claude Opus 5.5
>From 9fed9dc783ffebf77cd9df03fced4f0d59d133ec Mon Sep 17 00:00:00 2001
From: Adam Smith <adams at nvidia.com>
Date: Tue, 6 Oct 2026 11:26:01 -0700
Subject: [PATCH 1/2] [CIR][NFC] Share LLVM checks with classic in
inherited-ctors.cpp
The OGCG checks repeated the LLVM checks except for one call and one
vtable store in VirtualDelegatingCtor. This change runs the LLVM prefix
on both outputs and keeps LLVMCIR/OGCG only for those two lines.
Assisted-by: Claude Code / Claude Opus 5.5
---
clang/test/CIR/CodeGen/inherited-ctors.cpp | 60 ++++------------------
1 file changed, 10 insertions(+), 50 deletions(-)
diff --git a/clang/test/CIR/CodeGen/inherited-ctors.cpp b/clang/test/CIR/CodeGen/inherited-ctors.cpp
index 2afd42d70f00d..060d0151b0093 100644
--- a/clang/test/CIR/CodeGen/inherited-ctors.cpp
+++ b/clang/test/CIR/CodeGen/inherited-ctors.cpp
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -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 -fclangir -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: FileCheck --check-prefixes=LLVM,LLVMCIR --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
-// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+// RUN: FileCheck --check-prefixes=LLVM,OGCG --input-file=%t.ll %s
struct Base {
Base(int i);
@@ -37,12 +37,14 @@ void fallsthrough() {
}
-// LLVM and OGCG check labels are identical other than the 1 difference called out.
// CIR-LABEL: cir.func no_inline dso_local @_Z20emitDelegateCallArgsv()
// CIR: cir.call @_ZN7DerivedCI14BaseEi(%{{.*}}, %{{.*}}) : (!cir.ptr<!rec_Derived>{{.*}}, !s32i{{.*}}) -> ()
// LLVM-LABEL: define dso_local void @_Z20emitDelegateCallArgsv()
// LLVM: call void @_ZN7DerivedCI14BaseEi(ptr {{.*}}, i32 {{.*}}1)
//
+// LLVM-LABEL: define linkonce_odr void @_ZN7DerivedCI14BaseEi(ptr {{.*}}, i32 {{.*}})
+// LLVM: call void @_ZN7DerivedCI24BaseEi(ptr {{.*}}, i32 {{.*}})
+//
// CIR-LABEL: cir.func no_inline dso_local @_Z26cannotEmitDelegateCallArgsv()
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca "tmp" {{.*}} init : !cir.ptr<!cir.ptr<!rec_Derived>>
// CIR: %[[FP_1_1:.*]] = cir.const #cir.fp<1.1{{.*}}> : !cir.float
@@ -93,8 +95,11 @@ void fallsthrough() {
// CIR: %[[VPTR:.*]] = cir.vtable.get_vptr %[[THIS_LOAD]] : !cir.ptr<!rec_VirtualDelegatingCtor> -> !cir.ptr<!cir.vptr>
// CIR: cir.store align(8) %[[ADDR_PT]], %[[VPTR]] : !cir.vptr, !cir.ptr<!cir.vptr>
-// LLVM: call void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}%[[THIS_LOAD]], ptr {{.*}}(i8, ptr @_ZTT21VirtualDelegatingCtor, i64 8))
-// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV21VirtualDelegatingCtor, i64 24), ptr %[[THIS_LOAD]]
+// LLVMCIR: call void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}%[[THIS_LOAD]], ptr {{.*}}(i8, ptr @_ZTT21VirtualDelegatingCtor, i64 8))
+// LLVMCIR: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV21VirtualDelegatingCtor, i64 24), ptr %[[THIS_LOAD]]
+// OGCG: %[[X_LOAD:.*]] = load i32, ptr %[[X_ALLOCA]]
+// OGCG: call void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}%[[THIS_LOAD]], ptr {{.*}}(i8, ptr @_ZTT21VirtualDelegatingCtor, i64 8), i32{{.*}}%[[X_LOAD]])
+// OGCG: store ptr getelementptr inbounds inrange(-24, 0) (i8, ptr @_ZTV21VirtualDelegatingCtor, i64 24), ptr %[[THIS_LOAD]]
//
// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN7DerivedCI24BaseEi(%{{.*}}: !cir.ptr<!rec_Derived>{{.*}}, %{{.*}}: !s32i{{.*}}) func_info<#cir.cxx_ctor<!rec_Derived, custom>>
@@ -135,48 +140,3 @@ void fallsthrough() {
// LLVM: %[[VTT:.*]] = load ptr, ptr %[[VTT_ALLOCA]]
// LLVM: %[[VTT_ADDR_LOAD:.*]] = load ptr, ptr %[[VTT]]
// LLVM: store ptr %[[VTT_ADDR_LOAD]], ptr %[[THIS]]
-
-
-// OGCG-LABEL: define dso_local void @_Z20emitDelegateCallArgsv()
-// OGCG: call void @_ZN7DerivedCI14BaseEi(ptr {{.*}}, i32 {{.*}}1)
-//
-// OGCG-LABEL: define linkonce_odr void @_ZN7DerivedCI14BaseEi(ptr {{.*}}, i32 {{.*}})
-// OGCG: call void @_ZN7DerivedCI24BaseEi(ptr {{.*}}, i32 {{.*}})
-//
-// OGCG-LABEL: define dso_local void @_Z26cannotEmitDelegateCallArgsv()
-// OGCG: %[[TMP_ALLOCA:.*]] = alloca ptr
-// OGCG: %[[TMP_LOAD:.*]] = load ptr, ptr %[[TMP_ALLOCA]]
-// OGCG: call void (ptr, float, ...) @_ZN4BaseC2Efz(ptr {{.*}}%[[TMP_LOAD]], float {{.*}}1.100000e+00, i32 {{.*}}2, double {{.*}}3.000000e+00)
-//
-// OGCG-LABEL: declare void @_ZN4BaseC2Efz(ptr {{.*}}, float {{.*}}, ...)
-//
-// OGCG-LABEL: define dso_local void @_Z12fallsthroughv()
-// OGCG: call void @_ZN21VirtualDelegatingCtorC1Ei(ptr {{.*}}, i32 {{.*}}1)
-//
-// OGCG-LABEL: define linkonce_odr void @_ZN21VirtualDelegatingCtorC1Ei(ptr {{.*}}, i32 {{.*}})
-// OGCG: %[[THIS_ALLOCA:.*]] = alloca ptr
-// OGCG: %[[X_ALLOCA:.*]] = alloca i32
-// OGCG: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
-// OGCG: %[[X_LOAD:.*]] = load i32, ptr %[[X_ALLOCA]]
-// OGCG: call void @_ZN4BaseC2Ei(ptr {{.*}}%[[THIS_LOAD]], i32 {{.*}}%[[X_LOAD]])
-// Note: see the note above for the CIR/LLVM-IR difference here.
-// OGCG: %[[X_LOAD:.*]] = load i32, ptr %[[X_ALLOCA]]
-// OGCG: call void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}%[[THIS_LOAD]], ptr {{.*}}(i8, ptr @_ZTT21VirtualDelegatingCtor, i64 8), i32{{.*}}%[[X_LOAD]])
-// OGCG: store ptr getelementptr inbounds inrange(-24, 0) (i8, ptr @_ZTV21VirtualDelegatingCtor, i64 24), ptr %[[THIS_LOAD]]
-//
-// OGCG-LABEL: define linkonce_odr void @_ZN7DerivedCI24BaseEi(ptr {{.*}}, i32 {{.*}})
-// OGCG: %[[THIS_ALLOCA:.*]] = alloca ptr
-// OGCG: %[[INT_ALLOCA:.*]] = alloca i32
-// OGCG: %[[BASE_ADDR:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
-// OGCG: %[[INT:.*]] = load i32, ptr %[[INT_ALLOCA]]
-// OGCG: call void @_ZN4BaseC2Ei(ptr {{.*}}%[[BASE_ADDR]], i32 {{.*}}[[INT]])
-//
-// OGCG-LABEL: declare void @_ZN4BaseC2Ei(ptr {{.*}}, i32 {{.*}})
-
-// OGCG-LABEL: define linkonce_odr void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}, ptr {{.*}})
-// OGCG: %[[THIS_ALLOCA:.*]] = alloca ptr
-// OGCG: %[[VTT_ALLOCA:.*]] = alloca ptr
-// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
-// OGCG: %[[VTT:.*]] = load ptr, ptr %[[VTT_ALLOCA]]
-// OGCG: %[[VTT_ADDR_LOAD:.*]] = load ptr, ptr %[[VTT]]
-// OGCG: store ptr %[[VTT_ADDR_LOAD]], ptr %[[THIS]]
>From 63c1a4517179015a3ef09e34b6b2a0f481958b75 Mon Sep 17 00:00:00 2001
From: Adam Smith <adams at nvidia.com>
Date: Tue, 6 Oct 2026 11:45:50 -0700
Subject: [PATCH 2/2] [CIR] Pass only 'this' to an inherited ctor from a
virtual base
The base-object variant of an inheriting constructor whose inherited
constructor lives in a virtual base takes no arguments, since it doesn't
construct that base. We were hitting an NYI here. This change passes
just 'this', as classic codegen does.
Assisted-by: Claude Code / Claude Opus 5.5
---
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 6 +-
clang/test/CIR/CodeGen/inherited-ctors.cpp | 121 +++++++++++++++++++++
2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 28db1763fd3cb..86c6e0ea34b1c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -1423,9 +1423,9 @@ void CIRGenFunction::emitInheritedCXXConstructorCall(
if (inheritedFromVBase &&
cgm.getTarget().getCXXABI().hasConstructorVariants()) {
- cgm.errorNYI(e->getSourceRange(), "emitInheritedCXXConstructorCall "
- "inheritedFromVBase with ctor variants");
- return;
+ // The base-object variant doesn't construct virtual bases, so the
+ // inherited constructor's arguments aren't passed.
+ ctorArgs.push_back(thisArg);
} else if (!cxxInheritedCtorInitExprArgs.empty()) {
// The inheriting constructor was inlined; just inject its arguments.
assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
diff --git a/clang/test/CIR/CodeGen/inherited-ctors.cpp b/clang/test/CIR/CodeGen/inherited-ctors.cpp
index 060d0151b0093..7145436b93c5e 100644
--- a/clang/test/CIR/CodeGen/inherited-ctors.cpp
+++ b/clang/test/CIR/CodeGen/inherited-ctors.cpp
@@ -36,6 +36,22 @@ void fallsthrough() {
VirtualDelegatingCtor noInheritingCtorHasParams{1};
}
+struct VBaseInheriting : VirtDerived {
+ using VirtDerived::VirtDerived;
+};
+
+struct IndirectVBaseInheriting : VBaseInheriting {
+ using VBaseInheriting::VBaseInheriting;
+};
+
+void inheritedFromVBase() {
+ // VirtDerived's and VBaseInheriting's inheriting constructors take only
+ // 'this' and the VTT when called to construct a base subobject.
+ VBaseInheriting delegating{1};
+ VBaseInheriting inlined{1.1f, 2, 3.0};
+ IndirectVBaseInheriting indirect{1};
+}
+
// CIR-LABEL: cir.func no_inline dso_local @_Z20emitDelegateCallArgsv()
// CIR: cir.call @_ZN7DerivedCI14BaseEi(%{{.*}}, %{{.*}}) : (!cir.ptr<!rec_Derived>{{.*}}, !s32i{{.*}}) -> ()
@@ -101,6 +117,97 @@ void fallsthrough() {
// OGCG: call void @_ZN11VirtDerivedCI24BaseEi(ptr {{.*}}%[[THIS_LOAD]], ptr {{.*}}(i8, ptr @_ZTT21VirtualDelegatingCtor, i64 8), i32{{.*}}%[[X_LOAD]])
// OGCG: store ptr getelementptr inbounds inrange(-24, 0) (i8, ptr @_ZTV21VirtualDelegatingCtor, i64 24), ptr %[[THIS_LOAD]]
//
+// CIR-LABEL: cir.func no_inline dso_local @_Z18inheritedFromVBasev()
+// CIR: %[[DELEGATING:.*]] = cir.alloca "delegating" align(8) init : !cir.ptr<!rec_VBaseInheriting>
+// CIR: %[[INLINED:.*]] = cir.alloca "inlined" align(8) init : !cir.ptr<!rec_VBaseInheriting>
+// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca "tmp" align(8) init : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>
+// CIR: %[[INDIRECT:.*]] = cir.alloca "indirect" align(8) init : !cir.ptr<!rec_IndirectVBaseInheriting>
+// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.call @_ZN15VBaseInheritingCI14BaseEi(%[[DELEGATING]], %[[ONE]]) : (!cir.ptr<!rec_VBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !s32i {llvm.noundef}) -> ()
+// CIR: %[[FP_1_1:.*]] = cir.const #cir.fp<1.100000e+00> : !cir.float
+// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: %[[THREE:.*]] = cir.const #cir.fp<3.000000e+00> : !cir.double
+// CIR: cir.store align(8) %[[INLINED]], %[[TMP_ALLOCA]] : !cir.ptr<!rec_VBaseInheriting>, !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>
+// CIR: %[[TMP_LOAD:.*]] = cir.load %[[TMP_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>, !cir.ptr<!rec_VBaseInheriting>
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[TMP_LOAD]] [0] : !cir.ptr<!rec_VBaseInheriting> -> !cir.ptr<!rec_Base>
+// CIR: cir.call @_ZN4BaseC2Efz(%[[BASE_ADDR]], %[[FP_1_1]], %[[TWO]], %[[THREE]]) : (!cir.ptr<!rec_Base> {llvm.align = 1 : i64, llvm.dereferenceable = 1 : i64, llvm.nonnull, llvm.noundef}, !cir.float {llvm.noundef}, !s32i {llvm.noundef}, !cir.double {llvm.noundef}) -> ()
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[TMP_LOAD]] [0] : !cir.ptr<!rec_VBaseInheriting> -> !cir.ptr<!rec_VirtDerived>
+// CIR: %[[VTT_ADDR:.*]] = cir.vtt.address_point @_ZTT15VBaseInheriting, offset = 1 -> !cir.ptr<!cir.ptr<!void>>
+// CIR: cir.call @_ZN11VirtDerivedCI24BaseEfz(%[[BASE_ADDR]], %[[VTT_ADDR]]) : (!cir.ptr<!rec_VirtDerived> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!cir.ptr<!void>> {llvm.noundef}) -> ()
+// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.call @_ZN23IndirectVBaseInheritingCI14BaseEi(%[[INDIRECT]], %[[ONE]]) : (!cir.ptr<!rec_IndirectVBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !s32i {llvm.noundef}) -> ()
+//
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN15VBaseInheritingCI14BaseEi(%{{[a-z0-9]+}}: !cir.ptr<!rec_VBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef} loc({{[^)]+}}), %{{[a-z0-9]+}}: !s32i {llvm.noundef} loc({{[^)]+}})) func_info<#cir.cxx_ctor<!rec_VBaseInheriting, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" align(8) init : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>
+// CIR: %[[INT_ALLOCA:.*]] = cir.alloca "" align(4) init : !cir.ptr<!s32i>
+// CIR: %[[THIS_LOAD:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>, !cir.ptr<!rec_VBaseInheriting>
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[THIS_LOAD]] [0] : !cir.ptr<!rec_VBaseInheriting> -> !cir.ptr<!rec_Base>
+// CIR: %[[INT:.*]] = cir.load align(4) %[[INT_ALLOCA]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.call @_ZN4BaseC2Ei(%[[BASE_ADDR]], %[[INT]]) : (!cir.ptr<!rec_Base> {llvm.align = 1 : i64, llvm.dereferenceable = 1 : i64, llvm.nonnull, llvm.noundef}, !s32i {llvm.noundef}) -> ()
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[THIS_LOAD]] [0] : !cir.ptr<!rec_VBaseInheriting> -> !cir.ptr<!rec_VirtDerived>
+// CIR: %[[VTT_ADDR:.*]] = cir.vtt.address_point @_ZTT15VBaseInheriting, offset = 1 -> !cir.ptr<!cir.ptr<!void>>
+// CIR: cir.call @_ZN11VirtDerivedCI24BaseEi(%[[BASE_ADDR]], %[[VTT_ADDR]]) : (!cir.ptr<!rec_VirtDerived> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!cir.ptr<!void>> {llvm.noundef}) -> ()
+//
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN11VirtDerivedCI24BaseEfz(%{{[a-z0-9]+}}: !cir.ptr<!rec_VirtDerived> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef} loc({{[^)]+}}), %{{[a-z0-9]+}}: !cir.ptr<!cir.ptr<!void>> {llvm.noundef} loc({{[^)]+}})) func_info<#cir.cxx_ctor<!rec_VirtDerived, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" align(8) init : !cir.ptr<!cir.ptr<!rec_VirtDerived>>
+// CIR: %[[VTT_ALLOCA:.*]] = cir.alloca "vtt" align(8) init : !cir.ptr<!cir.ptr<!cir.ptr<!void>>>
+// CIR: %[[THIS:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_VirtDerived>>, !cir.ptr<!rec_VirtDerived>
+// CIR-NEXT: %[[VTT:.*]] = cir.load align(8) %[[VTT_ALLOCA]] : !cir.ptr<!cir.ptr<!cir.ptr<!void>>>, !cir.ptr<!cir.ptr<!void>>
+// CIR-NEXT: %[[VTT_ADDR:.*]] = cir.vtt.address_point %[[VTT]] : !cir.ptr<!cir.ptr<!void>>, offset = 0 -> !cir.ptr<!cir.ptr<!void>>
+// CIR-NEXT: %[[VTT_ADDR_CAST:.*]] = cir.cast bitcast %[[VTT_ADDR]] : !cir.ptr<!cir.ptr<!void>> -> !cir.ptr<!cir.vptr>
+// CIR-NEXT: %[[VTT_ADDR_LOAD:.*]] = cir.load align(8) %[[VTT_ADDR_CAST]] : !cir.ptr<!cir.vptr>, !cir.vptr
+// CIR-NEXT: %[[VPTR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_VirtDerived> -> !cir.ptr<!cir.vptr>
+// CIR-NEXT: cir.store align(8) %[[VTT_ADDR_LOAD]], %[[VPTR]] : !cir.vptr, !cir.ptr<!cir.vptr>
+// CIR-NEXT: cir.return
+//
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN23IndirectVBaseInheritingCI14BaseEi(%{{[a-z0-9]+}}: !cir.ptr<!rec_IndirectVBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef} loc({{[^)]+}}), %{{[a-z0-9]+}}: !s32i {llvm.noundef} loc({{[^)]+}})) func_info<#cir.cxx_ctor<!rec_IndirectVBaseInheriting, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" align(8) init : !cir.ptr<!cir.ptr<!rec_IndirectVBaseInheriting>>
+// CIR: %[[INT_ALLOCA:.*]] = cir.alloca "" align(4) init : !cir.ptr<!s32i>
+// CIR: %[[THIS_LOAD:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_IndirectVBaseInheriting>>, !cir.ptr<!rec_IndirectVBaseInheriting>
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[THIS_LOAD]] [0] : !cir.ptr<!rec_IndirectVBaseInheriting> -> !cir.ptr<!rec_Base>
+// CIR: %[[INT:.*]] = cir.load align(4) %[[INT_ALLOCA]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.call @_ZN4BaseC2Ei(%[[BASE_ADDR]], %[[INT]]) : (!cir.ptr<!rec_Base> {llvm.align = 1 : i64, llvm.dereferenceable = 1 : i64, llvm.nonnull, llvm.noundef}, !s32i {llvm.noundef}) -> ()
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[THIS_LOAD]] [0] : !cir.ptr<!rec_IndirectVBaseInheriting> -> !cir.ptr<!rec_VBaseInheriting>
+// CIR: %[[VTT_ADDR:.*]] = cir.vtt.address_point @_ZTT23IndirectVBaseInheriting, offset = 1 -> !cir.ptr<!cir.ptr<!void>>
+// CIR: cir.call @_ZN15VBaseInheritingCI24BaseEi(%[[BASE_ADDR]], %[[VTT_ADDR]]) : (!cir.ptr<!rec_VBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!cir.ptr<!void>> {llvm.noundef}) -> ()
+//
+// LLVM-LABEL: define dso_local void @_Z18inheritedFromVBasev()
+// LLVM: %[[DELEGATING:.*]] = alloca %struct.VBaseInheriting
+// LLVM: %[[INLINED:.*]] = alloca %struct.VBaseInheriting
+// LLVM: %[[TMP_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[INDIRECT:.*]] = alloca %struct.IndirectVBaseInheriting
+// LLVM: call void @_ZN15VBaseInheritingCI14BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %[[DELEGATING]], i32 noundef 1)
+// LLVM: store ptr %[[INLINED]], ptr %[[TMP_ALLOCA]]
+// LLVM: %[[TMP_LOAD:.*]] = load ptr, ptr %[[TMP_ALLOCA]]
+// LLVM: call void (ptr, float, ...) @_ZN4BaseC2Efz(ptr noundef nonnull align 1 dereferenceable(1) %[[TMP_LOAD]], float noundef 1.100000e+00, i32 noundef 2, double noundef 3.000000e+00)
+// LLVM: call void @_ZN11VirtDerivedCI24BaseEfz(ptr noundef nonnull align 8 dereferenceable(8) %[[TMP_LOAD]], ptr noundef getelementptr inbounds nuw (i8, ptr @_ZTT15VBaseInheriting, i64 8))
+// LLVM: call void @_ZN23IndirectVBaseInheritingCI14BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %[[INDIRECT]], i32 noundef 1)
+//
+// LLVM-LABEL: define linkonce_odr void @_ZN15VBaseInheritingCI14BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %{{[a-z0-9]+}}, i32 noundef %{{[a-z0-9]+}})
+// LLVM: %[[THIS_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[INT_ALLOCA:.*]] = alloca i32
+// LLVM: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
+// LLVM: %[[INT:.*]] = load i32, ptr %[[INT_ALLOCA]]
+// LLVM: call void @_ZN4BaseC2Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[THIS_LOAD]], i32 noundef %[[INT]])
+// LLVM: call void @_ZN11VirtDerivedCI24BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %[[THIS_LOAD]], ptr noundef getelementptr inbounds nuw (i8, ptr @_ZTT15VBaseInheriting, i64 8))
+//
+// LLVM-LABEL: define linkonce_odr void @_ZN11VirtDerivedCI24BaseEfz(ptr noundef nonnull align 8 dereferenceable(8) %{{[a-z0-9]+}}, ptr noundef %{{[a-z0-9]+}})
+// LLVM: %[[THIS_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[VTT_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
+// LLVM-NEXT: %[[VTT:.*]] = load ptr, ptr %[[VTT_ALLOCA]]
+// LLVM-NEXT: %[[VTT_ADDR_LOAD:.*]] = load ptr, ptr %[[VTT]]
+// LLVM-NEXT: store ptr %[[VTT_ADDR_LOAD]], ptr %[[THIS]]
+// LLVM-NEXT: ret void
+//
+// LLVM-LABEL: define linkonce_odr void @_ZN23IndirectVBaseInheritingCI14BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %{{[a-z0-9]+}}, i32 noundef %{{[a-z0-9]+}})
+// LLVM: %[[THIS_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[INT_ALLOCA:.*]] = alloca i32
+// LLVM: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
+// LLVM: %[[INT:.*]] = load i32, ptr %[[INT_ALLOCA]]
+// LLVM: call void @_ZN4BaseC2Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[THIS_LOAD]], i32 noundef %[[INT]])
+// LLVM: call void @_ZN15VBaseInheritingCI24BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %[[THIS_LOAD]], ptr noundef getelementptr inbounds nuw (i8, ptr @_ZTT23IndirectVBaseInheriting, i64 8))
+//
// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN7DerivedCI24BaseEi(%{{.*}}: !cir.ptr<!rec_Derived>{{.*}}, %{{.*}}: !s32i{{.*}}) func_info<#cir.cxx_ctor<!rec_Derived, custom>>
// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" {{.*}} init : !cir.ptr<!cir.ptr<!rec_Derived>>
@@ -140,3 +247,17 @@ void fallsthrough() {
// LLVM: %[[VTT:.*]] = load ptr, ptr %[[VTT_ALLOCA]]
// LLVM: %[[VTT_ADDR_LOAD:.*]] = load ptr, ptr %[[VTT]]
// LLVM: store ptr %[[VTT_ADDR_LOAD]], ptr %[[THIS]]
+
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN15VBaseInheritingCI24BaseEi(%{{[a-z0-9]+}}: !cir.ptr<!rec_VBaseInheriting> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef} loc({{[^)]+}}), %{{[a-z0-9]+}}: !cir.ptr<!cir.ptr<!void>> {llvm.noundef} loc({{[^)]+}})) func_info<#cir.cxx_ctor<!rec_VBaseInheriting, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" align(8) init : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>
+// CIR: %[[VTT_ALLOCA:.*]] = cir.alloca "vtt" align(8) init : !cir.ptr<!cir.ptr<!cir.ptr<!void>>>
+// CIR: %[[THIS:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_VBaseInheriting>>, !cir.ptr<!rec_VBaseInheriting>
+// CIR-NEXT: %[[VTT:.*]] = cir.load align(8) %[[VTT_ALLOCA]] : !cir.ptr<!cir.ptr<!cir.ptr<!void>>>, !cir.ptr<!cir.ptr<!void>>
+// CIR-NEXT: %[[BASE_ADDR:.*]] = cir.base_class_addr nonnull %[[THIS]] [0] : !cir.ptr<!rec_VBaseInheriting> -> !cir.ptr<!rec_VirtDerived>
+// CIR-NEXT: %[[SUB_VTT:.*]] = cir.vtt.address_point %[[VTT]] : !cir.ptr<!cir.ptr<!void>>, offset = 1 -> !cir.ptr<!cir.ptr<!void>>
+// CIR-NEXT: cir.call @_ZN11VirtDerivedCI24BaseEi(%[[BASE_ADDR]], %[[SUB_VTT]]) : (!cir.ptr<!rec_VirtDerived> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!cir.ptr<!void>> {llvm.noundef}) -> ()
+
+// LLVM-LABEL: define linkonce_odr void @_ZN15VBaseInheritingCI24BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %{{[a-z0-9]+}}, ptr noundef %{{[a-z0-9]+}})
+// LLVM: %[[THIS_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
+// LLVM: call void @_ZN11VirtDerivedCI24BaseEi(ptr noundef nonnull align 8 dereferenceable(8) %[[THIS]], ptr noundef %{{[a-z0-9]+}})
More information about the cfe-commits
mailing list