diff options
| author | Chris Lattner <sabre@nondot.org> | 2009-03-18 18:28:57 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2009-03-18 18:28:57 +0000 |
| commit | 28bcf1a4298e581fd003b5361cbd1de25fbe44f5 (patch) | |
| tree | 91669ec66f8f0ecae1f5f7669db9e33e75dca0b4 /clang | |
| parent | d175d9753b75d53a0cf34307c3ac23cd9c5dedc6 (diff) | |
| download | bcm5719-llvm-28bcf1a4298e581fd003b5361cbd1de25fbe44f5.tar.gz bcm5719-llvm-28bcf1a4298e581fd003b5361cbd1de25fbe44f5.zip | |
add codegen support for casting an element to a union.
There are some more complex cases (_Complex and structs)
that I'm still working on.
llvm-svn: 67218
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 33 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | ||||
| -rw-r--r-- | clang/test/CodeGen/exprs.c | 3 |
3 files changed, 29 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index b3cf921bc57..93b2382166a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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 //===--------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 7443e449166..8b578a6f394 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -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); diff --git a/clang/test/CodeGen/exprs.c b/clang/test/CodeGen/exprs.c index c22a4ecc71d..a0fe9600895 100644 --- a/clang/test/CodeGen/exprs.c +++ b/clang/test/CodeGen/exprs.c @@ -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;} + |

