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
