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/6] [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/6] [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/6] [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/6] [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 5/6] [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 6/6] 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:

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

Reply via email to