diff options
| -rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 35 | ||||
| -rw-r--r-- | clang/test/CodeGen/union-init.c | 31 | 
2 files changed, 57 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 1144cf1c915..4cb3c7bb2a0 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -92,15 +92,26 @@ public:      // Copy initializer elements.      unsigned i = 0; +    bool RewriteType = false;      for (; i < NumInitableElts; ++i) {        llvm::Constant *C = Visit(ILE->getInit(i)); +      RewriteType |= (C->getType() != ElemTy);        Elts.push_back(C);      } -     +      // Initialize remaining array elements.      for (; i < NumElements; ++i)        Elts.push_back(llvm::Constant::getNullValue(ElemTy)); +    if (RewriteType) { +      // FIXME: Try to avoid packing the array +      std::vector<const llvm::Type*> Types; +      for (unsigned i = 0; i < Elts.size(); ++i) +        Types.push_back(Elts[i]->getType()); +      const llvm::StructType *SType = llvm::StructType::get(Types, true); +      return llvm::ConstantStruct::get(SType, Elts); +    } +      return llvm::ConstantArray::get(AType, Elts);        } @@ -166,6 +177,7 @@ public:      // Copy initializer elements. Skip padding fields.      unsigned EltNo = 0;  // Element no in ILE      int FieldNo = 0; // Field no in RecordDecl +    bool RewriteType = false;      while (EltNo < ILE->getNumInits() && FieldNo < RD->getNumMembers()) {        FieldDecl* curField = RD->getMember(FieldNo);        FieldNo++; @@ -175,22 +187,27 @@ public:        if (curField->isBitField()) {          InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo));        } else { -        Elts[CGM.getTypes().getLLVMFieldNo(curField)] = -            Visit(ILE->getInit(EltNo)); +        unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(curField); +        llvm::Constant* C = Visit(ILE->getInit(EltNo)); +        RewriteType |= (C->getType() != Elts[FieldNo]->getType()); +        Elts[FieldNo] = C;        }        EltNo++;      } +    if (RewriteType) { +      // FIXME: Make this work for non-packed structs +      assert(SType->isPacked() && "Cannot recreate unpacked structs"); +      std::vector<const llvm::Type*> Types; +      for (unsigned i = 0; i < Elts.size(); ++i) +        Types.push_back(Elts[i]->getType()); +      SType = llvm::StructType::get(Types, true); +    } +      return llvm::ConstantStruct::get(SType, Elts);    }    llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) { -    // FIXME: Need to make this work correctly for unions in structs/arrays -    CGM.WarnUnsupported(ILE, "bitfield initialization"); -    return llvm::UndefValue::get(CGM.getTypes().ConvertType(ILE->getType())); - -    // Following is a partial implementation; it doesn't work correctly -    // because the parent struct/arrays don't adapt their type yet, though      RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();      const llvm::Type *Ty = ConvertType(ILE->getType()); diff --git a/clang/test/CodeGen/union-init.c b/clang/test/CodeGen/union-init.c new file mode 100644 index 00000000000..9a515a72d92 --- /dev/null +++ b/clang/test/CodeGen/union-init.c @@ -0,0 +1,31 @@ +// RUN: clang -emit-llvm < %s -o - + +// A nice and complicated initialization example with unions from Python +typedef int Py_ssize_t; + +typedef union _gc_head { +	struct { +		union _gc_head *gc_next; +		union _gc_head *gc_prev; +		Py_ssize_t gc_refs; +	} gc; +	long double dummy;  /* force worst-case alignment */ +} PyGC_Head; + +struct gc_generation { +	PyGC_Head head; +	int threshold; /* collection threshold */ +	int count; /* count of allocations or collections of younger +		      generations */ +}; + +#define NUM_GENERATIONS 3 +#define GEN_HEAD(n) (&generations[n].head) + +/* linked lists of container objects */ +struct gc_generation generations[NUM_GENERATIONS] = { +	/* PyGC_Head,				threshold,	count */ +	{{{GEN_HEAD(0), GEN_HEAD(0), 0}},	700,		0}, +	{{{GEN_HEAD(1), GEN_HEAD(1), 0}},	10,		0}, +	{{{GEN_HEAD(2), GEN_HEAD(2), 0}},	10,		0}, +};  | 

