]> granicus.if.org Git - clang/commitdiff
__real__ and __imag__ can be lvalues. Add support to ast and codegen for them.
authorChris Lattner <sabre@nondot.org>
Tue, 30 Oct 2007 22:53:42 +0000 (22:53 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 30 Oct 2007 22:53:42 +0000 (22:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43525 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Expr.cpp
CodeGen/CGExpr.cpp
test/CodeGen/complex.c

index 0c631df5c04f90da9fea94eb8f773f69965ef678..b21aad20cee7aa01e834e395c821d0fe8ae32125 100644 (file)
@@ -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();
index a0ef03bdc8ce1b5b413c955ef0941f48d54e4296..b996ecacda5030e96c702bd261265e10f3e23dc4 100644 (file)
@@ -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) {
index 3ac04218cce2448e3abb2f069623c6597819f547..0cc002bc6d6b64b42ffee20b03e23eafa5e4cd67 100644 (file)
@@ -37,3 +37,12 @@ void test3() {
   g1 = g1 + D;
   g1 = D + g1;
 }
+
+void t1() {
+  (__real__ cf) = 4.0;
+}
+
+void t2() {
+  (__imag__ cf) = 4.0;
+}
+