// 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);
}
// 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++;
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());
--- /dev/null
+// 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},
+};