[clang] [Clang][Sema] Make _Imag int/float RValue not assignable (PR #218270)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 23 11:36:50 PDT 2026
https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/218270
Clang accepts `__real int/float` as an RValue because it's equal to the scalar value itself, so the assignment will work fine, but it's not the case for `__imag` because, for int and float, there is no imaginary part to assign a value to it, so in the sema we can reject this case, similar to GCC.
Fixes: #119498
>From 2cd9cb2326c3405ad141ffd6937f971b2063cc10 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 23 Aug 2026 19:18:38 +0200
Subject: [PATCH] [Clang][Sema] Make _Imag int/float RValue not assignable
---
clang/docs/ReleaseNotes.md | 1 +
clang/lib/AST/ExprClassification.cpp | 7 +++-
.../imag-lvalue-with-non-complex-operand.cpp | 35 +++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index ca0dbfa2af229..e541f5aa3f1e5 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -440,6 +440,7 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when declaring a member template within a local class inside an OpenMP region. (#GH216052)
- Fixed a bug where repeated #imports of modular headers in non-modular compilation were translated to #pragma clang module import. (#GH216924)
- Fixed an assertion when `#pragma omp declare simd` or `#pragma omp declare variant` is followed by another OpenMP declarative directive containing a qualified identifier. (#GH217204)
+- Fixed an ICE hat occurred when using `__imag int/float` as rvalue in assignment. (#GH119498)
#### Bug Fixes to Compiler Builtins
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index eebae17d7b948..a80bd2ab50001 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -283,7 +283,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E));
case Expr::UnaryOperatorClass:
- switch (cast<UnaryOperator>(E)->getOpcode()) {
+ switch (auto UnaryOp = cast<UnaryOperator>(E)->getOpcode()) {
// C++ [expr.unary.op]p1: The unary * operator performs indirection:
// [...] the result is an lvalue referring to the object or function
// to which the expression points.
@@ -304,6 +304,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
if (isa<ObjCPropertyRefExpr>(Op))
return Cl::CL_SubObjCPropertySetting;
+
+ // _Imag with non-complex operand is not a valid l-value
+ if (UnaryOp == UO_Imag && !Op->getType()->isAnyComplexType())
+ return Cl::CL_PRValue;
+
return Cl::CL_LValue;
}
diff --git a/clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp b/clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp
new file mode 100644
index 0000000000000..b1ea9b4473b3e
--- /dev/null
+++ b/clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void lvalue_with_imag_int() {
+ int i;
+ __imag__ i = 0; // expected-error {{expression is not assignable}}
+}
+
+void lvalue_with_imag_float() {
+ float i;
+ __imag__ i = 0; // expected-error {{expression is not assignable}}
+}
+
+_Complex float foo() // expected-note {{previous definition is here}}
+{
+ float f;
+ __real__ f = 0;
+ __imag__ f = 0; // expected-error {{expression is not assignable}}
+ return f;
+}
+
+_Complex float baz()
+{
+ float f;
+ __real__ f = 0;
+ __imag__ } // expected-error {{expected expression}}
+
+
+typedef _Complex float C;
+C foo() // expected-error {{redefinition of 'foo'}}
+{
+ C f;
+ __real__ f = 0;
+ __imag__ f = 0;
+ return f;
+}
More information about the cfe-commits
mailing list