[clang] [clang][CodeGen] Fix invalid bitcast in InitCatchParam for non-zero address space pointers (PR #224680)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 2 03:37:31 PDT 2026
https://github.com/im-lunex updated https://github.com/llvm/llvm-project/pull/224680
>From 1f39fd518ea82aef0f20086329151e975b4c6464 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Fri, 18 Sep 2026 23:01:46 +0600
Subject: [PATCH 1/7] add test for the rest of the cases
---
clang/lib/CodeGen/ItaniumCXXABI.cpp | 11 ++++---
.../CodeGenCXX/exception-addrspace-ms.cpp | 31 +++++++++++++++++++
clang/test/CodeGenCXX/exceptions.cpp | 12 +++++++
3 files changed, 49 insertions(+), 5 deletions(-)
create mode 100644 clang/test/CodeGenCXX/exception-addrspace-ms.cpp
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c17813140b10f7d..5c3832d915ac07b 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -5032,7 +5032,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
// Create the temporary and write the adjusted pointer into it.
Address ExnPtrTmp =
CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
- llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+ llvm::Value *Casted =
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(AdjustedExn, PtrTy);
CGF.Builder.CreateStore(Casted, ExnPtrTmp);
// Bind the reference to the temporary.
@@ -5040,8 +5041,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
}
}
- llvm::Value *ExnCast =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
+ llvm::Value *ExnCast = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ AdjustedExn, LLVMCatchTy, "exn.byref");
CGF.Builder.CreateStore(ExnCast, ParamAddr);
return;
}
@@ -5054,8 +5055,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
// If the catch type is a pointer type, __cxa_begin_catch returns
// the pointer by value.
if (CatchType->hasPointerRepresentation()) {
- llvm::Value *CastExn =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
+ llvm::Value *CastExn = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ AdjustedExn, LLVMCatchTy, "exn.casted");
switch (CatchType.getQualifiers().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
diff --git a/clang/test/CodeGenCXX/exception-addrspace-ms.cpp b/clang/test/CodeGenCXX/exception-addrspace-ms.cpp
new file mode 100644
index 000000000000000..0130abe32e977b8
--- /dev/null
+++ b/clang/test/CodeGenCXX/exception-addrspace-ms.cpp
@@ -0,0 +1,31 @@
+// Test for issue - (https://github.com/llvm/llvm-project/issues/222931)
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-PTR32 %s
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-AS270-BYREF %s
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-AS270-REF %s
+
+void sink_ptr32(int);
+
+void test_ptr32() {
+ try { throw (int * __ptr32)0; } catch (int * __ptr32 p) { sink_ptr32(*p); }
+}
+
+// CHECK-PTR32: %exn.casted = addrspacecast ptr %{{.*}} to ptr addrspace(270)
+
+typedef int __attribute__((address_space(270))) as270_int;
+void sink_as270(as270_int &);
+
+void test_byref() {
+ try { throw (as270_int)0; } catch (as270_int &p) { sink_as270(p); }
+}
+
+// CHECK-AS270-BYREF: %exn.byref = addrspacecast ptr {{.*}} to ptr addrspace(270)
+
+struct S2 {};
+typedef S2 __attribute__((address_space(270))) *PtrRec;
+void sink_ptrrec(PtrRec &);
+
+void test_ptrrec() {
+ try { throw (PtrRec)0; } catch (PtrRec &p) { sink_ptrrec(p); }
+}
+
+// CHECK-AS270-REF: store ptr addrspace(270) %{{.*}}, ptr %exn.byref.tmp, align 8
\ No newline at end of file
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp
index 6c920d718670956..7986aefb1eafd45 100644
--- a/clang/test/CodeGenCXX/exceptions.cpp
+++ b/clang/test/CodeGenCXX/exceptions.cpp
@@ -623,3 +623,15 @@ void test(int c) {
}
// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}} }
+
+// Test for issue - (https://github.com/llvm/llvm-project/issues/222931)
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK-AS1 %s
+
+typedef int __attribute__((address_space(1))) *as1_int_ptr;
+void sink_as1(int);
+
+void test_as1() {
+ try { throw (as1_int_ptr)0; } catch (as1_int_ptr p) { sink_as1(*p); }
+}
+
+// CHECK-AS1: %exn.casted = addrspacecast ptr %{{.*}} to ptr addrspace(1)
>From c222765a1f500d6f65710458c63409ce51277c1d Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Tue, 22 Sep 2026 21:58:50 +0600
Subject: [PATCH 2/7] improve test and separate those
---
.../CodeGenCXX/catch-address-space-ptr.cpp | 257 ++++++++++++++++++
.../CodeGenCXX/exception-addrspace-ms.cpp | 31 ---
clang/test/CodeGenCXX/exceptions.cpp | 14 -
3 files changed, 257 insertions(+), 45 deletions(-)
create mode 100644 clang/test/CodeGenCXX/catch-address-space-ptr.cpp
delete mode 100644 clang/test/CodeGenCXX/exception-addrspace-ms.cpp
diff --git a/clang/test/CodeGenCXX/catch-address-space-ptr.cpp b/clang/test/CodeGenCXX/catch-address-space-ptr.cpp
new file mode 100644
index 000000000000000..64b5ca8ec75ee3d
--- /dev/null
+++ b/clang/test/CodeGenCXX/catch-address-space-ptr.cpp
@@ -0,0 +1,257 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck %s
+
+// Issue #222931: Verify that catching pointers in non-zero address spaces
+// generates addrspacecast instead of invalid bitcast.
+
+void sink_ptr32(int);
+
+// CHECK-LABEL: define dso_local void @_Z10test_ptr32v(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(270), align 4
+// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3:[0-9]+]]
+// CHECK-NEXT: store ptr addrspace(270) null, ptr [[EXCEPTION]], align 16
+// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU10ptr32_sptri, ptr null) #[[ATTR4:[0-9]+]]
+// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
+// CHECK: [[LPAD]]:
+// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: catch ptr @_ZTIPU10ptr32_sptri
+// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
+// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
+// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
+// CHECK: [[CATCH_DISPATCH]]:
+// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU10ptr32_sptri) #[[ATTR3]]
+// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
+// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
+// CHECK: [[CATCH]]:
+// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
+// CHECK-NEXT: [[EXN_CASTED:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
+// CHECK-NEXT: store ptr addrspace(270) [[EXN_CASTED]], ptr [[P]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(270), ptr [[P]], align 4
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr addrspace(270) [[TMP5]], align 4
+// CHECK-NEXT: invoke void @_Z10sink_ptr32i(i32 [[TMP6]])
+// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
+// CHECK: [[INVOKE_CONT]]:
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[TRY_CONT:.*]]
+// CHECK: [[TRY_CONT]]:
+// CHECK-NEXT: ret void
+// CHECK: [[LPAD1]]:
+// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: cleanup
+// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
+// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
+// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[EH_RESUME]]
+// CHECK: [[EH_RESUME]]:
+// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
+// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
+// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
+// CHECK: [[UNREACHABLE]]:
+// CHECK-NEXT: unreachable
+//
+void test_ptr32() {
+ try { throw (int * __ptr32)0; } catch (int * __ptr32 p) { sink_ptr32(*p); }
+}
+
+typedef int __attribute__((address_space(270))) as270_int;
+void sink_as270(as270_int &);
+
+// CHECK-LABEL: define dso_local void @_Z10test_byrefv(
+// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(270), align 4
+// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3]]
+// CHECK-NEXT: store i32 0, ptr [[EXCEPTION]], align 16
+// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR4]]
+// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
+// CHECK: [[LPAD]]:
+// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: catch ptr @_ZTIi
+// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
+// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
+// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
+// CHECK: [[CATCH_DISPATCH]]:
+// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #[[ATTR3]]
+// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
+// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
+// CHECK: [[CATCH]]:
+// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
+// CHECK-NEXT: [[EXN_BYREF:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
+// CHECK-NEXT: store ptr addrspace(270) [[EXN_BYREF]], ptr [[P]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(270), ptr [[P]], align 4, !align [[META1:![0-9]+]]
+// CHECK-NEXT: invoke void @_Z10sink_as270RU5AS270i(ptr addrspace(270) align 4 dereferenceable(4) [[TMP5]])
+// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
+// CHECK: [[INVOKE_CONT]]:
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[TRY_CONT:.*]]
+// CHECK: [[TRY_CONT]]:
+// CHECK-NEXT: ret void
+// CHECK: [[LPAD1]]:
+// CHECK-NEXT: [[TMP6:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: cleanup
+// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0
+// CHECK-NEXT: store ptr [[TMP7]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1
+// CHECK-NEXT: store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[EH_RESUME]]
+// CHECK: [[EH_RESUME]]:
+// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
+// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
+// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
+// CHECK: [[UNREACHABLE]]:
+// CHECK-NEXT: unreachable
+//
+void test_byref() {
+ try { throw (as270_int)0; } catch (as270_int &p) { sink_as270(p); }
+}
+
+struct S2 {};
+typedef S2 __attribute__((address_space(270))) *PtrRec;
+void sink_ptrrec(PtrRec &);
+
+// CHECK-LABEL: define dso_local void @_Z11test_ptrrecv(
+// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[EXN_BYREF_TMP:%.*]] = alloca ptr addrspace(270), align 8
+// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3]]
+// CHECK-NEXT: store ptr addrspace(270) null, ptr [[EXCEPTION]], align 16
+// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU5AS2702S2, ptr null) #[[ATTR4]]
+// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
+// CHECK: [[LPAD]]:
+// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: catch ptr @_ZTIPU5AS2702S2
+// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
+// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
+// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
+// CHECK: [[CATCH_DISPATCH]]:
+// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU5AS2702S2) #[[ATTR3]]
+// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
+// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
+// CHECK: [[CATCH]]:
+// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
+// CHECK-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
+// CHECK-NEXT: store ptr addrspace(270) [[TMP5]], ptr [[EXN_BYREF_TMP]], align 8
+// CHECK-NEXT: store ptr [[EXN_BYREF_TMP]], ptr [[P]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META2:![0-9]+]], !align [[META1]]
+// CHECK-NEXT: invoke void @_Z11sink_ptrrecRPU5AS2702S2(ptr nonnull align 4 dereferenceable(4) [[TMP6]])
+// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
+// CHECK: [[INVOKE_CONT]]:
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[TRY_CONT:.*]]
+// CHECK: [[TRY_CONT]]:
+// CHECK-NEXT: ret void
+// CHECK: [[LPAD1]]:
+// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: cleanup
+// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
+// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
+// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[EH_RESUME]]
+// CHECK: [[EH_RESUME]]:
+// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
+// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
+// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
+// CHECK: [[UNREACHABLE]]:
+// CHECK-NEXT: unreachable
+//
+void test_ptrrec() {
+ try { throw (PtrRec)0; } catch (PtrRec &p) { sink_ptrrec(p); }
+}
+
+typedef int __attribute__((address_space(1))) *as1_int_ptr;
+void sink_as1(int);
+
+// CHECK-LABEL: define dso_local void @_Z8test_as1v(
+// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(1), align 8
+// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 8) #[[ATTR3]]
+// CHECK-NEXT: store ptr addrspace(1) null, ptr [[EXCEPTION]], align 16
+// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU3AS1i, ptr null) #[[ATTR4]]
+// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
+// CHECK: [[LPAD]]:
+// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: catch ptr @_ZTIPU3AS1i
+// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
+// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
+// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
+// CHECK: [[CATCH_DISPATCH]]:
+// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU3AS1i) #[[ATTR3]]
+// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
+// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
+// CHECK: [[CATCH]]:
+// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
+// CHECK-NEXT: [[EXN_CASTED:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(1)
+// CHECK-NEXT: store ptr addrspace(1) [[EXN_CASTED]], ptr [[P]], align 8
+// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[P]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr addrspace(1) [[TMP5]], align 4
+// CHECK-NEXT: invoke void @_Z8sink_as1i(i32 [[TMP6]])
+// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
+// CHECK: [[INVOKE_CONT]]:
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[TRY_CONT:.*]]
+// CHECK: [[TRY_CONT]]:
+// CHECK-NEXT: ret void
+// CHECK: [[LPAD1]]:
+// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
+// CHECK-NEXT: cleanup
+// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
+// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
+// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
+// CHECK-NEXT: br label %[[EH_RESUME]]
+// CHECK: [[EH_RESUME]]:
+// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
+// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
+// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
+// CHECK: [[UNREACHABLE]]:
+// CHECK-NEXT: unreachable
+//
+void test_as1() {
+ try { throw (as1_int_ptr)0; } catch (as1_int_ptr p) { sink_as1(*p); }
+}
+//.
+// CHECK: [[META1]] = !{i64 4}
+// CHECK: [[META2]] = !{}
+//.
diff --git a/clang/test/CodeGenCXX/exception-addrspace-ms.cpp b/clang/test/CodeGenCXX/exception-addrspace-ms.cpp
deleted file mode 100644
index 0130abe32e977b8..000000000000000
--- a/clang/test/CodeGenCXX/exception-addrspace-ms.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Test for issue - (https://github.com/llvm/llvm-project/issues/222931)
-// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-PTR32 %s
-// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-AS270-BYREF %s
-// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck -check-prefix=CHECK-AS270-REF %s
-
-void sink_ptr32(int);
-
-void test_ptr32() {
- try { throw (int * __ptr32)0; } catch (int * __ptr32 p) { sink_ptr32(*p); }
-}
-
-// CHECK-PTR32: %exn.casted = addrspacecast ptr %{{.*}} to ptr addrspace(270)
-
-typedef int __attribute__((address_space(270))) as270_int;
-void sink_as270(as270_int &);
-
-void test_byref() {
- try { throw (as270_int)0; } catch (as270_int &p) { sink_as270(p); }
-}
-
-// CHECK-AS270-BYREF: %exn.byref = addrspacecast ptr {{.*}} to ptr addrspace(270)
-
-struct S2 {};
-typedef S2 __attribute__((address_space(270))) *PtrRec;
-void sink_ptrrec(PtrRec &);
-
-void test_ptrrec() {
- try { throw (PtrRec)0; } catch (PtrRec &p) { sink_ptrrec(p); }
-}
-
-// CHECK-AS270-REF: store ptr addrspace(270) %{{.*}}, ptr %exn.byref.tmp, align 8
\ No newline at end of file
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp
index 7986aefb1eafd45..858d8dcccc764b0 100644
--- a/clang/test/CodeGenCXX/exceptions.cpp
+++ b/clang/test/CodeGenCXX/exceptions.cpp
@@ -621,17 +621,3 @@ void test(int c) {
}
}
-
-// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}} }
-
-// Test for issue - (https://github.com/llvm/llvm-project/issues/222931)
-// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK-AS1 %s
-
-typedef int __attribute__((address_space(1))) *as1_int_ptr;
-void sink_as1(int);
-
-void test_as1() {
- try { throw (as1_int_ptr)0; } catch (as1_int_ptr p) { sink_as1(*p); }
-}
-
-// CHECK-AS1: %exn.casted = addrspacecast ptr %{{.*}} to ptr addrspace(1)
>From fc905cb5f227cae40ab537764b7c956863d4afb5 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Wed, 23 Sep 2026 14:50:37 +0600
Subject: [PATCH 3/7] [Sema] we dont have the runtimes support for
cross-address-space conversions yet. soo reject those kind of pointers with
non-default address space in Sema insted
---
.../clang/Basic/DiagnosticSemaKinds.td | 5 +-
clang/lib/CodeGen/ItaniumCXXABI.cpp | 11 +-
clang/lib/Sema/SemaDeclCXX.cpp | 7 +
clang/lib/Sema/SemaExprCXX.cpp | 8 +
.../CodeGenCXX/catch-address-space-ptr.cpp | 257 ------------------
clang/test/CodeGenCXX/exceptions.cpp | 2 +
clang/test/Sema/throw-address-space.cpp | 18 ++
7 files changed, 44 insertions(+), 264 deletions(-)
delete mode 100644 clang/test/CodeGenCXX/catch-address-space-ptr.cpp
create mode 100644 clang/test/Sema/throw-address-space.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 825d17f49790c6a..13053db72e4e2ea 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8907,7 +8907,10 @@ def warn_cdtor_function_try_handler_mem_expr : Warning<
"%select{constructor|destructor}0 function try block">, InGroup<Exceptions>;
def err_throw_object_throwing_dtor : Error<
"cannot throw object of type %0 with a potentially-throwing destructor">;
-
+def err_throw_address_space_qualified_ptr : Error<
+ "cannot throw pointer with address space %0">;
+def err_catch_address_space_qualified_ptr : Error<
+ "cannot catch pointer with address space">;
let CategoryName = "Lambda Issue" in {
def err_capture_more_than_once : Error<
"%0 can appear only once in a capture list">;
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5c3832d915ac07b..1e644cedc31767d 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -5032,8 +5032,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
// Create the temporary and write the adjusted pointer into it.
Address ExnPtrTmp =
CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
- llvm::Value *Casted =
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(AdjustedExn, PtrTy);
+ llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
CGF.Builder.CreateStore(Casted, ExnPtrTmp);
// Bind the reference to the temporary.
@@ -5041,8 +5040,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
}
}
- llvm::Value *ExnCast = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- AdjustedExn, LLVMCatchTy, "exn.byref");
+ llvm::Value *ExnCast =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
CGF.Builder.CreateStore(ExnCast, ParamAddr);
return;
}
@@ -5055,8 +5054,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
// If the catch type is a pointer type, __cxa_begin_catch returns
// the pointer by value.
if (CatchType->hasPointerRepresentation()) {
- llvm::Value *CastExn = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- AdjustedExn, LLVMCatchTy, "exn.casted");
+ llvm::Value *CastExn =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
switch (CatchType.getQualifiers().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ea628f29d8a0053..f6fdd0eee5f7662 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17504,6 +17504,13 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
Invalid = true;
}
+ // reject trowing of pointers with non-default address space cause runtimes
+ // dosn't have support for cross-address-space conversions yet;
+ if (!Invalid && Mode == 1 && BaseType.getAddressSpace() != LangAS::Default) {
+ Diag(Loc, diag::err_catch_address_space_qualified_ptr) << ExDeclType;
+ Invalid = true;
+ }
+
if (!Invalid && Mode != 1 && BaseType->isSizelessType()) {
Diag(Loc, diag::err_catch_sizeless) << (Mode == 2 ? 1 : 0) << BaseType;
Invalid = true;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index deb7bdd09fdc7dc..a66b6a8c28dc12a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -981,6 +981,14 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
isPointer = true;
}
+ // reject trowing of pointers with Non-default address space cause runtimes
+ // dosen't have support for cross-address-space conversions yet;
+ if (isPointer && Ty.getAddressSpace() != LangAS::Default) {
+ Diag(ThrowLoc, diag::err_throw_address_space_qualified_ptr)
+ << E->getType() << E->getSourceRange();
+ return true;
+ }
+
// Cannot throw WebAssembly reference type.
if (Ty.isWebAssemblyReferenceType()) {
Diag(ThrowLoc, diag::err_wasm_reftype_tc) << 0 << E->getSourceRange();
diff --git a/clang/test/CodeGenCXX/catch-address-space-ptr.cpp b/clang/test/CodeGenCXX/catch-address-space-ptr.cpp
deleted file mode 100644
index 64b5ca8ec75ee3d..000000000000000
--- a/clang/test/CodeGenCXX/catch-address-space-ptr.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
-// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fms-extensions | FileCheck %s
-
-// Issue #222931: Verify that catching pointers in non-zero address spaces
-// generates addrspacecast instead of invalid bitcast.
-
-void sink_ptr32(int);
-
-// CHECK-LABEL: define dso_local void @_Z10test_ptr32v(
-// CHECK-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(270), align 4
-// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3:[0-9]+]]
-// CHECK-NEXT: store ptr addrspace(270) null, ptr [[EXCEPTION]], align 16
-// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU10ptr32_sptri, ptr null) #[[ATTR4:[0-9]+]]
-// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
-// CHECK: [[LPAD]]:
-// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: catch ptr @_ZTIPU10ptr32_sptri
-// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
-// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
-// CHECK: [[CATCH_DISPATCH]]:
-// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU10ptr32_sptri) #[[ATTR3]]
-// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
-// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
-// CHECK: [[CATCH]]:
-// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
-// CHECK-NEXT: [[EXN_CASTED:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
-// CHECK-NEXT: store ptr addrspace(270) [[EXN_CASTED]], ptr [[P]], align 4
-// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(270), ptr [[P]], align 4
-// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr addrspace(270) [[TMP5]], align 4
-// CHECK-NEXT: invoke void @_Z10sink_ptr32i(i32 [[TMP6]])
-// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
-// CHECK: [[INVOKE_CONT]]:
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[TRY_CONT:.*]]
-// CHECK: [[TRY_CONT]]:
-// CHECK-NEXT: ret void
-// CHECK: [[LPAD1]]:
-// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: cleanup
-// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
-// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
-// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[EH_RESUME]]
-// CHECK: [[EH_RESUME]]:
-// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
-// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
-// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
-// CHECK: [[UNREACHABLE]]:
-// CHECK-NEXT: unreachable
-//
-void test_ptr32() {
- try { throw (int * __ptr32)0; } catch (int * __ptr32 p) { sink_ptr32(*p); }
-}
-
-typedef int __attribute__((address_space(270))) as270_int;
-void sink_as270(as270_int &);
-
-// CHECK-LABEL: define dso_local void @_Z10test_byrefv(
-// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(270), align 4
-// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3]]
-// CHECK-NEXT: store i32 0, ptr [[EXCEPTION]], align 16
-// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR4]]
-// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
-// CHECK: [[LPAD]]:
-// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: catch ptr @_ZTIi
-// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
-// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
-// CHECK: [[CATCH_DISPATCH]]:
-// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #[[ATTR3]]
-// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
-// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
-// CHECK: [[CATCH]]:
-// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
-// CHECK-NEXT: [[EXN_BYREF:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
-// CHECK-NEXT: store ptr addrspace(270) [[EXN_BYREF]], ptr [[P]], align 4
-// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(270), ptr [[P]], align 4, !align [[META1:![0-9]+]]
-// CHECK-NEXT: invoke void @_Z10sink_as270RU5AS270i(ptr addrspace(270) align 4 dereferenceable(4) [[TMP5]])
-// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
-// CHECK: [[INVOKE_CONT]]:
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[TRY_CONT:.*]]
-// CHECK: [[TRY_CONT]]:
-// CHECK-NEXT: ret void
-// CHECK: [[LPAD1]]:
-// CHECK-NEXT: [[TMP6:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: cleanup
-// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0
-// CHECK-NEXT: store ptr [[TMP7]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1
-// CHECK-NEXT: store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[EH_RESUME]]
-// CHECK: [[EH_RESUME]]:
-// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
-// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
-// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
-// CHECK: [[UNREACHABLE]]:
-// CHECK-NEXT: unreachable
-//
-void test_byref() {
- try { throw (as270_int)0; } catch (as270_int &p) { sink_as270(p); }
-}
-
-struct S2 {};
-typedef S2 __attribute__((address_space(270))) *PtrRec;
-void sink_ptrrec(PtrRec &);
-
-// CHECK-LABEL: define dso_local void @_Z11test_ptrrecv(
-// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[EXN_BYREF_TMP:%.*]] = alloca ptr addrspace(270), align 8
-// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR3]]
-// CHECK-NEXT: store ptr addrspace(270) null, ptr [[EXCEPTION]], align 16
-// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU5AS2702S2, ptr null) #[[ATTR4]]
-// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
-// CHECK: [[LPAD]]:
-// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: catch ptr @_ZTIPU5AS2702S2
-// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
-// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
-// CHECK: [[CATCH_DISPATCH]]:
-// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU5AS2702S2) #[[ATTR3]]
-// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
-// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
-// CHECK: [[CATCH]]:
-// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
-// CHECK-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(270)
-// CHECK-NEXT: store ptr addrspace(270) [[TMP5]], ptr [[EXN_BYREF_TMP]], align 8
-// CHECK-NEXT: store ptr [[EXN_BYREF_TMP]], ptr [[P]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META2:![0-9]+]], !align [[META1]]
-// CHECK-NEXT: invoke void @_Z11sink_ptrrecRPU5AS2702S2(ptr nonnull align 4 dereferenceable(4) [[TMP6]])
-// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
-// CHECK: [[INVOKE_CONT]]:
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[TRY_CONT:.*]]
-// CHECK: [[TRY_CONT]]:
-// CHECK-NEXT: ret void
-// CHECK: [[LPAD1]]:
-// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: cleanup
-// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
-// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
-// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[EH_RESUME]]
-// CHECK: [[EH_RESUME]]:
-// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
-// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
-// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
-// CHECK: [[UNREACHABLE]]:
-// CHECK-NEXT: unreachable
-//
-void test_ptrrec() {
- try { throw (PtrRec)0; } catch (PtrRec &p) { sink_ptrrec(p); }
-}
-
-typedef int __attribute__((address_space(1))) *as1_int_ptr;
-void sink_as1(int);
-
-// CHECK-LABEL: define dso_local void @_Z8test_as1v(
-// CHECK-SAME: ) #[[ATTR0]] personality ptr @__gxx_personality_v0 {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(1), align 8
-// CHECK-NEXT: [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 8) #[[ATTR3]]
-// CHECK-NEXT: store ptr addrspace(1) null, ptr [[EXCEPTION]], align 16
-// CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIPU3AS1i, ptr null) #[[ATTR4]]
-// CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
-// CHECK: [[LPAD]]:
-// CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: catch ptr @_ZTIPU3AS1i
-// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
-// CHECK-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: br label %[[CATCH_DISPATCH:.*]]
-// CHECK: [[CATCH_DISPATCH]]:
-// CHECK-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPU3AS1i) #[[ATTR3]]
-// CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
-// CHECK-NEXT: br i1 [[MATCHES]], label %[[CATCH:.*]], label %[[EH_RESUME:.*]]
-// CHECK: [[CATCH]]:
-// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]]
-// CHECK-NEXT: [[EXN_CASTED:%.*]] = addrspacecast ptr [[TMP4]] to ptr addrspace(1)
-// CHECK-NEXT: store ptr addrspace(1) [[EXN_CASTED]], ptr [[P]], align 8
-// CHECK-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[P]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr addrspace(1) [[TMP5]], align 4
-// CHECK-NEXT: invoke void @_Z8sink_as1i(i32 [[TMP6]])
-// CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD1:.*]]
-// CHECK: [[INVOKE_CONT]]:
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[TRY_CONT:.*]]
-// CHECK: [[TRY_CONT]]:
-// CHECK-NEXT: ret void
-// CHECK: [[LPAD1]]:
-// CHECK-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 }
-// CHECK-NEXT: cleanup
-// CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
-// CHECK-NEXT: store ptr [[TMP8]], ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
-// CHECK-NEXT: store i32 [[TMP9]], ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: call void @__cxa_end_catch() #[[ATTR3]]
-// CHECK-NEXT: br label %[[EH_RESUME]]
-// CHECK: [[EH_RESUME]]:
-// CHECK-NEXT: [[EXN2:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
-// CHECK-NEXT: [[SEL3:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
-// CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN2]], 0
-// CHECK-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL3]], 1
-// CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL4]]
-// CHECK: [[UNREACHABLE]]:
-// CHECK-NEXT: unreachable
-//
-void test_as1() {
- try { throw (as1_int_ptr)0; } catch (as1_int_ptr p) { sink_as1(*p); }
-}
-//.
-// CHECK: [[META1]] = !{i64 4}
-// CHECK: [[META2]] = !{}
-//.
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp
index 858d8dcccc764b0..6c920d718670956 100644
--- a/clang/test/CodeGenCXX/exceptions.cpp
+++ b/clang/test/CodeGenCXX/exceptions.cpp
@@ -621,3 +621,5 @@ void test(int c) {
}
}
+
+// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}} }
diff --git a/clang/test/Sema/throw-address-space.cpp b/clang/test/Sema/throw-address-space.cpp
new file mode 100644
index 000000000000000..8b70e1c13bff2c5
--- /dev/null
+++ b/clang/test/Sema/throw-address-space.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -fms-extensions -verify %s
+
+// test for issue (https://github.com/llvm/llvm-project/issues/222931)
+
+// Reject throwing/catching pointers with non-default address spaces in Sema because
+// runtimes dont yet support for cross-address-space pointer conversions
+
+void test_throw() {
+ throw (int * __ptr32)0; // expected-error {{cannot throw pointer with address space}}
+ throw (int __attribute__((address_space(1))) *)0; // expected-error {{cannot throw pointer with address space}}
+}
+
+void test_catch() {
+ try {
+ } catch (int * __ptr32 p) { // expected-error {{cannot catch pointer with address space}}
+ } catch (int __attribute__((address_space(1))) * p) { // expected-error {{cannot catch pointer with address space}}
+ }
+}
>From 5bfdb4e4bef0c4d5312097f5c023f5a4e28877a1 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sat, 26 Sep 2026 11:05:34 +0600
Subject: [PATCH 4/7] implement rejection for throwing and catching of ptr's
and ref's that require cross-adder-space conversions
---
.../clang/Basic/DiagnosticSemaKinds.td | 7 ++--
clang/lib/Sema/SemaDeclCXX.cpp | 17 +++++++--
clang/lib/Sema/SemaExprCXX.cpp | 8 ++--
clang/test/Sema/throw-address-space.cpp | 38 +++++++++++++++----
4 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 13053db72e4e2ea..315eed41ef53ed9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8907,10 +8907,9 @@ def warn_cdtor_function_try_handler_mem_expr : Warning<
"%select{constructor|destructor}0 function try block">, InGroup<Exceptions>;
def err_throw_object_throwing_dtor : Error<
"cannot throw object of type %0 with a potentially-throwing destructor">;
-def err_throw_address_space_qualified_ptr : Error<
- "cannot throw pointer with address space %0">;
-def err_catch_address_space_qualified_ptr : Error<
- "cannot catch pointer with address space">;
+def err_throw_or_catch_address_space_qualified_ptr : Error<
+ "cannot %select{throw|catch}0 %select{pointer|reference}1 with non-default address space "
+ "(type %2)">;
let CategoryName = "Lambda Issue" in {
def err_capture_more_than_once : Error<
"%0 can appear only once in a capture list">;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f6fdd0eee5f7662..b8e111f090e1f1d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17504,10 +17504,19 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
Invalid = true;
}
- // reject trowing of pointers with non-default address space cause runtimes
- // dosn't have support for cross-address-space conversions yet;
- if (!Invalid && Mode == 1 && BaseType.getAddressSpace() != LangAS::Default) {
- Diag(Loc, diag::err_catch_address_space_qualified_ptr) << ExDeclType;
+ // Reject catching of ptr's and ref's involving non-default address spaces
+ // runtimes cannot perform cross-address-space conversions yet.
+ QualType T = ExDeclType;
+ bool IsRef = false;
+ if (const auto *RT = T->getAs<ReferenceType>()) {
+ IsRef = true;
+ T = RT->getPointeeType();
+ }
+ if (T.getAddressSpace() != LangAS::Default ||
+ (T->isPointerType() &&
+ T->getPointeeType().getAddressSpace() != LangAS::Default)) {
+ Diag(Loc, diag::err_throw_or_catch_address_space_qualified_ptr)
+ << /*IsCatch=*/1 << IsRef << ExDeclType;
Invalid = true;
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index a66b6a8c28dc12a..c3f18cb86fed7fc 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -981,11 +981,11 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
isPointer = true;
}
- // reject trowing of pointers with Non-default address space cause runtimes
- // dosen't have support for cross-address-space conversions yet;
+ // Reject throwing of ptr's involving non-default address spaces runtimes
+ // cannot perform cross-address-space conversions yet.
if (isPointer && Ty.getAddressSpace() != LangAS::Default) {
- Diag(ThrowLoc, diag::err_throw_address_space_qualified_ptr)
- << E->getType() << E->getSourceRange();
+ Diag(ThrowLoc, diag::err_throw_or_catch_address_space_qualified_ptr)
+ << /*IsCatch=*/0 << /*IsRef=*/0 << E->getType() << E->getSourceRange();
return true;
}
diff --git a/clang/test/Sema/throw-address-space.cpp b/clang/test/Sema/throw-address-space.cpp
index 8b70e1c13bff2c5..3c2c59217737f41 100644
--- a/clang/test/Sema/throw-address-space.cpp
+++ b/clang/test/Sema/throw-address-space.cpp
@@ -1,18 +1,42 @@
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -fms-extensions -verify %s
-// test for issue (https://github.com/llvm/llvm-project/issues/222931)
+// Test for issue (https://github.com/llvm/llvm-project/issues/222931).
+// Reject throwing/catching pointers and references with non-default address
+// spaces because runtimes don't yet support cross-address-space conversions.
-// Reject throwing/catching pointers with non-default address spaces in Sema because
-// runtimes dont yet support for cross-address-space pointer conversions
+using as1_int = int __attribute__((address_space(1)));
+using as1_int_ptr = int * __ptr32;
void test_throw() {
- throw (int * __ptr32)0; // expected-error {{cannot throw pointer with address space}}
- throw (int __attribute__((address_space(1))) *)0; // expected-error {{cannot throw pointer with address space}}
+ throw (int * __ptr32)0; // expected-error {{cannot throw pointer with non-default address space}}
+ throw (as1_int *)0; // expected-error {{cannot throw pointer with non-default address space}}
+ throw (int *)0; // ok
}
void test_catch() {
try {
- } catch (int * __ptr32 p) { // expected-error {{cannot catch pointer with address space}}
- } catch (int __attribute__((address_space(1))) * p) { // expected-error {{cannot catch pointer with address space}}
+ } catch (int * __ptr32 p) { // expected-error {{cannot catch pointer with non-default address space}}
}
+ try {
+ } catch (as1_int *p) { // expected-error {{cannot catch pointer with non-default address space}}
+ }
+ try {
+ } catch (as1_int &p) { // expected-error {{cannot catch reference with non-default address space}}
+ }
+ try {
+ } catch (as1_int &&p) { // expected-error {{cannot catch exceptions by rvalue reference}}
+ // expected-error at -1 {{cannot catch reference with non-default address space}}
+ }
+ try {
+ } catch (as1_int_ptr &p) { // expected-error {{cannot catch reference with non-default address space}}
+ }
+ try {
+ } catch (int &p) { // ok
+ }
+ try {
+ } catch (int *&p) { // ok
+ }
+try {
+} catch (as1_int p) { // expected-error {{cannot catch pointer with non-default address space}}
+}
}
>From 5f49ff6a8a38fe2dc0ccaa77c81b58c86c7c06e6 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sun, 27 Sep 2026 01:15:40 +0600
Subject: [PATCH 5/7] retest CI
>From 4a024cb179a6688607a1b844e7c9c038bac877b4 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Fri, 2 Oct 2026 15:10:29 +0600
Subject: [PATCH 6/7] Simplify address-space catch check
---
clang/lib/Sema/SemaDeclCXX.cpp | 16 ++++----------
clang/test/Sema/throw-address-space.cpp | 28 ++++++++++++++-----------
2 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b8e111f090e1f1d..35427e3f843b1e9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17504,19 +17504,11 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
Invalid = true;
}
- // Reject catching of ptr's and ref's involving non-default address spaces
- // runtimes cannot perform cross-address-space conversions yet.
- QualType T = ExDeclType;
- bool IsRef = false;
- if (const auto *RT = T->getAs<ReferenceType>()) {
- IsRef = true;
- T = RT->getPointeeType();
- }
- if (T.getAddressSpace() != LangAS::Default ||
- (T->isPointerType() &&
- T->getPointeeType().getAddressSpace() != LangAS::Default)) {
+ // Reject pointers/refs whose pointee is in a non-default address space.
+ // Runtimes cannot perform cross-address-space conversions yet.
+ if (Mode != 0 && BaseType.getAddressSpace() != LangAS::Default) {
Diag(Loc, diag::err_throw_or_catch_address_space_qualified_ptr)
- << /*IsCatch=*/1 << IsRef << ExDeclType;
+ << /*IsCatch=*/1 << /*IsRef=*/(Mode == 2) << ExDeclType;
Invalid = true;
}
diff --git a/clang/test/Sema/throw-address-space.cpp b/clang/test/Sema/throw-address-space.cpp
index 3c2c59217737f41..80626ef8170189c 100644
--- a/clang/test/Sema/throw-address-space.cpp
+++ b/clang/test/Sema/throw-address-space.cpp
@@ -1,8 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -fms-extensions -verify %s
// Test for issue (https://github.com/llvm/llvm-project/issues/222931).
-// Reject throwing/catching pointers and references with non-default address
-// spaces because runtimes don't yet support cross-address-space conversions.
+// Reject throwing/catching pointers and references whose pointee/referred type
+// has a non-default address space; runtimes don't yet support cross-address-
+// space conversions.
+
+// catch of a reference to a pointer (T*&), are not rejected by the Mode/BaseType
+// check.
using as1_int = int __attribute__((address_space(1)));
using as1_int_ptr = int * __ptr32;
@@ -18,25 +22,25 @@ void test_catch() {
} catch (int * __ptr32 p) { // expected-error {{cannot catch pointer with non-default address space}}
}
try {
- } catch (as1_int *p) { // expected-error {{cannot catch pointer with non-default address space}}
+ } catch (as1_int *p) { // expected-error {{cannot catch pointer with non-default address space}}
}
try {
- } catch (as1_int &p) { // expected-error {{cannot catch reference with non-default address space}}
+ } catch (as1_int &p) { // expected-error {{cannot catch reference with non-default address space}}
}
try {
- } catch (as1_int &&p) { // expected-error {{cannot catch exceptions by rvalue reference}}
- // expected-error at -1 {{cannot catch reference with non-default address space}}
+ } catch (as1_int &&p) { // expected-error {{cannot catch exceptions by rvalue reference}}
+ // expected-error at -1 {{cannot catch reference with non-default address space}}
}
try {
- } catch (as1_int_ptr &p) { // expected-error {{cannot catch reference with non-default address space}}
+ } catch (as1_int_ptr &p) { // ok: reference to pointer; BaseType is the pointer type (default AS)
}
try {
- } catch (int &p) { // ok
+ } catch (int &p) { // ok
}
try {
- } catch (int *&p) { // ok
+ } catch (int *&p) { // ok
+ }
+ try {
+ } catch (as1_int p) { // ok: by-value, Mode == 0
}
-try {
-} catch (as1_int p) { // expected-error {{cannot catch pointer with non-default address space}}
-}
}
>From 1897f194817cbedcecaafb70e72e0f917114d552 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Fri, 2 Oct 2026 16:37:08 +0600
Subject: [PATCH 7/7] fix test issue
---
clang/lib/Sema/SemaExprCXX.cpp | 16 ++++++++--------
clang/test/SemaCXX/address-space-placement.cpp | 5 +++--
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index c3f18cb86fed7fc..40c35b1eb9ba810 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -981,14 +981,6 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
isPointer = true;
}
- // Reject throwing of ptr's involving non-default address spaces runtimes
- // cannot perform cross-address-space conversions yet.
- if (isPointer && Ty.getAddressSpace() != LangAS::Default) {
- Diag(ThrowLoc, diag::err_throw_or_catch_address_space_qualified_ptr)
- << /*IsCatch=*/0 << /*IsRef=*/0 << E->getType() << E->getSourceRange();
- return true;
- }
-
// Cannot throw WebAssembly reference type.
if (Ty.isWebAssemblyReferenceType()) {
Diag(ThrowLoc, diag::err_wasm_reftype_tc) << 0 << E->getSourceRange();
@@ -1001,6 +993,14 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
return true;
}
+ // Reject throwing of ptr's involving non-default address spaces runtimes
+ // cannot perform cross-address-space conversions yet.
+ if (isPointer && Ty.getAddressSpace() != LangAS::Default) {
+ Diag(ThrowLoc, diag::err_throw_or_catch_address_space_qualified_ptr)
+ << /*IsCatch=*/0 << /*IsRef=*/0 << E->getType() << E->getSourceRange();
+ return true;
+ }
+
if (!isPointer || !Ty->isVoidType()) {
if (RequireCompleteType(ThrowLoc, Ty,
isPointer ? diag::err_throw_incomplete_ptr
diff --git a/clang/test/SemaCXX/address-space-placement.cpp b/clang/test/SemaCXX/address-space-placement.cpp
index 90a81ac1d5569b6..16cb5b1cf4e3269 100644
--- a/clang/test/SemaCXX/address-space-placement.cpp
+++ b/clang/test/SemaCXX/address-space-placement.cpp
@@ -15,7 +15,8 @@ void f([[clang::address_space(1)]] int* param) { // expected-warning {{applying
while([[clang::address_space(1)]] int* p = nullptr) {} // expected-warning {{applying attribute 'clang::address_space' to a declaration is deprecated; apply it to the type instead}}
if ([[clang::address_space(1)]] int* p = nullptr) {} // expected-warning {{applying attribute 'clang::address_space' to a declaration is deprecated; apply it to the type instead}}
try {
- } catch([[clang::address_space(1)]] int& i) { // expected-warning {{applying attribute 'clang::address_space' to a declaration is deprecated; apply it to the type instead}}
+ } catch([[clang::address_space(1)]] int& i) { // expected-warning {{applying attribute 'clang::address_space' to a declaration is deprecated; apply it to the type instead}}
+ // expected-error at -1 {{cannot catch reference with non-default address space}}
}
for (int [[clang::address_space(1)]] * p = nullptr; p; ++p) {}
@@ -23,7 +24,7 @@ void f([[clang::address_space(1)]] int* param) { // expected-warning {{applying
while(int [[clang::address_space(1)]] * p = nullptr) {}
if (int [[clang::address_space(1)]] * p = nullptr) {}
try {
- } catch(int [[clang::address_space(1)]] & i) {
+ } catch(int [[clang::address_space(1)]] & i) { // expected-error {{cannot catch reference with non-default address space}}
}
}
More information about the cfe-commits
mailing list