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;
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to