[clang] 77874a5 - [Clang][Sema] Make _Imag int/float LValue not assignable (#218270)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 9 12:01:27 PDT 2026
Author: Amr Hesham
Date: 2026-09-09T21:01:22+02:00
New Revision: 77874a5794a3bb007cda2e6a5ac77e7ce48cf8c4
URL: https://github.com/llvm/llvm-project/commit/77874a5794a3bb007cda2e6a5ac77e7ce48cf8c4
DIFF: https://github.com/llvm/llvm-project/commit/77874a5794a3bb007cda2e6a5ac77e7ce48cf8c4.diff
LOG: [Clang][Sema] Make _Imag int/float LValue not assignable (#218270)
Clang accepts `__real int/float` as an LValue 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
Added:
clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp
Modified:
clang/docs/ReleaseNotes.md
clang/lib/AST/ExprClassification.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 63e0e34197aed..92d30d347107d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -517,6 +517,7 @@ features cannot lower the translation-unit ABI level;
- 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 a crash when an `asm` label names the register for a global variable of incomplete type. (#GH219746)
+- Fixed an ICE hat occurred when using `__imag int/float` as lvalue in assignment. (#GH119498)
#### Bug Fixes to Compiler Builtins
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index eebae17d7b948..5fdd8d516ffa6 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -298,12 +298,18 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// expressions: l-value only if the operand is a true l-value.
case UO_Real:
case UO_Imag: {
- const Expr *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ const auto *UnaryOp = cast<UnaryOperator>(E);
+ const Expr *Op = UnaryOp->getSubExpr()->IgnoreParens();
Cl::Kinds K = ClassifyInternal(Ctx, Op);
if (K != Cl::CL_LValue) return K;
if (isa<ObjCPropertyRefExpr>(Op))
return Cl::CL_SubObjCPropertySetting;
+
+ // _Imag with non-complex operand is not a valid l-value.
+ if (UnaryOp->getOpcode() == 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..e07e7b42950d6
--- /dev/null
+++ b/clang/test/SemaCXX/imag-lvalue-with-non-complex-operand.cpp
@@ -0,0 +1,36 @@
+// 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()
+{
+ 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 float C;
+C lvalue_with_imag_float_with_typedef()
+{
+ C f;
+ __real__ f = 0;
+ __imag__ f = 0; // expected-error {{expression is not assignable}}
+ return f;
+}
More information about the cfe-commits
mailing list