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 1/4] [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 2/4] [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 3/4] [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 4/4] [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: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
