https://github.com/Perdixky updated https://github.com/llvm/llvm-project/pull/184011
>From e7d6d88c49bca11d9c8855ffe4b894830dac6977 Mon Sep 17 00:00:00 2001 From: Nikita B <[email protected]> Date: Thu, 16 Oct 2025 21:12:14 +0200 Subject: [PATCH 01/11] [CIR] vTableClassNameForType: return correct VTableClass name for Type::ObjCObjectPointer, Type::Pointer Signed-off-by: Nikita B <[email protected]> --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index a18e2b91b1dd4..65b9ae9077e27 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -1009,8 +1009,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { case Type::ObjCObjectPointer: case Type::Pointer: - cgm.errorNYI("VTableClassNameForType: __pointer_type_info"); - break; + return "_ZTVN10__cxxabiv119__pointer_type_infoE"; case Type::MemberPointer: cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info"); >From 2168aa6f77e87ab8f1a72179d628d9cda94e14a7 Mon Sep 17 00:00:00 2001 From: Nikita B <[email protected]> Date: Sat, 18 Oct 2025 13:15:23 +0200 Subject: [PATCH 02/11] [CIR] vTableClassNameForType: add throw test for Type::Pointer Signed-off-by: Nikita B <[email protected]> --- clang/test/CIR/CodeGen/throws.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/clang/test/CIR/CodeGen/throws.cpp b/clang/test/CIR/CodeGen/throws.cpp index 53af1efc22cd4..bedb09a2d82ec 100644 --- a/clang/test/CIR/CodeGen/throws.cpp +++ b/clang/test/CIR/CodeGen/throws.cpp @@ -244,3 +244,32 @@ void throw_enum_class_expr() { // OGCG: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16 // OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIZ21throw_enum_class_exprvE4Test, ptr null) // OGCG: unreachable + +void throw_pointer_type() { + static int var = 42; + int *ptr = &var; + throw ptr; +} + +// CIR: %[[PTR_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["ptr", init] +// CIR: %[[VAR_ADDR:.*]] = cir.get_global @_ZZ18throw_pointer_typevE3var : !cir.ptr<!s32i> +// CIR: cir.store{{.*}} %[[VAR_ADDR]], %[[PTR_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 8 -> !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[TMP_PTR:.*]] = cir.load{{.*}} %[[PTR_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: cir.store{{.*}} %[[TMP_PTR]], %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, @_ZTIPi +// CIR: cir.unreachable + +// LLVM: %[[PTR_ADDR:.*]] = alloca ptr,{{.*}} align 8 +// LLVM: store ptr @_ZZ18throw_pointer_typevE3var, ptr %[[PTR_ADDR]], align 8 +// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8) +// LLVM: %[[TMP_PTR:.*]] = load ptr, ptr %[[PTR_ADDR]], align 8 +// LLVM: store ptr %[[TMP_PTR]], ptr %[[EXCEPTION_ADDR]], align 16 +// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIPi, ptr null) + +// OGCG: %[[PTR_ADDR:.*]] = alloca ptr, align 8 +// OGCG: store ptr @_ZZ18throw_pointer_typevE3var, ptr %[[PTR_ADDR]], align 8 +// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8) +// OGCG: %[[TMP_PTR:.*]] = load ptr, ptr %[[PTR_ADDR]], align 8 +// OGCG: store ptr %[[TMP_PTR]], ptr %[[EXCEPTION_ADDR]], align 16 +// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIPi, ptr null) >From 1811f74074439a336c105eabcb6dfe7a965e426a Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Sun, 1 Mar 2026 23:41:35 +0800 Subject: [PATCH 03/11] [CIR] Implement pointer type RTTI (buildPointerTypeInfo) Add extractPBaseFlags() and buildPointerTypeInfo() to CIRGenItaniumCXXABI, implementing __pointer_type_info emission per Itanium C++ ABI 2.9.4p7. This handles PTI_Const/Volatile/Restrict/Incomplete/Noexcept flags and recursively emits the pointee type info. Also fix vTableClassNameForType for FunctionProto/FunctionNoProto to return the correct __function_type_info vtable name instead of errorNYI, enabling RTTI for pointer-to-function types. Add clang/test/CIR/CodeGen/rtti-qualfn.cpp to test throwing a pointer to a noexcept function, verifying the PTI_Noexcept flag (0x40 = 64) is set. --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 68 ++++++++++++++++++- clang/test/CIR/CodeGen/rtti-qualfn.cpp | 36 ++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 clang/test/CIR/CodeGen/rtti-qualfn.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 65b9ae9077e27..2f9400943c235 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -22,6 +22,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/GlobalDecl.h" +#include "clang/AST/TypeBase.h" #include "clang/AST/VTableBuilder.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/Support/ErrorHandling.h" @@ -557,6 +558,10 @@ class CIRGenItaniumRTTIBuilder { /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd); + /// Build an abi::__pointer_type_info, used for pointer types, according + /// to the Itanium API, 2.9.4p7. + void buildPointerTypeInfo(mlir::Location loc, QualType ty); + public: CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm) : cgm(cgm), cxxABI(abi) {} @@ -924,6 +929,31 @@ static bool containsIncompleteClassType(QualType ty) { return false; } +static unsigned extractPBaseFlags(const ASTContext &ctx, QualType &ty) { + unsigned flags = 0; + + if (ty.isConstQualified()) + flags |= PTI_Const; + if (ty.isVolatileQualified()) + flags |= PTI_Volatile; + if (ty.isRestrictQualified()) + flags |= PTI_Restrict; + + ty = ty.getUnqualifiedType(); + + if (containsIncompleteClassType(ty)) + flags |= PTI_Incomplete; + + if (const auto *proto = ty->getAs<FunctionProtoType>()) { + if (proto->isNothrow()) { + flags |= PTI_Noexcept; + ty = ctx.getFunctionTypeWithExceptionSpec(ty, EST_None); + } + } + + return flags; +} + const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { // abi::__class_type_info. static const char *const classTypeInfo = @@ -978,8 +1008,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { case Type::FunctionNoProto: case Type::FunctionProto: - cgm.errorNYI("VTableClassNameForType: __function_type_info"); - break; + return "_ZTVN10__cxxabiv120__function_type_infoE"; case Type::Enum: return "_ZTVN10__cxxabiv116__enum_type_infoE"; @@ -1276,6 +1305,38 @@ void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc, } } +void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, + QualType ty) { + // Itanium C++ ABI 2.9.4p7: + // abi::__pbase_type_info is a base for both pointer types and + // pointer-to-member types. It adds two data members: + // + // class __pbase_type_info : public std::type_info { + // public: + // unsigned int __flags; + // const std::type_info *__pointee; + // + // enum __masks { + // __const_mask = 0x1, + // __volatile_mask = 0x2, + // __restrict_mask = 0x4, + // __incomplete_mask = 0x8, + // __incomplete_class_mask = 0x10, + // __transaction_safe_mask = 0x20 + // __noexcept_mask = 0x40 + // }; + // }; + const unsigned int flags = extractPBaseFlags(cgm.getASTContext(), ty); + + auto unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); + mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); + fields.push_back(flagsAttr); + + mlir::Attribute pointeeTypeInfo = + CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, ty); + fields.push_back(pointeeTypeInfo); +} + mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc, QualType ty) { // We want to operate on the canonical type. @@ -1437,7 +1498,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo( break; case Type::Pointer: - cgm.errorNYI("buildTypeInfo: Pointer"); + // We need to get the type info for the pointee type. + buildPointerTypeInfo(loc, cast<PointerType>(ty)->getPointeeType()); break; case Type::MemberPointer: diff --git a/clang/test/CIR/CodeGen/rtti-qualfn.cpp b/clang/test/CIR/CodeGen/rtti-qualfn.cpp new file mode 100644 index 0000000000000..acd732f65136b --- /dev/null +++ b/clang/test/CIR/CodeGen/rtti-qualfn.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +// Test that throwing a pointer to a noexcept function produces correct RTTI +// with the PTI_Noexcept flag (0x40 = 64) set in the __pointer_type_info. + +void f() noexcept { + throw f; +} + +// The pointee type _ZTIFvvE (function type info for void()) must be emitted +// using the __function_type_info vtable. +// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> +// CIR-DAG: cir.global {{.*}} @_ZTIFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__function_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSFvvE> : !cir.ptr<!u8i>}> + +// The pointer type info _ZTIPDoFvvE must include flag 64 (PTI_Noexcept). +// CIR-DAG: cir.global {{.*}} @_ZTSPDoFvvE = #cir.const_array<"PDoFvvE" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7> +// CIR-DAG: cir.global {{.*}} @_ZTIPDoFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv119__pointer_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSPDoFvvE> : !cir.ptr<!u8i>, #cir.int<64> : !u32i, #cir.global_view<@_ZTIFvvE> : !cir.ptr<!u8i>}> + +// CIR: cir.throw %{{.*}} : !cir.ptr<!cir.ptr<!cir.func<()>>>, @_ZTIPDoFvvE + +// LLVM-DAG: @_ZTSFvvE = linkonce_odr global [4 x i8] c"FvvE" +// LLVM-DAG: @_ZTIFvvE = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE } +// LLVM-DAG: @_ZTSPDoFvvE = linkonce_odr global [7 x i8] c"PDoFvvE" +// LLVM-DAG: @_ZTIPDoFvvE = constant { ptr, ptr, i32, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 16), ptr @_ZTSPDoFvvE, i32 64, ptr @_ZTIFvvE } +// LLVM: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIPDoFvvE, ptr null) + +// OGCG-DAG: @_ZTSFvvE = linkonce_odr constant [5 x i8] c"FvvE\00", comdat +// OGCG-DAG: @_ZTIFvvE = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 2), ptr @_ZTSFvvE }, comdat +// OGCG-DAG: @_ZTSPDoFvvE = linkonce_odr constant [8 x i8] c"PDoFvvE\00", comdat +// OGCG-DAG: @_ZTIPDoFvvE = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2), ptr @_ZTSPDoFvvE, i32 64, ptr @_ZTIFvvE }, comdat +// OGCG: invoke void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIPDoFvvE, ptr null) >From 497b5d4571df4649a55e592af1c63c7c0245a561 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Mon, 2 Mar 2026 08:55:10 +0800 Subject: [PATCH 04/11] [CIR] Fix typo --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 2f9400943c235..302c64fc25db0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -559,7 +559,7 @@ class CIRGenItaniumRTTIBuilder { void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd); /// Build an abi::__pointer_type_info, used for pointer types, according - /// to the Itanium API, 2.9.4p7. + /// to the Itanium C++ ABI, 2.9.4p7. void buildPointerTypeInfo(mlir::Location loc, QualType ty); public: >From cf8ecf78b06a738dfbed537203be9da1134c81dd Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Mon, 2 Mar 2026 15:38:27 +0800 Subject: [PATCH 05/11] [CIR] Implement MemberPointer/ObjCObjectPointer RTTI Add buildPointerToMemberTypeInfo() to CIRGenItaniumCXXABI to emit __pointer_to_member_type_info which carries three fields: flags, pointee and context (the containing class type) per Itanium C++ ABI 2.9.5p7. Also fix vTableClassNameForType to return the correct vtable names for Type::MemberPointer and Type::ObjCObjectPointer. Add test for pointer-to-member RTTI. ObjCObjectPointer test is omitted because CIR does not yet support ObjC AST codegen. --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 39 ++++++++- .../test/CIR/CodeGen/rtti-member-pointer.cpp | 79 +++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGen/rtti-member-pointer.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 302c64fc25db0..2b6f6e738e8f2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -562,6 +562,10 @@ class CIRGenItaniumRTTIBuilder { /// to the Itanium C++ ABI, 2.9.4p7. void buildPointerTypeInfo(mlir::Location loc, QualType ty); + /// Build an abi::__pointer_to_member_type_info, used for pointer to member + /// types, according to the Itanium C++ ABI, 2.9.4p9. + void buildPointerToMemberTypeInfo(mlir::Location loc, const MemberPointerType *ty); + public: CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm) : cgm(cgm), cxxABI(abi) {} @@ -1041,7 +1045,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { return "_ZTVN10__cxxabiv119__pointer_type_infoE"; case Type::MemberPointer: - cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info"); + return "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; break; case Type::HLSLAttributedResource: @@ -1337,6 +1341,37 @@ void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, fields.push_back(pointeeTypeInfo); } +void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo( + mlir::Location loc, const MemberPointerType *ty) { + + // The abi::__pointer_to_member_type_info type adds one field to abi::__pbase_type_info: + // + // class __pointer_to_member_type_info : public __pbase_type_info { + // public: + // const abi::__class_type_info *__context; + // }; + QualType pointeeTy = ty->getPointeeType(); + + unsigned flags = extractPBaseFlags(cgm.getASTContext(), pointeeTy); + + const auto *rd = ty->getMostRecentCXXRecordDecl(); + if (!rd->hasDefinition()) + flags |= PTI_ContainingClassIncomplete; + + auto unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); + mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); + fields.push_back(flagsAttr); + + mlir::Attribute pointeeTypeInfo = + CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, pointeeTy); + fields.push_back(pointeeTypeInfo); + + CanQualType contextTy = cgm.getASTContext().getCanonicalTagType(rd); + mlir::Attribute classTypeInfo = + CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, contextTy); + fields.push_back(classTypeInfo); +} + mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc, QualType ty) { // We want to operate on the canonical type. @@ -1503,7 +1538,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo( break; case Type::MemberPointer: - cgm.errorNYI("buildTypeInfo: MemberPointer"); + buildPointerToMemberTypeInfo(loc, cast<MemberPointerType>(ty)); break; case Type::Atomic: diff --git a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp new file mode 100644 index 0000000000000..4b863d93e259f --- /dev/null +++ b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +// Test RTTI emission for pointer-to-member types (abi::__pointer_to_member_type_info). +// Each descriptor must use the __pointer_to_member_type_info vtable and carry +// three extra fields beyond the standard type_info header: +// __flags (unsigned int) +// __pointee (const type_info* for the pointed-to type) +// __context (const __class_type_info* for the containing class) + +struct A { + int data; + void func(); +}; + +// --- Test 1: data member pointer (int A::*) --- + +void throw_data_member_ptr() { + int A::*p = &A::data; + throw p; +} + +// Class A has no bases, so it uses __class_type_info. +// CIR-DAG: cir.global {{.*}} @_ZTS1A = #cir.const_array<"1A" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2> +// CIR-DAG: cir.global {{.*}} @_ZTI1A = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1A> : !cir.ptr<!u8i>}> + +// The type name for "int A::*" is "M1Ai". +// CIR-DAG: cir.global {{.*}} @_ZTSM1Ai = #cir.const_array<"M1Ai" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> + +// The member-pointer type info must use the __pointer_to_member_type_info vtable, +// flags=0 (int has no cv-qualifiers), pointee=int (_ZTIi), context=A (_ZTI1A). +// CIR-DAG: cir.global {{.*}} @_ZTIM1Ai = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1Ai> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> + +// CIR-DAG: cir.throw %{{.*}} : !cir.ptr<!s64i>, @_ZTIM1Ai + +// LLVM-DAG: @_ZTSM1Ai = linkonce_odr global [4 x i8] c"M1Ai" +// LLVM-DAG: @_ZTS1A = linkonce_odr global [2 x i8] c"1A" +// LLVM-DAG: @_ZTI1A = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS1A } +// LLVM-DAG: @_ZTIM1Ai = constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1Ai, i32 0, ptr @_ZTIi, ptr @_ZTI1A } +// LLVM-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1Ai, ptr null) + +// OGCG-DAG: @_ZTSM1Ai = linkonce_odr constant [5 x i8] c"M1Ai\00", comdat +// OGCG-DAG: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat +// OGCG-DAG: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat +// OGCG-DAG: @_ZTIM1Ai = linkonce_odr constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2), ptr @_ZTSM1Ai, i32 0, ptr @_ZTIi, ptr @_ZTI1A }, comdat +// OGCG-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1Ai, ptr null) + +// --- Test 2: member function pointer (void (A::*)()) --- + +void throw_member_fn_ptr() { + void (A::*p)() = &A::func; + throw p; +} + +// The type name for "void (A::*)()" is "M1AFvvE". +// CIR-DAG: cir.global {{.*}} @_ZTSM1AFvvE = #cir.const_array<"M1AFvvE" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7> + +// The pointee "void()" is a function type, using __function_type_info. +// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> +// CIR-DAG: cir.global {{.*}} @_ZTIFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__function_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSFvvE> : !cir.ptr<!u8i>}> + +// flags=0, pointee=void() (_ZTIFvvE), context=A (_ZTI1A). +// CIR-DAG: cir.global {{.*}} @_ZTIM1AFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1AFvvE> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIFvvE> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> + +// LLVM-DAG: @_ZTSM1AFvvE = linkonce_odr global [7 x i8] c"M1AFvvE" +// LLVM-DAG: @_ZTSFvvE = linkonce_odr global [4 x i8] c"FvvE" +// LLVM-DAG: @_ZTIFvvE = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE } +// LLVM-DAG: @_ZTIM1AFvvE = constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1AFvvE, i32 0, ptr @_ZTIFvvE, ptr @_ZTI1A } +// LLVM-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1AFvvE, ptr null) + +// OGCG-DAG: @_ZTSM1AFvvE = linkonce_odr constant [8 x i8] c"M1AFvvE\00", comdat +// OGCG-DAG: @_ZTSFvvE = linkonce_odr constant [5 x i8] c"FvvE\00", comdat +// OGCG-DAG: @_ZTIFvvE = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 2), ptr @_ZTSFvvE }, comdat +// OGCG-DAG: @_ZTIM1AFvvE = linkonce_odr constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2), ptr @_ZTSM1AFvvE, i32 0, ptr @_ZTIFvvE, ptr @_ZTI1A }, comdat +// OGCG-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1AFvvE, ptr null) >From 17017871c28f0624807ecd32c2d29eebd06f7755 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Mon, 2 Mar 2026 20:01:07 +0800 Subject: [PATCH 06/11] Update clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp Co-authored-by: Copilot <[email protected]> --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 2b6f6e738e8f2..f7b16675f34e7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -1046,7 +1046,6 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { case Type::MemberPointer: return "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; - break; case Type::HLSLAttributedResource: case Type::HLSLInlineSpirv: >From a3c8d965c7dc982bd14b3138c64f282730381a98 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Tue, 3 Mar 2026 10:03:52 +0800 Subject: [PATCH 07/11] [CIR] Fix missing 'this' pointer in member function type --- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 223b53731359a..4e0faa6492824 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1603,7 +1603,10 @@ mlir::Value CIRGenModule::emitMemberPointerConstant(const UnaryOperator *e) { return cir::ConstantOp::create( builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl)); - cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl); + const CIRGenFunctionInfo &fi = + getTypes().arrangeCXXMethodDeclaration(methodDecl); + cir::FuncType funcTy = getTypes().getFunctionType(fi); + cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl, funcTy); return cir::ConstantOp::create(builder, loc, builder.getMethodAttr(ty, methodFuncOp)); } >From ac22b35bb407f6b824015c7f33de858f22f5cd50 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Tue, 3 Mar 2026 10:40:12 +0800 Subject: [PATCH 08/11] [CIR] Format --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index f7b16675f34e7..4e23dc92885b8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -564,7 +564,8 @@ class CIRGenItaniumRTTIBuilder { /// Build an abi::__pointer_to_member_type_info, used for pointer to member /// types, according to the Itanium C++ ABI, 2.9.4p9. - void buildPointerToMemberTypeInfo(mlir::Location loc, const MemberPointerType *ty); + void buildPointerToMemberTypeInfo(mlir::Location loc, + const MemberPointerType *ty); public: CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm) @@ -1343,7 +1344,8 @@ void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo( mlir::Location loc, const MemberPointerType *ty) { - // The abi::__pointer_to_member_type_info type adds one field to abi::__pbase_type_info: + // The abi::__pointer_to_member_type_info type adds one field to + // abi::__pbase_type_info: // // class __pointer_to_member_type_info : public __pbase_type_info { // public: >From 2dfd2bd854a397d0c40310473aac04d4cc668a16 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Wed, 11 Mar 2026 09:19:49 +0800 Subject: [PATCH 09/11] [CIR] Use explicit type instead of auto --- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 4e23dc92885b8..08e57db0060aa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -1332,7 +1332,7 @@ void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, // }; const unsigned int flags = extractPBaseFlags(cgm.getASTContext(), ty); - auto unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); + mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); fields.push_back(flagsAttr); @@ -1359,7 +1359,7 @@ void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo( if (!rd->hasDefinition()) flags |= PTI_ContainingClassIncomplete; - auto unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); + mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); fields.push_back(flagsAttr); >From 9b5205f3880a1b4c4fa3f29f6a16e12ee2209330 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Wed, 11 Mar 2026 09:19:49 +0800 Subject: [PATCH 10/11] [CIR] Remove redundant comments --- .../test/CIR/CodeGen/rtti-member-pointer.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp index 4b863d93e259f..a4296cc6c6289 100644 --- a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp +++ b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp @@ -5,34 +5,20 @@ // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG -// Test RTTI emission for pointer-to-member types (abi::__pointer_to_member_type_info). -// Each descriptor must use the __pointer_to_member_type_info vtable and carry -// three extra fields beyond the standard type_info header: -// __flags (unsigned int) -// __pointee (const type_info* for the pointed-to type) -// __context (const __class_type_info* for the containing class) - struct A { int data; void func(); }; -// --- Test 1: data member pointer (int A::*) --- - void throw_data_member_ptr() { int A::*p = &A::data; throw p; } -// Class A has no bases, so it uses __class_type_info. // CIR-DAG: cir.global {{.*}} @_ZTS1A = #cir.const_array<"1A" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2> // CIR-DAG: cir.global {{.*}} @_ZTI1A = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1A> : !cir.ptr<!u8i>}> -// The type name for "int A::*" is "M1Ai". // CIR-DAG: cir.global {{.*}} @_ZTSM1Ai = #cir.const_array<"M1Ai" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> - -// The member-pointer type info must use the __pointer_to_member_type_info vtable, -// flags=0 (int has no cv-qualifiers), pointee=int (_ZTIi), context=A (_ZTI1A). // CIR-DAG: cir.global {{.*}} @_ZTIM1Ai = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1Ai> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> // CIR-DAG: cir.throw %{{.*}} : !cir.ptr<!s64i>, @_ZTIM1Ai @@ -49,21 +35,14 @@ void throw_data_member_ptr() { // OGCG-DAG: @_ZTIM1Ai = linkonce_odr constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2), ptr @_ZTSM1Ai, i32 0, ptr @_ZTIi, ptr @_ZTI1A }, comdat // OGCG-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1Ai, ptr null) -// --- Test 2: member function pointer (void (A::*)()) --- - void throw_member_fn_ptr() { void (A::*p)() = &A::func; throw p; } -// The type name for "void (A::*)()" is "M1AFvvE". // CIR-DAG: cir.global {{.*}} @_ZTSM1AFvvE = #cir.const_array<"M1AFvvE" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7> - -// The pointee "void()" is a function type, using __function_type_info. // CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> // CIR-DAG: cir.global {{.*}} @_ZTIFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__function_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSFvvE> : !cir.ptr<!u8i>}> - -// flags=0, pointee=void() (_ZTIFvvE), context=A (_ZTI1A). // CIR-DAG: cir.global {{.*}} @_ZTIM1AFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1AFvvE> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIFvvE> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> // LLVM-DAG: @_ZTSM1AFvvE = linkonce_odr global [7 x i8] c"M1AFvvE" >From 4c9a13c6814311602c323d77eeee68b4735e9b83 Mon Sep 17 00:00:00 2001 From: Perdixky <[email protected]> Date: Sat, 14 Mar 2026 09:10:14 +0800 Subject: [PATCH 11/11] [CIR] Fix RTTI type name string checks to include null terminator Update CIR FileCheck patterns in rtti-qualfn.cpp and rtti-member-pointer.cpp to reflect that RTTI type name strings (_ZTS*) are now emitted with a null terminator, represented as trailing_zeros with array size N+1. This matches the behavior of the traditional codegen (OGCG). --- clang/test/CIR/CodeGen/rtti-member-pointer.cpp | 8 ++++---- clang/test/CIR/CodeGen/rtti-qualfn.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp index a4296cc6c6289..0be750fd8fada 100644 --- a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp +++ b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp @@ -15,10 +15,10 @@ void throw_data_member_ptr() { throw p; } -// CIR-DAG: cir.global {{.*}} @_ZTS1A = #cir.const_array<"1A" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2> +// CIR-DAG: cir.global {{.*}} @_ZTS1A = #cir.const_array<"1A" : !cir.array<!s8i x 2>, trailing_zeros> : !cir.array<!s8i x 3> // CIR-DAG: cir.global {{.*}} @_ZTI1A = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1A> : !cir.ptr<!u8i>}> -// CIR-DAG: cir.global {{.*}} @_ZTSM1Ai = #cir.const_array<"M1Ai" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> +// CIR-DAG: cir.global {{.*}} @_ZTSM1Ai = #cir.const_array<"M1Ai" : !cir.array<!s8i x 4>, trailing_zeros> : !cir.array<!s8i x 5> // CIR-DAG: cir.global {{.*}} @_ZTIM1Ai = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1Ai> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> // CIR-DAG: cir.throw %{{.*}} : !cir.ptr<!s64i>, @_ZTIM1Ai @@ -40,8 +40,8 @@ void throw_member_fn_ptr() { throw p; } -// CIR-DAG: cir.global {{.*}} @_ZTSM1AFvvE = #cir.const_array<"M1AFvvE" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7> -// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> +// CIR-DAG: cir.global {{.*}} @_ZTSM1AFvvE = #cir.const_array<"M1AFvvE" : !cir.array<!s8i x 7>, trailing_zeros> : !cir.array<!s8i x 8> +// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>, trailing_zeros> : !cir.array<!s8i x 5> // CIR-DAG: cir.global {{.*}} @_ZTIFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__function_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSFvvE> : !cir.ptr<!u8i>}> // CIR-DAG: cir.global {{.*}} @_ZTIM1AFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSM1AFvvE> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTIFvvE> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> diff --git a/clang/test/CIR/CodeGen/rtti-qualfn.cpp b/clang/test/CIR/CodeGen/rtti-qualfn.cpp index acd732f65136b..159cef1cf0256 100644 --- a/clang/test/CIR/CodeGen/rtti-qualfn.cpp +++ b/clang/test/CIR/CodeGen/rtti-qualfn.cpp @@ -14,11 +14,11 @@ void f() noexcept { // The pointee type _ZTIFvvE (function type info for void()) must be emitted // using the __function_type_info vtable. -// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>> : !cir.array<!s8i x 4> +// CIR-DAG: cir.global {{.*}} @_ZTSFvvE = #cir.const_array<"FvvE" : !cir.array<!s8i x 4>, trailing_zeros> : !cir.array<!s8i x 5> // CIR-DAG: cir.global {{.*}} @_ZTIFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__function_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSFvvE> : !cir.ptr<!u8i>}> // The pointer type info _ZTIPDoFvvE must include flag 64 (PTI_Noexcept). -// CIR-DAG: cir.global {{.*}} @_ZTSPDoFvvE = #cir.const_array<"PDoFvvE" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7> +// CIR-DAG: cir.global {{.*}} @_ZTSPDoFvvE = #cir.const_array<"PDoFvvE" : !cir.array<!s8i x 7>, trailing_zeros> : !cir.array<!s8i x 8> // CIR-DAG: cir.global {{.*}} @_ZTIPDoFvvE = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv119__pointer_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSPDoFvvE> : !cir.ptr<!u8i>, #cir.int<64> : !u32i, #cir.global_view<@_ZTIFvvE> : !cir.ptr<!u8i>}> // CIR: cir.throw %{{.*}} : !cir.ptr<!cir.ptr<!cir.func<()>>>, @_ZTIPDoFvvE _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
