[clang] [clang] Fixed a crash when explicitly casting between atomic complex types (PR #172210)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 14 11:56:43 PST 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/172210
>From 858cb45fcdd050f604579790aeba7d44914ae75a Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sat, 13 Dec 2025 22:39:45 +0100
Subject: [PATCH 1/2] [clang] Fixed a crash when explicitly casting between
atomic complex types
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/CodeGen/CGExprComplex.cpp | 5 +++++
clang/test/CodeGen/complex.c | 29 +++++++++++++++++++++++++++++
3 files changed, 35 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index feaf92ad4415f..b6ff1734b78f8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -800,6 +800,7 @@ Crash and bug fixes
containing a single colon. (#GH167905)
- Fixed a crash when parsing malformed #pragma clang loop vectorize_width(4,8,16)
by diagnosing invalid comma-separated argument lists. (#GH166325)
+- Fixed a crash when explicitly casting between atomic complex types. (#GH172208)
Improvements
^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index e5815ef1130dc..151b9473eb39c 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -515,7 +515,12 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
QualType DestType,
SourceLocation Loc) {
// Get the src/dest element type.
+ if (SrcType->isAtomicType())
+ SrcType = SrcType->castAs<AtomicType>()->getValueType();
SrcType = SrcType->castAs<ComplexType>()->getElementType();
+
+ if (DestType->isAtomicType())
+ DestType = DestType->castAs<AtomicType>()->getValueType();
DestType = DestType->castAs<ComplexType>()->getElementType();
// C99 6.3.1.6: When a value of complex type is converted to another
diff --git a/clang/test/CodeGen/complex.c b/clang/test/CodeGen/complex.c
index 91fc9dda72f72..c789d6e7c3ed7 100644
--- a/clang/test/CodeGen/complex.c
+++ b/clang/test/CodeGen/complex.c
@@ -593,3 +593,32 @@ void imag_on_scalar_with_type_promotion() {
_Float16 _Complex a;
_Float16 b = __real__(__imag__ a);
}
+
+// CHECK-LABEL: define dso_local void @explicit_cast_atomic_complex_to_atomic_complex(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A:%.*]] = alloca { float, float }, align 8
+// CHECK-NEXT: [[B:%.*]] = alloca { i32, i32 }, align 8
+// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca { float, float }, align 8
+// CHECK-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0
+// CHECK-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1
+// CHECK-NEXT: store float 2.000000e+00, ptr [[A_REALP]], align 8
+// CHECK-NEXT: store float 0.000000e+00, ptr [[A_IMAGP]], align 4
+// CHECK-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i64, ptr [[A]] seq_cst, align 8
+// CHECK-NEXT: store i64 [[ATOMIC_LOAD]], ptr [[ATOMIC_TEMP]], align 8
+// CHECK-NEXT: [[ATOMIC_TEMP_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ATOMIC_TEMP]], i32 0, i32 0
+// CHECK-NEXT: [[ATOMIC_TEMP_REAL:%.*]] = load float, ptr [[ATOMIC_TEMP_REALP]], align 8
+// CHECK-NEXT: [[ATOMIC_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ATOMIC_TEMP]], i32 0, i32 1
+// CHECK-NEXT: [[ATOMIC_TEMP_IMAG:%.*]] = load float, ptr [[ATOMIC_TEMP_IMAGP]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[ATOMIC_TEMP_REAL]] to i32
+// CHECK-NEXT: [[CONV1:%.*]] = fptosi float [[ATOMIC_TEMP_IMAG]] to i32
+// CHECK-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 0
+// CHECK-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[CONV]], ptr [[B_REALP]], align 8
+// CHECK-NEXT: store i32 [[CONV1]], ptr [[B_IMAGP]], align 4
+// CHECK-NEXT: ret void
+//
+void explicit_cast_atomic_complex_to_atomic_complex() {
+ _Atomic _Complex float a = 2.0f;
+ _Atomic _Complex int b = (_Atomic _Complex int)a;
+}
>From e5a81c4b5bcc8524aaab9a8cb78738f47cd95453 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 14 Dec 2025 20:56:22 +0100
Subject: [PATCH 2/2] Update releasenotes and add more test cases
---
clang/docs/ReleaseNotes.rst | 2 +-
clang/test/CodeGen/complex.c | 55 ++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b6ff1734b78f8..32488d5bfe1ec 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -800,7 +800,7 @@ Crash and bug fixes
containing a single colon. (#GH167905)
- Fixed a crash when parsing malformed #pragma clang loop vectorize_width(4,8,16)
by diagnosing invalid comma-separated argument lists. (#GH166325)
-- Fixed a crash when explicitly casting between atomic complex types. (#GH172208)
+- Fixed a crash when explicitly casting a complex type to or from an atomic complex type. (#GH172208)
Improvements
^^^^^^^^^^^^
diff --git a/clang/test/CodeGen/complex.c b/clang/test/CodeGen/complex.c
index c789d6e7c3ed7..f0e0709755538 100644
--- a/clang/test/CodeGen/complex.c
+++ b/clang/test/CodeGen/complex.c
@@ -622,3 +622,58 @@ void explicit_cast_atomic_complex_to_atomic_complex() {
_Atomic _Complex float a = 2.0f;
_Atomic _Complex int b = (_Atomic _Complex int)a;
}
+
+// CHECK-LABEL: define dso_local void @explicit_cast_atomic_complex_to_complex(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A:%.*]] = alloca { float, float }, align 8
+// CHECK-NEXT: [[B:%.*]] = alloca { i32, i32 }, align 4
+// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca { float, float }, align 8
+// CHECK-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0
+// CHECK-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1
+// CHECK-NEXT: store float 2.000000e+00, ptr [[A_REALP]], align 8
+// CHECK-NEXT: store float 0.000000e+00, ptr [[A_IMAGP]], align 4
+// CHECK-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i64, ptr [[A]] seq_cst, align 8
+// CHECK-NEXT: store i64 [[ATOMIC_LOAD]], ptr [[ATOMIC_TEMP]], align 8
+// CHECK-NEXT: [[ATOMIC_TEMP_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ATOMIC_TEMP]], i32 0, i32 0
+// CHECK-NEXT: [[ATOMIC_TEMP_REAL:%.*]] = load float, ptr [[ATOMIC_TEMP_REALP]], align 8
+// CHECK-NEXT: [[ATOMIC_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ATOMIC_TEMP]], i32 0, i32 1
+// CHECK-NEXT: [[ATOMIC_TEMP_IMAG:%.*]] = load float, ptr [[ATOMIC_TEMP_IMAGP]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[ATOMIC_TEMP_REAL]] to i32
+// CHECK-NEXT: [[CONV1:%.*]] = fptosi float [[ATOMIC_TEMP_IMAG]] to i32
+// CHECK-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 0
+// CHECK-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[CONV]], ptr [[B_REALP]], align 4
+// CHECK-NEXT: store i32 [[CONV1]], ptr [[B_IMAGP]], align 4
+// CHECK-NEXT: ret void
+//
+void explicit_cast_atomic_complex_to_complex() {
+ _Atomic _Complex float a = 2.0f;
+ _Complex int b = (_Complex int)a;
+}
+
+// CHECK-LABEL: define dso_local void @explicit_cast_complex_to_atomic_complex(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A:%.*]] = alloca { float, float }, align 4
+// CHECK-NEXT: [[B:%.*]] = alloca { i32, i32 }, align 8
+// CHECK-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0
+// CHECK-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1
+// CHECK-NEXT: store float 2.000000e+00, ptr [[A_REALP]], align 4
+// CHECK-NEXT: store float 0.000000e+00, ptr [[A_IMAGP]], align 4
+// CHECK-NEXT: [[A_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0
+// CHECK-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP1]], align 4
+// CHECK-NEXT: [[A_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1
+// CHECK-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP2]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[A_REAL]] to i32
+// CHECK-NEXT: [[CONV3:%.*]] = fptosi float [[A_IMAG]] to i32
+// CHECK-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 0
+// CHECK-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[B]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[CONV]], ptr [[B_REALP]], align 8
+// CHECK-NEXT: store i32 [[CONV3]], ptr [[B_IMAGP]], align 4
+// CHECK-NEXT: ret void
+//
+void explicit_cast_complex_to_atomic_complex() {
+ _Complex float a = 2.0f;
+ _Atomic _Complex int b = (_Atomic _Complex int)a;
+}
More information about the cfe-commits
mailing list