From: Nuno Lopes Date: Sat, 17 Jan 2009 00:48:48 +0000 (+0000) Subject: add support for usage of cast to union thing with static vars X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=81e51e2c5bf1e4edc3b70040e2083fa83d314e40;p=clang add support for usage of cast to union thing with static vars git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62387 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 41875522ed..72674f77fb 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -61,6 +61,12 @@ public: } llvm::Constant *VisitCastExpr(CastExpr* E) { + // GCC cast to union extension + if (E->getType()->isUnionType()) { + const llvm::Type *Ty = ConvertType(E->getType()); + return EmitUnion(CGM.EmitConstantExpr(E->getSubExpr(), CGF), Ty); + } + llvm::Constant *C = Visit(E->getSubExpr()); return EmitConversion(C, E->getSubExpr()->getType(), E->getType()); @@ -217,6 +223,27 @@ public: return llvm::ConstantStruct::get(SType, Elts); } + llvm::Constant *EmitUnion(llvm::Constant *C, const llvm::Type *Ty) { + // Build a struct with the union sub-element as the first member, + // and padded to the appropriate size + std::vector Elts; + std::vector Types; + Elts.push_back(C); + Types.push_back(C->getType()); + unsigned CurSize = CGM.getTargetData().getTypeStoreSize(C->getType()); + unsigned TotalSize = CGM.getTargetData().getTypeStoreSize(Ty); + while (CurSize < TotalSize) { + Elts.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty)); + Types.push_back(llvm::Type::Int8Ty); + CurSize++; + } + + // This always generates a packed struct + // FIXME: Try to generate an unpacked struct when we can + llvm::StructType* STy = llvm::StructType::get(Types, true); + return llvm::ConstantStruct::get(STy, Elts); + } + llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) { RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); const llvm::Type *Ty = ConvertType(ILE->getType()); @@ -248,26 +275,7 @@ public: return llvm::ConstantArray::get(RetTy, Elts); } - llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(0), CGF); - - // Build a struct with the union sub-element as the first member, - // and padded to the appropriate size - std::vector Elts; - std::vector Types; - Elts.push_back(C); - Types.push_back(C->getType()); - unsigned CurSize = CGM.getTargetData().getTypeStoreSize(C->getType()); - unsigned TotalSize = CGM.getTargetData().getTypeStoreSize(Ty); - while (CurSize < TotalSize) { - Elts.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty)); - Types.push_back(llvm::Type::Int8Ty); - CurSize++; - } - - // This always generates a packed struct - // FIXME: Try to generate an unpacked struct when we can - llvm::StructType* STy = llvm::StructType::get(Types, true); - return llvm::ConstantStruct::get(STy, Elts); + return EmitUnion(CGM.EmitConstantExpr(ILE->getInit(0), CGF), Ty); } llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) { diff --git a/test/CodeGen/cast-to-union.c b/test/CodeGen/cast-to-union.c index 3f339041eb..2f10d6ce56 100644 --- a/test/CodeGen/cast-to-union.c +++ b/test/CodeGen/cast-to-union.c @@ -1,10 +1,13 @@ -// RUN: clang -emit-llvm < %s | grep "store i32 351, i32*" +// RUN: clang -emit-llvm < %s -o %t && +// RUN: grep "store i32 351, i32*" %t && +// RUN: grep "w = global <{ i32, i8, i8, i8, i8 }> <{ i32 2, i8 0, i8 0, i8 0, i8 0 }>" %t && +// RUN: grep "y = global <{ double }> <{ double 7.300000e+01 }>" %t -union u { int i; }; +union u { int i; double d; }; void foo() { union u ola = (union u) 351; } -// FIXME: not working yet -// union u w = (union u)2; +union u w = (union u)2; +union u y = (union u)73.0;