]> granicus.if.org Git - clang/commitdiff
add codegen support for casting an element to a union.
authorChris Lattner <sabre@nondot.org>
Wed, 18 Mar 2009 18:28:57 +0000 (18:28 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 18 Mar 2009 18:28:57 +0000 (18:28 +0000)
There are some more complex cases (_Complex and structs)
that I'm still working on.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67218 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGen/exprs.c

index b3cf921bc57e36d9be2d53381c25533ee06fdc49..93b2382166ac3ef99b4528aa6f996f444ee87219 100644 (file)
@@ -186,12 +186,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
   case Expr::CXXDynamicCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXConstCastExprClass:
-    // Casts are only lvalues when the source and destination types are the 
-    // same.
-    assert(getContext().hasSameUnqualifiedType(E->getType(),
-                               cast<CastExpr>(E)->getSubExpr()->getType()) &&
-           "Type changing cast is not an lvalue");
-    return EmitLValue(cast<CastExpr>(E)->getSubExpr());
+    return EmitCastLValue(cast<CastExpr>(E));
   }
 }
 
@@ -994,8 +989,7 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
   return LV;
 }
 
-LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E)
-{
+LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
   const llvm::Type *LTy = ConvertType(E->getType());
   llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral");
 
@@ -1013,6 +1007,29 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E)
   return Result;
 }
 
+/// EmitCastLValue - Casts are never lvalues.  If a cast is needed by the code
+/// generator in an lvalue context, then it must mean that we need the address
+/// of an aggregate in order to access one of its fields.  This can happen for
+/// all the reasons that casts are permitted with aggregate result, including
+/// noop aggregate casts, and cast from scalar to union.
+LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
+  // If this is an aggregate-to-aggregate cast, just use the input's address as
+  // the lvalue.
+  if (getContext().hasSameUnqualifiedType(E->getType(),
+                                          E->getSubExpr()->getType()))
+    return EmitLValue(E->getSubExpr());
+
+  // Otherwise, we must have a cast from scalar to union.
+  assert(E->getType()->isUnionType() && "Expected scalar-to-union cast");
+  
+  // Casts are only lvalues when the source and destination types are the same.
+  llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
+  EmitAnyExpr(E, Temp, false);
+  
+  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
+                          getContext().getObjCGCAttrKind(E->getType()));
+}
+
 //===--------------------------------------------------------------------===//
 //                             Expression Emission
 //===--------------------------------------------------------------------===//
index 7443e449166f8a4e1f18cab3032732ddfc29adeb..8b578a6f3945b994f305ccd51b58eec68ea9265e 100644 (file)
@@ -605,6 +605,7 @@ public:
   LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E);
   LValue EmitMemberExpr(const MemberExpr *E);
   LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
+  LValue EmitCastLValue(const CastExpr *E);
 
   llvm::Value *EmitIvarOffset(ObjCInterfaceDecl *Interface,
                               const ObjCIvarDecl *Ivar);
index c22a4ecc71d6fdb63c50dc129ed2248322e21e04..a0fe96008952b9f32f109cfe7721a04549c4b0f5 100644 (file)
@@ -79,3 +79,6 @@ unsigned f1(void) {
   return (unsigned) fp;
 }  
 
+union f3_x {int x; float y;};
+int f3() {return ((union f3_x)2).x;}
+