https://github.com/Perdixky created 
https://github.com/llvm/llvm-project/pull/184011

#163601 
#163850 

>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/3] [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/3] [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 3fa26641c8272cd903c4e86663f9ca701f26ebdb Mon Sep 17 00:00:00 2001
From: Perdixky <[email protected]>
Date: Sun, 1 Mar 2026 23:29:03 +0800
Subject: [PATCH 3/3] [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)

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

Reply via email to