diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index d4d9c92838b0..1f222a2bd1df 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1036,87 +1036,122 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, } } +static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, + const llvm::Type *baseType, + const CXXRecordDecl *base); + static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, - const CXXRecordDecl *RD) { - QualType T = CGM.getContext().getTagDeclType(RD); + const CXXRecordDecl *record, + bool asCompleteObject) { + const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record); + const llvm::StructType *structure = + (asCompleteObject ? layout.getLLVMType() + : layout.getBaseSubobjectLLVMType()); - const llvm::StructType *STy = - cast(CGM.getTypes().ConvertTypeForMem(T)); - unsigned NumElements = STy->getNumElements(); - std::vector Elements(NumElements); + unsigned numElements = structure->getNumElements(); + std::vector elements(numElements); - const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD); - - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + // Fill in all the bases. + for (CXXRecordDecl::base_class_const_iterator + I = record->bases_begin(), E = record->bases_end(); I != E; ++I) { if (I->isVirtual()) { - // Ignore virtual bases. + // Ignore virtual bases; if we're laying out for a complete + // object, we'll lay these out later. continue; } - const CXXRecordDecl *BaseDecl = - cast(I->getType()->getAs()->getDecl()); + const CXXRecordDecl *base = + cast(I->getType()->castAs()->getDecl()); // Ignore empty bases. - if (BaseDecl->isEmpty()) + if (base->isEmpty()) continue; - // Ignore bases that don't have any pointer to data members. - if (CGM.getTypes().isZeroInitializable(BaseDecl)) - continue; - - unsigned BaseFieldNo = Layout.getNonVirtualBaseLLVMFieldNo(BaseDecl); - const llvm::Type *BaseTy = STy->getElementType(BaseFieldNo); - - if (isa(BaseTy)) { - // We can just emit the base as a null constant. - Elements[BaseFieldNo] = EmitNullConstant(CGM, BaseDecl); - continue; - } - - // Some bases are represented as arrays of i8 if the size of the - // base is smaller than its corresponding LLVM type. - // Figure out how many elements this base array has. - const llvm::ArrayType *BaseArrayTy = cast(BaseTy); - unsigned NumBaseElements = BaseArrayTy->getNumElements(); - - // Fill in null data member pointers. - std::vector BaseElements(NumBaseElements); - FillInNullDataMemberPointers(CGM, I->getType(), BaseElements, 0); - - // Now go through all other elements and zero them out. - if (NumBaseElements) { - const llvm::Type* Int8Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext()); - llvm::Constant *Zero = llvm::Constant::getNullValue(Int8Ty); - for (unsigned I = 0; I != NumBaseElements; ++I) { - if (!BaseElements[I]) - BaseElements[I] = Zero; - } - } - - Elements[BaseFieldNo] = llvm::ConstantArray::get(BaseArrayTy, BaseElements); + unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base); + const llvm::Type *baseType = structure->getElementType(fieldIndex); + elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); } - // Visit all fields. - for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I) { - const FieldDecl *FD = *I; + // Fill in all the fields. + for (RecordDecl::field_iterator I = record->field_begin(), + E = record->field_end(); I != E; ++I) { + const FieldDecl *field = *I; // Ignore bit fields. - if (FD->isBitField()) + if (field->isBitField()) continue; - unsigned FieldNo = Layout.getLLVMFieldNo(FD); - Elements[FieldNo] = CGM.EmitNullConstant(FD->getType()); + unsigned fieldIndex = layout.getLLVMFieldNo(field); + elements[fieldIndex] = CGM.EmitNullConstant(field->getType()); + } + + // Fill in the virtual bases, if we're working with the complete object. + if (asCompleteObject) { + for (CXXRecordDecl::base_class_const_iterator + I = record->vbases_begin(), E = record->vbases_end(); I != E; ++I) { + const CXXRecordDecl *base = + cast(I->getType()->castAs()->getDecl()); + + // Ignore empty bases. + if (base->isEmpty()) + continue; + + unsigned fieldIndex = layout.getVirtualBaseIndex(base); + + // We might have already laid this field out. + if (elements[fieldIndex]) continue; + + const llvm::Type *baseType = structure->getElementType(fieldIndex); + elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); + } } // Now go through all other fields and zero them out. - for (unsigned i = 0; i != NumElements; ++i) { - if (!Elements[i]) - Elements[i] = llvm::Constant::getNullValue(STy->getElementType(i)); + for (unsigned i = 0; i != numElements; ++i) { + if (!elements[i]) + elements[i] = llvm::Constant::getNullValue(structure->getElementType(i)); } - return llvm::ConstantStruct::get(STy, Elements); + return llvm::ConstantStruct::get(structure, elements); +} + +/// Emit the null constant for a base subobject. +static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, + const llvm::Type *baseType, + const CXXRecordDecl *base) { + const CGRecordLayout &baseLayout = CGM.getTypes().getCGRecordLayout(base); + + // Just zero out bases that don't have any pointer to data members. + if (baseLayout.isZeroInitializableAsBase()) + return llvm::Constant::getNullValue(baseType); + + // If the base type is a struct, we can just use its null constant. + if (isa(baseType)) { + return EmitNullConstant(CGM, base, /*complete*/ false); + } + + // Otherwise, some bases are represented as arrays of i8 if the size + // of the base is smaller than its corresponding LLVM type. Figure + // out how many elements this base array has. + const llvm::ArrayType *baseArrayType = cast(baseType); + unsigned numBaseElements = baseArrayType->getNumElements(); + + // Fill in null data member pointers. + std::vector baseElements(numBaseElements); + FillInNullDataMemberPointers(CGM, CGM.getContext().getTypeDeclType(base), + baseElements, 0); + + // Now go through all other elements and zero them out. + if (numBaseElements) { + const llvm::Type *i8 = llvm::Type::getInt8Ty(CGM.getLLVMContext()); + llvm::Constant *i8_zero = llvm::Constant::getNullValue(i8); + for (unsigned i = 0; i != numBaseElements; ++i) { + if (!baseElements[i]) + baseElements[i] = i8_zero; + } + } + + return llvm::ConstantArray::get(baseArrayType, baseElements); } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { @@ -1140,7 +1175,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { if (const RecordType *RT = T->getAs()) { const CXXRecordDecl *RD = cast(RT->getDecl()); - return ::EmitNullConstant(*this, RD); + return ::EmitNullConstant(*this, RD, /*complete object*/ true); } assert(T->isMemberPointerType() && "Should only see member pointers here!"); diff --git a/clang/lib/CodeGen/CGRecordLayout.h b/clang/lib/CodeGen/CGRecordLayout.h index 2a7aa3596598..30da05f421fe 100644 --- a/clang/lib/CodeGen/CGRecordLayout.h +++ b/clang/lib/CodeGen/CGRecordLayout.h @@ -173,12 +173,13 @@ class CGRecordLayout { void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT private: - /// The LLVM type corresponding to this record layout. - llvm::PATypeHolder LLVMType; + /// The LLVM type corresponding to this record layout; used when + /// laying it out as a complete object. + llvm::PATypeHolder CompleteObjectType; - /// The LLVM type for the non-virtual part of this record layout, used for - /// laying out the record as a base. - llvm::PATypeHolder NonVirtualBaseLLVMType; + /// The LLVM type for the non-virtual part of this record layout; + /// used when laying it out as a base subobject. + llvm::PATypeHolder BaseSubobjectType; /// Map from (non-bit-field) struct field to the corresponding llvm struct /// type field no. This info is populated by record builder. @@ -190,26 +191,41 @@ private: // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single // map for both virtual and non virtual bases. - llvm::DenseMap NonVirtualBaseFields; + llvm::DenseMap NonVirtualBases; - /// Whether one of the fields in this record layout is a pointer to data - /// member, or a struct that contains pointer to data member. + /// Map from virtual bases to their field index in the complete object. + llvm::DenseMap CompleteObjectVirtualBases; + + /// False if any direct or indirect subobject of this class, when + /// considered as a complete object, requires a non-zero bitpattern + /// when zero-initialized. bool IsZeroInitializable : 1; -public: - CGRecordLayout(const llvm::StructType *LLVMType, - const llvm::StructType *NonVirtualBaseLLVMType, - bool IsZeroInitializable) - : LLVMType(LLVMType), NonVirtualBaseLLVMType(NonVirtualBaseLLVMType), - IsZeroInitializable(IsZeroInitializable) {} + /// False if any direct or indirect subobject of this class, when + /// considered as a base subobject, requires a non-zero bitpattern + /// when zero-initialized. + bool IsZeroInitializableAsBase : 1; - /// \brief Return the LLVM type associated with this record. +public: + CGRecordLayout(const llvm::StructType *CompleteObjectType, + const llvm::StructType *BaseSubobjectType, + bool IsZeroInitializable, + bool IsZeroInitializableAsBase) + : CompleteObjectType(CompleteObjectType), + BaseSubobjectType(BaseSubobjectType), + IsZeroInitializable(IsZeroInitializable), + IsZeroInitializableAsBase(IsZeroInitializableAsBase) {} + + /// \brief Return the "complete object" LLVM type associated with + /// this record. const llvm::StructType *getLLVMType() const { - return cast(LLVMType.get()); + return cast(CompleteObjectType.get()); } - const llvm::StructType *getNonVirtualBaseLLVMType() const { - return cast(NonVirtualBaseLLVMType.get()); + /// \brief Return the "base subobject" LLVM type associated with + /// this record. + const llvm::StructType *getBaseSubobjectLLVMType() const { + return cast(BaseSubobjectType.get()); } /// \brief Check whether this struct can be C++ zero-initialized @@ -218,6 +234,12 @@ public: return IsZeroInitializable; } + /// \brief Check whether this struct can be C++ zero-initialized + /// with a zeroinitializer when considered as a base subobject. + bool isZeroInitializableAsBase() const { + return IsZeroInitializableAsBase; + } + /// \brief Return llvm::StructType element number that corresponds to the /// field FD. unsigned getLLVMFieldNo(const FieldDecl *FD) const { @@ -227,8 +249,15 @@ public: } unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const { - assert(NonVirtualBaseFields.count(RD) && "Invalid non-virtual base!"); - return NonVirtualBaseFields.lookup(RD); + assert(NonVirtualBases.count(RD) && "Invalid non-virtual base!"); + return NonVirtualBases.lookup(RD); + } + + /// \brief Return the LLVM field index corresponding to the given + /// virtual base. Only valid when operating on the complete object. + unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const { + assert(CompleteObjectVirtualBases.count(base) && "Invalid virtual base!"); + return CompleteObjectVirtualBases.lookup(base); } /// \brief Return the BitFieldInfo that corresponds to the field FD. @@ -236,7 +265,7 @@ public: assert(FD->isBitField() && "Invalid call for non bit-field decl!"); llvm::DenseMap::const_iterator it = BitFields.find(FD); - assert(it != BitFields.end() && "Unable to find bitfield info"); + assert(it != BitFields.end() && "Unable to find bitfield info"); return it->second; } diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index aaff7fc9f78a..f2864944f9a1 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -33,9 +33,10 @@ namespace { class CGRecordLayoutBuilder { public: /// FieldTypes - Holds the LLVM types that the struct is created from. + /// std::vector FieldTypes; - /// NonVirtualBaseFieldTypes - Holds the LLVM types for the non-virtual part + /// BaseSubobjectType - Holds the LLVM type for the non-virtual part /// of the struct. For example, consider: /// /// struct A { int i; }; @@ -47,22 +48,19 @@ public: /// /// And the LLVM type of the non-virtual base struct will be /// %struct.C.base = type { i32 (...)**, %struct.A, i32 } - std::vector NonVirtualBaseFieldTypes; + /// + /// This only gets initialized if the base subobject type is + /// different from the complete-object type. + const llvm::StructType *BaseSubobjectType; - /// NonVirtualBaseTypeIsSameAsCompleteType - Whether the non-virtual part of - /// the struct is equivalent to the complete struct. - bool NonVirtualBaseTypeIsSameAsCompleteType; - - /// LLVMFieldInfo - Holds a field and its corresponding LLVM field number. - typedef std::pair LLVMFieldInfo; - llvm::SmallVector LLVMFields; + /// FieldInfo - Holds a field and its corresponding LLVM field number. + llvm::DenseMap Fields; - /// LLVMBitFieldInfo - Holds location and size information about a bit field. - typedef std::pair LLVMBitFieldInfo; - llvm::SmallVector LLVMBitFields; + /// BitFieldInfo - Holds location and size information about a bit field. + llvm::DenseMap BitFields; - typedef std::pair LLVMBaseInfo; - llvm::SmallVector LLVMNonVirtualBases; + llvm::DenseMap NonVirtualBases; + llvm::DenseMap VirtualBases; /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are /// primary base classes for some other direct or indirect base class. @@ -75,6 +73,7 @@ public: /// IsZeroInitializable - Whether this struct can be C++ /// zero-initialized with an LLVM zeroinitializer. bool IsZeroInitializable; + bool IsZeroInitializableAsBase; /// Packed - Whether the resulting LLVM struct will be packed or not. bool Packed; @@ -148,6 +147,7 @@ private: /// AppendBytes - Append a given number of bytes to the record. void AppendBytes(uint64_t NumBytes); + void AppendBytes(CharUnits numBytes) { AppendBytes(numBytes.getQuantity()); } /// AppendTailPadding - Append enough tail padding so that the type will have /// the passed size. @@ -162,13 +162,13 @@ private: /// CheckZeroInitializable - Check if the given type contains a pointer /// to data member. void CheckZeroInitializable(QualType T); - void CheckZeroInitializable(const CXXRecordDecl *RD); public: CGRecordLayoutBuilder(CodeGenTypes &Types) - : NonVirtualBaseTypeIsSameAsCompleteType(false), IsZeroInitializable(true), - Packed(false), Types(Types), Alignment(0), BitsAvailableInLastField(0), - NextFieldOffsetInBytes(0) { } + : BaseSubobjectType(0), + IsZeroInitializable(true), IsZeroInitializableAsBase(true), + Packed(false), Types(Types), Alignment(0), + BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { } /// Layout - Will layout a RecordDecl. void Layout(const RecordDecl *D); @@ -193,9 +193,10 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { Packed = true; NextFieldOffsetInBytes = 0; FieldTypes.clear(); - LLVMFields.clear(); - LLVMBitFields.clear(); - LLVMNonVirtualBases.clear(); + Fields.clear(); + BitFields.clear(); + NonVirtualBases.clear(); + VirtualBases.clear(); LayoutFields(D); } @@ -339,9 +340,8 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, } // Add the bit field info. - LLVMBitFields.push_back( - LLVMBitFieldInfo(D, CGBitFieldInfo::MakeInfo(Types, D, FieldOffset, - FieldSize))); + BitFields.insert(std::make_pair(D, + CGBitFieldInfo::MakeInfo(Types, D, FieldOffset, FieldSize))); AppendBytes(NumBytesToAppend); @@ -401,7 +401,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, AppendPadding(FieldOffsetInBytes, TypeAlignment); // Now append the field. - LLVMFields.push_back(LLVMFieldInfo(D, FieldTypes.size())); + Fields[D] = FieldTypes.size(); AppendField(FieldOffsetInBytes, Ty); return true; @@ -426,14 +426,13 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, FieldTy = llvm::ArrayType::get(FieldTy, NumBytesToAppend); // Add the bit field info. - LLVMBitFields.push_back( - LLVMBitFieldInfo(Field, CGBitFieldInfo::MakeInfo(Types, Field, - 0, FieldSize))); + BitFields.insert(std::make_pair(Field, + CGBitFieldInfo::MakeInfo(Types, Field, 0, FieldSize))); return FieldTy; } // This is a regular union field. - LLVMFields.push_back(LLVMFieldInfo(Field, 0)); + Fields[Field] = 0; return Types.ConvertTypeForMemRecursive(Field->getType()); } @@ -495,41 +494,51 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { AppendPadding(RecordSize, Align); } -void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *BaseDecl, - uint64_t BaseOffset) { - CheckZeroInitializable(BaseDecl); +void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base, + uint64_t baseOffsetInBits) { + uint64_t baseOffsetInBytes = baseOffsetInBits / 8; + AppendPadding(baseOffsetInBytes, 1); - const ASTRecordLayout &Layout = - Types.getContext().getASTRecordLayout(BaseDecl); - - CharUnits NonVirtualSize = Layout.getNonVirtualSize(); - - AppendPadding(BaseOffset / 8, 1); - - // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can. - AppendBytes(NonVirtualSize.getQuantity()); + const ASTRecordLayout &baseASTLayout + = Types.getContext().getASTRecordLayout(base); + + // FIXME: use a better type than [sizeof(base) x i8]. + // We could use the base layout's subobject type as the actualy + // subobject type in the layout if its size is the nvsize of the + // base, or if we'd need padding out to the enclosing object anyhow. + AppendBytes(baseASTLayout.getNonVirtualSize()); +} + +void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *base, + uint64_t baseOffsetInBits) { + // Ignore empty bases. + if (base->isEmpty()) return; + + const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base); + if (IsZeroInitializableAsBase) { + assert(IsZeroInitializable && + "class zero-initializable as base but not as complete object"); + + IsZeroInitializable = IsZeroInitializableAsBase = + baseLayout.isZeroInitializableAsBase(); + } + + LayoutBase(base, baseOffsetInBits); + NonVirtualBases[base] = (FieldTypes.size() - 1); } void -CGRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *BaseDecl, - uint64_t BaseOffset) { +CGRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *base, + uint64_t baseOffsetInBits) { // Ignore empty bases. - if (BaseDecl->isEmpty()) - return; + if (base->isEmpty()) return; - CheckZeroInitializable(BaseDecl); + const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base); + if (IsZeroInitializable) + IsZeroInitializable = baseLayout.isZeroInitializableAsBase(); - const ASTRecordLayout &Layout = - Types.getContext().getASTRecordLayout(BaseDecl); - - CharUnits NonVirtualSize = Layout.getNonVirtualSize(); - - AppendPadding(BaseOffset / 8, 1); - - // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can. - AppendBytes(NonVirtualSize.getQuantity()); - - // FIXME: Add the vbase field info. + LayoutBase(base, baseOffsetInBits); + VirtualBases[base] = (FieldTypes.size() - 1); } /// LayoutVirtualBases - layout the non-virtual bases of a record decl. @@ -561,18 +570,6 @@ CGRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, } } -void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl, - uint64_t BaseOffset) { - // Ignore empty bases. - if (BaseDecl->isEmpty()) - return; - - LayoutBase(BaseDecl, BaseOffset); - - // Append the base field. - LLVMNonVirtualBases.push_back(LLVMBaseInfo(BaseDecl, FieldTypes.size() - 1)); -} - void CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout) { @@ -618,37 +615,40 @@ bool CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) { const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD); - CharUnits NonVirtualSize = Layout.getNonVirtualSize(); CharUnits NonVirtualAlign = Layout.getNonVirtualAlign(); uint64_t AlignedNonVirtualTypeSize = NonVirtualSize.RoundUpToAlignment(NonVirtualAlign).getQuantity(); - // First check if we can use the same fields as for the complete class. uint64_t RecordSize = Layout.getSize().getQuantity(); - if (AlignedNonVirtualTypeSize == RecordSize) { - NonVirtualBaseTypeIsSameAsCompleteType = true; + if (AlignedNonVirtualTypeSize == RecordSize) return true; - } // Check if we need padding. uint64_t AlignedNextFieldOffset = llvm::RoundUpToAlignment(NextFieldOffsetInBytes, getAlignmentAsLLVMStruct()); - if (AlignedNextFieldOffset > AlignedNonVirtualTypeSize) + if (AlignedNextFieldOffset > AlignedNonVirtualTypeSize) { + assert(!Packed && "cannot layout even as packed struct"); return false; // Needs packing. - - NonVirtualBaseFieldTypes = FieldTypes; - - if (AlignedNonVirtualTypeSize == AlignedNextFieldOffset) { - // We don't need any padding. - return true; } - uint64_t NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset; - NonVirtualBaseFieldTypes.push_back(getByteArrayType(NumBytes)); + bool needsPadding = (AlignedNonVirtualTypeSize != AlignedNextFieldOffset); + if (needsPadding) { + uint64_t NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset; + FieldTypes.push_back(getByteArrayType(NumBytes)); + } + + BaseSubobjectType = llvm::StructType::get(Types.getLLVMContext(), + FieldTypes, Packed); + + if (needsPadding) { + // Pull the padding back off. + FieldTypes.pop_back(); + } + return true; } @@ -777,36 +777,29 @@ unsigned CGRecordLayoutBuilder::getAlignmentAsLLVMStruct() const { return MaxAlignment; } +/// Merge in whether a field of the given type is zero-initializable. void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) { // This record already contains a member pointer. - if (!IsZeroInitializable) + if (!IsZeroInitializableAsBase) return; // Can only have member pointers if we're compiling C++. if (!Types.getContext().getLangOptions().CPlusPlus) return; - T = Types.getContext().getBaseElementType(T); + const Type *elementType = T->getBaseElementTypeUnsafe(); - if (const MemberPointerType *MPT = T->getAs()) { + if (const MemberPointerType *MPT = elementType->getAs()) { if (!Types.getCXXABI().isZeroInitializable(MPT)) - IsZeroInitializable = false; - } else if (const RecordType *RT = T->getAs()) { + IsZeroInitializable = IsZeroInitializableAsBase = false; + } else if (const RecordType *RT = elementType->getAs()) { const CXXRecordDecl *RD = cast(RT->getDecl()); - CheckZeroInitializable(RD); + const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); + if (!Layout.isZeroInitializable()) + IsZeroInitializable = IsZeroInitializableAsBase = false; } } -void CGRecordLayoutBuilder::CheckZeroInitializable(const CXXRecordDecl *RD) { - // This record already contains a member pointer. - if (!IsZeroInitializable) - return; - - const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); - if (!Layout.isZeroInitializable()) - IsZeroInitializable = false; -} - CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { CGRecordLayoutBuilder Builder(*this); @@ -816,30 +809,25 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { Builder.FieldTypes, Builder.Packed); + // If we're in C++, compute the base subobject type. const llvm::StructType *BaseTy = 0; if (isa(D)) { - if (Builder.NonVirtualBaseTypeIsSameAsCompleteType) - BaseTy = Ty; - else if (!Builder.NonVirtualBaseFieldTypes.empty()) - BaseTy = llvm::StructType::get(getLLVMContext(), - Builder.NonVirtualBaseFieldTypes, - Builder.Packed); + BaseTy = Builder.BaseSubobjectType; + if (!BaseTy) BaseTy = Ty; } CGRecordLayout *RL = - new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable); + new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable, + Builder.IsZeroInitializableAsBase); - // Add all the non-virtual base field numbers. - RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(), - Builder.LLVMNonVirtualBases.end()); + RL->NonVirtualBases.swap(Builder.NonVirtualBases); + RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases); // Add all the field numbers. - RL->FieldInfo.insert(Builder.LLVMFields.begin(), - Builder.LLVMFields.end()); + RL->FieldInfo.swap(Builder.Fields); // Add bitfield info. - RL->BitFields.insert(Builder.LLVMBitFields.begin(), - Builder.LLVMBitFields.end()); + RL->BitFields.swap(Builder.BitFields); // Dump the layout, if requested. if (getContext().getLangOptions().DumpRecordLayouts) { @@ -913,9 +901,9 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { void CGRecordLayout::print(llvm::raw_ostream &OS) const { OS << "