summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-10-30 22:53:42 +0000
committerChris Lattner <sabre@nondot.org>2007-10-30 22:53:42 +0000
commit595db86c9dc8d5fea20de1ae7387d7f030cb7ab8 (patch)
tree9b56e54e1a06eed613977762e168c82ecb17a33b /clang
parentc2dbfee43f87012155fd860e6f67051af817a677 (diff)
downloadbcm5719-llvm-595db86c9dc8d5fea20de1ae7387d7f030cb7ab8.tar.gz
bcm5719-llvm-595db86c9dc8d5fea20de1ae7387d7f030cb7ab8.zip
__real__ and __imag__ can be lvalues. Add support to ast and codegen for them.
llvm-svn: 43525
Diffstat (limited to 'clang')
-rw-r--r--clang/AST/Expr.cpp9
-rw-r--r--clang/CodeGen/CGExpr.cpp18
-rw-r--r--clang/test/CodeGen/complex.c9
3 files changed, 31 insertions, 5 deletions
diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp
index 0c631df5c04..b21aad20cee 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<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/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp
index a0ef03bdc8c..b996ecacda5 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 3ac04218cce..0cc002bc6d6 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;
+}
+
OpenPOWER on IntegriCloud