[clang] [CIR] Fix emission of functions referenced by member-pointer (PR #181452)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 13 18:47:18 PST 2026
https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/181452
>From ec971885ff3eacbb37da368cbacca890edce0ca5 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 13 Feb 2026 18:07:29 -0800
Subject: [PATCH 1/2] [CIR] Fix emission of functions referenced by
member-pointer
While working on attributes for these, I discovered that when a function
was referenced only via a member function pointer (see no-odr-use.cpp
test for the example that failed!), that we were incorrectly generating
the type of the function to not include the 'this' pointer. This
restores that behavior by making sure we generate the type for the
member-pointer type correctly.
---
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 3 +-
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 11 ++--
clang/test/CIR/CodeGen/no-odr-use.cpp | 17 +++++++
.../CodeGen/pointer-to-member-func-cast.cpp | 20 ++++----
.../CodeGen/pointer-to-member-func-cmp.cpp | 12 ++---
.../CIR/CodeGen/pointer-to-member-func.cpp | 50 +++++++++----------
6 files changed, 68 insertions(+), 45 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 3b88856f09842..462e73b3acc8d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1895,7 +1895,8 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
if (cxxDecl->isVirtual())
return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
- cir::FuncOp methodFuncOp = cgm.getAddrOfFunction(cxxDecl);
+ cir::FuncOp methodFuncOp =
+ cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 03d5eb860ab81..6a88cda7bf2c5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -540,13 +540,18 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
case Type::MemberPointer: {
const auto *mpt = cast<MemberPointerType>(ty);
- mlir::Type memberTy = convertType(mpt->getPointeeType());
+ NestedNameSpecifier mptNNS = mpt->getQualifier();
auto clsTy = mlir::cast<cir::RecordType>(
- convertType(QualType(mpt->getQualifier().getAsType(), 0)));
+ convertType(QualType(mptNNS.getAsType(), 0)));
if (mpt->isMemberDataPointer()) {
+ mlir::Type memberTy = convertType(mpt->getPointeeType());
resultType = cir::DataMemberType::get(memberTy, clsTy);
} else {
- auto memberFuncTy = mlir::cast<cir::FuncType>(memberTy);
+ auto memberFuncTy =
+ getFunctionType(cgm.getTypes().arrangeCXXMethodType(
+ mptNNS.getAsRecordDecl(),
+ mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
+ /*methodDecl=*/nullptr));
resultType = cir::MethodType::get(memberFuncTy, clsTy);
}
break;
diff --git a/clang/test/CIR/CodeGen/no-odr-use.cpp b/clang/test/CIR/CodeGen/no-odr-use.cpp
index 5c3476164d8f7..0458183750e68 100644
--- a/clang/test/CIR/CodeGen/no-odr-use.cpp
+++ b/clang/test/CIR/CodeGen/no-odr-use.cpp
@@ -95,6 +95,14 @@ namespace PR42276 {
using l = void (State::*)();
static constexpr l m[]{&State::f1, &State::f2};
};
+ // CIR-CXX11-LABEL: cir.func {{.*}} @_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>)
+ // CIR-CXX11-LABEL: cir.func {{.*}} @_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>)
+ //
+ // LLVM-CXX11-LABEL: declare{{.*}} @_ZN7PR422765State2f1Ev(ptr)
+ // LLVM-CXX11-LABEL: declare{{.*}} @_ZN7PR422765State2f2Ev(ptr)
+ //
+ // OG-Codegen always generates these deferred, not only if they are non-const.
+ //
// CIR-LABEL: cir.func {{.*}} @_ZN7PR422765State16syncDirtyObjectsEv(
// LLVM-LABEL: define{{.*}} void @_ZN7PR422765State16syncDirtyObjectsEv(
// OGCG-LABEL: define{{.*}} void @_ZN7PR422765State16syncDirtyObjectsEv(
@@ -110,4 +118,13 @@ namespace PR42276 {
// OGCG-CXX2A: getelementptr inbounds [2 x { i64, i64 }], ptr @_ZN7PR422765State1mE, i64 0, i64 %{{.*}}
(this->*m[i])();
}
+ // CIR-CXX2A-LABEL: cir.func {{.*}} @_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>)
+ // CIR-CXX2A-LABEL: cir.func {{.*}} @_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>)
+ //
+ // LLVM-CXX2A-LABEL: declare{{.*}} @_ZN7PR422765State2f1Ev(ptr)
+ // LLVM-CXX2A-LABEL: declare{{.*}} @_ZN7PR422765State2f2Ev(ptr)
+ //
+ // OGCG-LABEL: declare{{.*}} @_ZN7PR422765State2f1Ev(ptr{{.*}})
+ // OGCG-LABEL: declare{{.*}} @_ZN7PR422765State2f2Ev(ptr{{.*}})
+ //
}
diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp b/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp
index 1abb5241f8af9..acc77081a5bc8 100644
--- a/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp
@@ -21,7 +21,7 @@ bool memfunc_to_bool(void (Foo::*func)(int)) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z15memfunc_to_boolM3FooFviE
-// CIR-BEFORE: %{{.*}} = cir.cast member_ptr_to_bool %{{.*}} : !cir.method<!cir.func<(!s32i)> in !rec_Foo> -> !cir.bool
+// CIR-BEFORE: %{{.*}} = cir.cast member_ptr_to_bool %{{.*}} : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo> -> !cir.bool
// CIR-AFTER: cir.func {{.*}} @_Z15memfunc_to_boolM3FooFviE
// CIR-AFTER: %[[FUNC:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!rec_anon_struct>, !rec_anon_struct
@@ -50,7 +50,7 @@ auto memfunc_reinterpret(void (Foo::*func)(int)) -> void (Bar::*)() {
}
// CIR-BEFORE: cir.func {{.*}} @_Z19memfunc_reinterpretM3FooFviE
-// CIR-BEFORE: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.method<!cir.func<(!s32i)> in !rec_Foo> -> !cir.method<!cir.func<()> in !rec_Bar>
+// CIR-BEFORE: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo> -> !cir.method<!cir.func<(!cir.ptr<!rec_Bar>)> in !rec_Bar>
// CIR-AFTER: cir.func {{.*}} @_Z19memfunc_reinterpretM3FooFviE
// CIR-AFTER: %[[FUNC:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!rec_anon_struct>, !rec_anon_struct
@@ -93,8 +93,8 @@ DerivedMemFunc base_to_derived_zero_offset(Base1MemFunc ptr) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1FviE
-// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Base1>>, !cir.method<!cir.func<(!s32i)> in !rec_Base1>
-// CIR-BEFORE: %{{.*}} = cir.derived_method %[[PTR]][0] : !cir.method<!cir.func<(!s32i)> in !rec_Base1> -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>
+// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Base1>, !s32i)> in !rec_Base1>>, !cir.method<!cir.func<(!cir.ptr<!rec_Base1>, !s32i)> in !rec_Base1>
+// CIR-BEFORE: %{{.*}} = cir.derived_method %[[PTR]][0] : !cir.method<!cir.func<(!cir.ptr<!rec_Base1>, !s32i)> in !rec_Base1> -> !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>
// CIR-AFTER: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1FviE
// CIR-AFTER: %[[PTR:.*]] = cir.alloca !rec_anon_struct, !cir.ptr<!rec_anon_struct>, ["ptr", init]
@@ -125,8 +125,8 @@ DerivedMemFunc base_to_derived(Base2MemFunc ptr) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z15base_to_derivedM5Base2FviE
-// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Base2>>, !cir.method<!cir.func<(!s32i)> in !rec_Base2>
-// CIR-BEFORE: %{{.*}} = cir.derived_method %[[PTR]][16] : !cir.method<!cir.func<(!s32i)> in !rec_Base2> -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>
+// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Base2>, !s32i)> in !rec_Base2>>, !cir.method<!cir.func<(!cir.ptr<!rec_Base2>, !s32i)> in !rec_Base2>
+// CIR-BEFORE: %{{.*}} = cir.derived_method %[[PTR]][16] : !cir.method<!cir.func<(!cir.ptr<!rec_Base2>, !s32i)> in !rec_Base2> -> !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>
// CIR-AFTER: cir.func {{.*}} @_Z15base_to_derivedM5Base2FviE
// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!rec_anon_struct>, !rec_anon_struct
@@ -154,8 +154,8 @@ Base1MemFunc derived_to_base_zero_offset(DerivedMemFunc ptr) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7DerivedFviE
-// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Derived>>, !cir.method<!cir.func<(!s32i)> in !rec_Derived>
-// CIR-BEFORE: %{{.*}} = cir.base_method %[[PTR]][0] : !cir.method<!cir.func<(!s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!s32i)> in !rec_Base1>
+// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>>, !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>
+// CIR-BEFORE: %{{.*}} = cir.base_method %[[PTR]][0] : !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!cir.ptr<!rec_Base1>, !s32i)> in !rec_Base1>
// CIR-AFTER: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7DerivedFviE
// CIR-AFTER: %[[PTR:.*]] = cir.alloca !rec_anon_struct, !cir.ptr<!rec_anon_struct>, ["ptr", init]
@@ -186,8 +186,8 @@ Base2MemFunc derived_to_base(DerivedMemFunc ptr) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z15derived_to_baseM7DerivedFviE
-// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Derived>>, !cir.method<!cir.func<(!s32i)> in !rec_Derived>
-// CIR-BEFORE: %{{.*}} = cir.base_method %[[PTR]][16] : !cir.method<!cir.func<(!s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!s32i)> in !rec_Base2>
+// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>>, !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived>
+// CIR-BEFORE: %{{.*}} = cir.base_method %[[PTR]][16] : !cir.method<!cir.func<(!cir.ptr<!rec_Derived>, !s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!cir.ptr<!rec_Base2>, !s32i)> in !rec_Base2>
// CIR-AFTER: cir.func {{.*}} @_Z15derived_to_baseM7DerivedFviE
// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!rec_anon_struct>, !rec_anon_struct
diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func-cmp.cpp b/clang/test/CIR/CodeGen/pointer-to-member-func-cmp.cpp
index f00d227e97fe7..a268886d34634 100644
--- a/clang/test/CIR/CodeGen/pointer-to-member-func-cmp.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func-cmp.cpp
@@ -17,9 +17,9 @@ bool cmp_eq(void (Foo::*lhs)(int), void (Foo::*rhs)(int)) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z6cmp_eqM3FooFviES1_
-// CIR-BEFORE: %[[LHS:.*]] = cir.load{{.*}} %0 : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>
-// CIR-BEFORE: %[[RHS:.*]] = cir.load{{.*}} %1 : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>
-// CIR-BEFORE: %[[CMP:.*]] = cir.cmp(eq, %[[LHS]], %[[RHS]]) : !cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.bool
+// CIR-BEFORE: %[[LHS:.*]] = cir.load{{.*}} %0 : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>
+// CIR-BEFORE: %[[RHS:.*]] = cir.load{{.*}} %1 : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>
+// CIR-BEFORE: %[[CMP:.*]] = cir.cmp(eq, %[[LHS]], %[[RHS]]) : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.bool
// CIR-BEFORE: cir.store %[[CMP]], %{{.*}} : !cir.bool, !cir.ptr<!cir.bool>
// CIR-AFTER: @_Z6cmp_eqM3FooFviES1_
@@ -71,9 +71,9 @@ bool cmp_ne(void (Foo::*lhs)(int), void (Foo::*rhs)(int)) {
}
// CIR-BEFORE: cir.func {{.*}} @_Z6cmp_neM3FooFviES1_
-// CIR-BEFORE: %[[LHS:.*]] = cir.load{{.*}} %0 : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>
-// CIR-BEFORE: %[[RHS:.*]] = cir.load{{.*}} %1 : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>
-// CIR-BEFORE: %[[CMP:.*]] = cir.cmp(ne, %[[LHS]], %[[RHS]]) : !cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.bool
+// CIR-BEFORE: %[[LHS:.*]] = cir.load{{.*}} %0 : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>
+// CIR-BEFORE: %[[RHS:.*]] = cir.load{{.*}} %1 : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>
+// CIR-BEFORE: %[[CMP:.*]] = cir.cmp(ne, %[[LHS]], %[[RHS]]) : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.bool
// CIR-BEFORE: cir.store %[[CMP]], %{{.*}} : !cir.bool, !cir.ptr<!cir.bool>
// CIR-AFTER: cir.func {{.*}} @_Z6cmp_neM3FooFviES1_
diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
index 21238f2eda859..3f6f67f44ed4c 100644
--- a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
@@ -15,7 +15,7 @@ struct Foo {
// Global pointer to non-virtual method
void (Foo::*m1_ptr)(int) = &Foo::m1;
-// CIR-BEFORE: cir.global external @m1_ptr = #cir.method<@_ZN3Foo2m1Ei> : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.global external @m1_ptr = #cir.method<@_ZN3Foo2m1Ei> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-AFTER: cir.global external @m1_ptr = #cir.const_record<{#cir.global_view<@_ZN3Foo2m1Ei> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct
// LLVM: @m1_ptr = global { i64, i64 } { i64 ptrtoint (ptr @_ZN3Foo2m1Ei to i64), i64 0 }
// OGCG: @m1_ptr = global { i64, i64 } { i64 ptrtoint (ptr @_ZN3Foo2m1Ei to i64), i64 0 }
@@ -23,7 +23,7 @@ void (Foo::*m1_ptr)(int) = &Foo::m1;
// Global pointer to virtual method
void (Foo::*m2_ptr)(int) = &Foo::m2;
-// CIR-BEFORE: cir.global external @m2_ptr = #cir.method<vtable_offset = 0> : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.global external @m2_ptr = #cir.method<vtable_offset = 0> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-AFTER: cir.global external @m2_ptr = #cir.const_record<{#cir.int<1> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct
// LLVM: @m2_ptr = global { i64, i64 } { i64 1, i64 0 }
// OGCG: @m2_ptr = global { i64, i64 } { i64 1, i64 0 }
@@ -32,12 +32,12 @@ auto make_non_virtual() -> void (Foo::*)(int) {
return &Foo::m1;
}
-// CIR-BEFORE: cir.func {{.*}} @_Z16make_non_virtualv() -> !cir.method<!cir.func<(!s32i)> in !rec_Foo>
-// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>, ["__retval"]
-// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<@_ZN3Foo2m1Ei> : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.func {{.*}} @_Z16make_non_virtualv() -> !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>, ["__retval"]
+// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<@_ZN3Foo2m1Ei> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-BEFORE: cir.store %[[METHOD_PTR]], %[[RETVAL]]
// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL]]
-// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-AFTER: cir.func {{.*}} @_Z16make_non_virtualv() -> !rec_anon_struct {
// CIR-AFTER: %[[RETVAL:.*]] = cir.alloca !rec_anon_struct, !cir.ptr<!rec_anon_struct>, ["__retval"]
@@ -59,12 +59,12 @@ auto make_virtual() -> void (Foo::*)(int) {
return &Foo::m3;
}
-// CIR-BEFORE: cir.func {{.*}} @_Z12make_virtualv() -> !cir.method<!cir.func<(!s32i)> in !rec_Foo>
-// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>, ["__retval"]
-// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<vtable_offset = 8> : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.func {{.*}} @_Z12make_virtualv() -> !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>, ["__retval"]
+// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<vtable_offset = 8> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-BEFORE: cir.store %[[METHOD_PTR]], %[[RETVAL]]
-// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>, !cir.method<!cir.func<(!s32i)> in !rec_Foo>
-// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>, !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-AFTER: cir.func {{.*}} @_Z12make_virtualv() -> !rec_anon_struct
// CIR-AFTER: %[[RETVAL:.*]] = cir.alloca !rec_anon_struct, !cir.ptr<!rec_anon_struct>, ["__retval"]
@@ -86,12 +86,12 @@ auto make_null() -> void (Foo::*)(int) {
return nullptr;
}
-// CIR-BEFORE: cir.func {{.*}} @_Z9make_nullv() -> !cir.method<!cir.func<(!s32i)> in !rec_Foo>
-// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>, ["__retval"]
-// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<null> : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.func {{.*}} @_Z9make_nullv() -> !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+// CIR-BEFORE: %[[RETVAL:.*]] = cir.alloca !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>, ["__retval"]
+// CIR-BEFORE: %[[METHOD_PTR:.*]] = cir.const #cir.method<null> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-BEFORE: cir.store %[[METHOD_PTR]], %[[RETVAL]]
// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL]]
-// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!s32i)> in !rec_Foo>
+// CIR-BEFORE: cir.return %[[RET]] : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
// CIR-AFTER: cir.func {{.*}} @_Z9make_nullv() -> !rec_anon_struct
// CIR-AFTER: %[[RETVAL:.*]] = cir.alloca !rec_anon_struct, !cir.ptr<!rec_anon_struct>, ["__retval"]
@@ -115,10 +115,10 @@ void call(Foo *obj, void (Foo::*func)(int), int arg) {
// CIR-BEFORE: cir.func {{.*}} @_Z4callP3FooMS_FviEi
// CIR-BEFORE: %[[OBJ:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!rec_Foo>>, !cir.ptr<!rec_Foo>
-// CIR-BEFORE: %[[FUNC:.*]] = cir.load{{.*}} : !cir.ptr<!cir.method<!cir.func<(!s32i)> in !rec_Foo>>, !cir.method<!cir.func<(!s32i)> in !rec_Foo>
-// CIR-BEFORE: %[[CALLEE:.*]], %[[THIS:.*]] = cir.get_method %[[FUNC]], %[[OBJ]] : (!cir.method<!cir.func<(!s32i)> in !rec_Foo>, !cir.ptr<!rec_Foo>) -> (!cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>, !cir.ptr<!void>)
+// CIR-BEFORE: %[[FUNC:.*]] = cir.load{{.*}} : !cir.ptr<!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>>, !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+// CIR-BEFORE: %[[CALLEE:.*]], %[[THIS:.*]] = cir.get_method %[[FUNC]], %[[OBJ]] : (!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>, !cir.ptr<!rec_Foo>) -> (!cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>, !cir.ptr<!void>)
// CIR-BEFORE: %[[ARG:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
-// CIR-BEFORE: cir.call %[[CALLEE]](%[[THIS]], %[[ARG]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>, !cir.ptr<!void>, !s32i) -> ()
+// CIR-BEFORE: cir.call %[[CALLEE]](%[[THIS]], %[[ARG]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>, !cir.ptr<!void>, !s32i) -> ()
// CIR-AFTER: cir.func {{.*}} @_Z4callP3FooMS_FviEi
// CIR-AFTER: %[[OBJ:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!rec_Foo>>, !cir.ptr<!rec_Foo>
@@ -135,15 +135,15 @@ void call(Foo *obj, void (Foo::*func)(int), int arg) {
// CIR-AFTER: %[[VTABLE:.*]] = cir.load %[[VTABLE_PTR]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
// CIR-AFTER: %[[OFFSET:.*]] = cir.binop(sub, %[[METHOD_PTR]], %[[VIRT_BIT]]) : !s64i
// CIR-AFTER: %[[VTABLE_SLOT:.*]] = cir.ptr_stride %[[VTABLE]], %[[OFFSET]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
-// CIR-AFTER: %[[VIRTUAL_FN_PTR:.*]] = cir.cast bitcast %[[VTABLE_SLOT]] : !cir.ptr<!s8i> -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>>
-// CIR-AFTER: %[[VIRTUAL_FN_PTR_LOAD:.*]] = cir.load %[[VIRTUAL_FN_PTR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>>, !cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>
-// CIR-AFTER: cir.yield %[[VIRTUAL_FN_PTR_LOAD]] : !cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>
+// CIR-AFTER: %[[VIRTUAL_FN_PTR:.*]] = cir.cast bitcast %[[VTABLE_SLOT]] : !cir.ptr<!s8i> -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>>
+// CIR-AFTER: %[[VIRTUAL_FN_PTR_LOAD:.*]] = cir.load %[[VIRTUAL_FN_PTR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>>, !cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>
+// CIR-AFTER: cir.yield %[[VIRTUAL_FN_PTR_LOAD]] : !cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>
// CIR-AFTER: }, false {
-// CIR-AFTER: %[[CALLEE_PTR:.*]] = cir.cast int_to_ptr %[[METHOD_PTR]] : !s64i -> !cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>
-// CIR-AFTER: cir.yield %[[CALLEE_PTR]] : !cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>
-// CIR-AFTER: }) : (!cir.bool) -> !cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>
+// CIR-AFTER: %[[CALLEE_PTR:.*]] = cir.cast int_to_ptr %[[METHOD_PTR]] : !s64i -> !cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>
+// CIR-AFTER: cir.yield %[[CALLEE_PTR]] : !cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>
+// CIR-AFTER: }) : (!cir.bool) -> !cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>
// CIR-AFTER: %[[ARG:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
-// CIR-AFTER: cir.call %[[CALLEE]](%[[ADJUSTED_THIS]], %[[ARG]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>, !s32i)>>, !cir.ptr<!void>, !s32i) -> ()
+// CIR-AFTER: cir.call %[[CALLEE]](%[[ADJUSTED_THIS]], %[[ARG]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>, !cir.ptr<!rec_Foo>, !s32i)>>, !cir.ptr<!void>, !s32i) -> ()
// LLVM: define {{.*}} @_Z4callP3FooMS_FviEi
// LLVM: %[[OBJ:.*]] = load ptr, ptr %{{.*}}
>From f284d96ae43e09cbb4c49928fa31dd2bdd384af7 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 13 Feb 2026 18:47:06 -0800
Subject: [PATCH 2/2] Clang-format
---
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 6a88cda7bf2c5..5d6423dc0da2d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -547,11 +547,10 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
mlir::Type memberTy = convertType(mpt->getPointeeType());
resultType = cir::DataMemberType::get(memberTy, clsTy);
} else {
- auto memberFuncTy =
- getFunctionType(cgm.getTypes().arrangeCXXMethodType(
- mptNNS.getAsRecordDecl(),
- mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
- /*methodDecl=*/nullptr));
+ auto memberFuncTy = getFunctionType(cgm.getTypes().arrangeCXXMethodType(
+ mptNNS.getAsRecordDecl(),
+ mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
+ /*methodDecl=*/nullptr));
resultType = cir::MethodType::get(memberFuncTy, clsTy);
}
break;
More information about the cfe-commits
mailing list