diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 0c631df5c04f..b21aad20cee7 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -278,6 +278,7 @@ bool Expr::hasLocalSideEffect() const { /// - e->name /// - *e, the type of e cannot be a function type /// - string-constant +/// - (__real__ e) and (__imag__ e) where e is an lvalue [GNU extension] /// - reference type [C++ [expr]] /// Expr::isLvalueResult Expr::isLvalue() const { @@ -307,9 +308,13 @@ Expr::isLvalueResult Expr::isLvalue() const { const MemberExpr *m = cast(this); return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(); } - case UnaryOperatorClass: // C99 6.5.3p4 + case UnaryOperatorClass: if (cast(this)->getOpcode() == UnaryOperator::Deref) - return LV_Valid; + return LV_Valid; // C99 6.5.3p4 + + if (cast(this)->getOpcode() == UnaryOperator::Real || + cast(this)->getOpcode() == UnaryOperator::Imag) + return cast(this)->getSubExpr()->isLvalue(); // GNU. break; case ParenExprClass: // C99 6.5.1p5 return cast(this)->getSubExpr()->isLvalue(); diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index a0ef03bdc8ce..b996ecacda50 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -283,9 +283,21 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { if (E->getOpcode() == UnaryOperator::Extension) return EmitLValue(E->getSubExpr()); - assert(E->getOpcode() == UnaryOperator::Deref && - "'*' is the only unary operator that produces an lvalue"); - return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr())); + switch (E->getOpcode()) { + default: assert(0 && "Unknown unary operator lvalue!"); + case UnaryOperator::Deref: + return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr())); + case UnaryOperator::Real: + case UnaryOperator::Imag: + LValue LV = EmitLValue(E->getSubExpr()); + + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, + E->getOpcode() == UnaryOperator::Imag); + llvm::Value *Ops[] = {Zero, Idx}; + return LValue::MakeAddr(Builder.CreateGEP(LV.getAddress(), Ops, Ops+2, + "idx")); + } } LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { diff --git a/clang/test/CodeGen/complex.c b/clang/test/CodeGen/complex.c index 3ac04218cce2..0cc002bc6d6b 100644 --- a/clang/test/CodeGen/complex.c +++ b/clang/test/CodeGen/complex.c @@ -37,3 +37,12 @@ void test3() { g1 = g1 + D; g1 = D + g1; } + +void t1() { + (__real__ cf) = 4.0; +} + +void t2() { + (__imag__ cf) = 4.0; +} +