diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index 1c8eda1f6076..4c602488cc18 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -385,14 +385,6 @@ EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) { LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { Expr *BaseExpr = E->getBase(); - // FIXME: Handle union members. - if (BaseExpr->getType()->isUnionType()) { - fprintf(stderr, "Unimplemented lvalue expr!\n"); - E->dump(getContext().SourceMgr); - llvm::Type *Ty = llvm::PointerType::get(ConvertType(E->getType())); - return LValue::MakeAddr(llvm::UndefValue::get(Ty)); - } - llvm::Value *BaseValue = NULL; if (BaseExpr->isLvalue() == Expr::LV_Valid) { LValue BaseLV = EmitLValue(BaseExpr); @@ -412,7 +404,16 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty), llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) }; - return LValue::MakeAddr(Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp")); + llvm::Value *V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp"); + // Match union field type. + if (BaseExpr->getType()->isUnionType()) { + const llvm::Type * FieldTy = ConvertType(Field->getType()); + const llvm::PointerType * BaseTy = cast(BaseValue->getType()); + if (FieldTy != BaseTy->getElementType()) { + V = Builder.CreateBitCast(V, llvm::PointerType::get(FieldTy), "tmp"); + } + } + return LValue::MakeAddr(V); // FIXME: If record field does not have one to one match with llvm::StructType // field then apply appropriate masks to select only member field bits. diff --git a/clang/CodeGen/CodeGenTypes.cpp b/clang/CodeGen/CodeGenTypes.cpp index 0b225291d254..8b873286689a 100644 --- a/clang/CodeGen/CodeGenTypes.cpp +++ b/clang/CodeGen/CodeGenTypes.cpp @@ -258,13 +258,15 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const RecordDecl *RD = cast(TD); // Just use the largest element of the union, breaking ties with the // highest aligned member. - std::vector Fields; + if (RD->getNumMembers() != 0) { std::pair MaxElt = Context.getTypeInfo(RD->getMember(0)->getType(), SourceLocation()); unsigned MaxEltNo = 0; - + addFieldInfo(RD->getMember(0), 0); // Each field gets first slot. + // FIXME : Move union field handling in RecordOrganize for (unsigned i = 1, e = RD->getNumMembers(); i != e; ++i) { + addFieldInfo(RD->getMember(i), 0); // Each field gets first slot. std::pair EltInfo = Context.getTypeInfo(RD->getMember(i)->getType(), SourceLocation()); if (EltInfo.first > MaxElt.first || @@ -274,10 +276,19 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { MaxEltNo = i; } } - - Fields.push_back(ConvertType(RD->getMember(MaxEltNo)->getType())); - } - ResultType = llvm::StructType::get(Fields); + + RecordOrganizer RO; + RO.addField(RD->getMember(MaxEltNo)); + RO.layoutFields(*this); + + // Get llvm::StructType. + RecordLayoutInfo *RLI = new RecordLayoutInfo(RO.getLLVMType()); + ResultType = RLI->getLLVMType(); + RecordLayouts[ResultType] = RLI; + } else { + std::vector Fields; + ResultType = llvm::StructType::get(Fields); + } } else { assert(0 && "FIXME: Implement tag decl kind!"); } diff --git a/clang/test/CodeGen/union.c b/clang/test/CodeGen/union.c new file mode 100644 index 000000000000..8102f9b6fd73 --- /dev/null +++ b/clang/test/CodeGen/union.c @@ -0,0 +1,18 @@ +// RUN: clang %s -emit-llvm + +union { + int a; + float b; +} u; + +void f() { + u.b = 11; +} + +int f2( float __x ) { + union{ + float __f; + unsigned int __u; + }__u; + return (int)(__u.__u >> 31); +}