[clang] [CIR] Handle missing member pointer initializers (PR #235267)
GADI MEDHA SPANDANA via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 24 02:41:54 PDT 2026
https://github.com/cs24btech11025 created https://github.com/llvm/llvm-project/pull/235267
Fixes #233397.
### Summary
CXXABI lowering can crash when an external pointer-to-data-member or pointer-to-member-function global has no initializer. The member-pointer lowering paths assume the initializer attribute is present and attempt to access it.
Return an empty attribute when the initializer is absent for `DataMemberType` or `MethodType`, preserving the uninitialized external global rather than treating it as a null member pointer.
### Tests
Added regression coverage in `clang/test/CIR/CodeGen/member-pointer-null-init.cpp` for external data-member and member-function pointer globals referenced in expression statements.
- Targeted regression test passes.
- CIR CodeGen suite: 573 passed, 2 unsupported, 1 expected failure; no unexpected failures.
- `git diff --check` passes.
### AI assistance
ChatGPT assisted with debugging, patch development, and test investigation. I reviewed the changes and test results and take responsibility for the contribution.
>From 4f260957654f55a6545067b40b12f39edeea1cf2 Mon Sep 17 00:00:00 2001
From: Gadi Medha Spandana <cs24btech11025 at iith.ac.in>
Date: Sat, 24 Oct 2026 09:14:08 +0000
Subject: [PATCH] [CIR] Handle missing member pointer initializers
---
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 5 +++
.../CIR/CodeGen/member-pointer-null-init.cpp | 31 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index c68b6b05a328e..81e8200ec74d7 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -415,6 +415,11 @@ static mlir::TypedAttr lowerInitialValue(const LowerModule *lowerModule,
if (mlir::isa_and_present<cir::PoisonAttr>(initVal))
return cir::PoisonAttr::get(tc.convertType(ty));
+ // An external member-pointer global may have no initializer.
+ if (!initVal &&
+ mlir::isa<cir::DataMemberType, cir::MethodType>(ty))
+ return {};
+
if (mlir::isa<cir::DataMemberType>(ty)) {
// Members without a CIR field index (e.g. no_unique_address empty fields)
// are represented by an explicit byte offset instead of a field path.
diff --git a/clang/test/CIR/CodeGen/member-pointer-null-init.cpp b/clang/test/CIR/CodeGen/member-pointer-null-init.cpp
index ca15d122f5cbb..717244aec043b 100644
--- a/clang/test/CIR/CodeGen/member-pointer-null-init.cpp
+++ b/clang/test/CIR/CodeGen/member-pointer-null-init.cpp
@@ -5,6 +5,9 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=LLVM,OGCG --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=CIR-EXTERNAL --input-file=%t.cir %s
+// RUN: FileCheck --check-prefix=LLVM-EXTERNAL --input-file=%t-cir.ll %s
+
struct Inner {
int Inner::*p;
};
@@ -91,3 +94,31 @@ void runtime_agg(int x) {
Outer o = {.b = x};
(void)o;
}
+
+// Referencing an external pointer-to-data-member with no initializer must not
+// crash CXXABILowering.
+struct Base {};
+struct Derived : Base {};
+
+extern int Derived::*external_member_ptr;
+
+void use_external_member_ptr() {
+ external_member_ptr;
+}
+
+// CIR-EXTERNAL: cir.global "private" external @external_member_ptr : !s64i
+// LLVM-EXTERNAL: @external_member_ptr = external global i64, align 8
+struct MethodOwner {
+ void method();
+};
+
+using MethodPointer = void (MethodOwner::*)();
+
+extern MethodPointer external_method_ptr;
+
+void use_external_method_ptr() {
+ external_method_ptr;
+}
+
+// CIR-EXTERNAL: cir.global "private" external @external_method_ptr
+// LLVM-EXTERNAL: @external_method_ptr = external global
More information about the cfe-commits
mailing list