diff options
author | Chris Lattner <sabre@nondot.org> | 2007-10-30 22:53:42 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-10-30 22:53:42 +0000 |
commit | 7da36f642e907ff5a5ba4b18b5bfebfabf36ecc7 (patch) | |
tree | 1588aeb85410ca7e8ff9b487281a8bedf5e5edac | |
parent | 8f54c1faaa94c789883d426109796fd62b81a044 (diff) |
__real__ and __imag__ can be lvalues. Add support to ast and codegen for them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43525 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/Expr.cpp | 9 | ||||
-rw-r--r-- | CodeGen/CGExpr.cpp | 18 | ||||
-rw-r--r-- | test/CodeGen/complex.c | 9 |
3 files changed, 31 insertions, 5 deletions
diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 0c631df5c0..b21aad20ce 100644 --- a/AST/Expr.cpp +++ b/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<MemberExpr>(this); return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(); } - case UnaryOperatorClass: // C99 6.5.3p4 + case UnaryOperatorClass: if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref) - return LV_Valid; + return LV_Valid; // C99 6.5.3p4 + + if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Real || + cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Imag) + return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(); // GNU. break; case ParenExprClass: // C99 6.5.1p5 return cast<ParenExpr>(this)->getSubExpr()->isLvalue(); diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index a0ef03bdc8..b996ecacda 100644 --- a/CodeGen/CGExpr.cpp +++ b/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/test/CodeGen/complex.c b/test/CodeGen/complex.c index 3ac04218cc..0cc002bc6d 100644 --- a/test/CodeGen/complex.c +++ b/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; +} + |