diff options
author | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
commit | 952eddef9aff85b1e92626e89baaf7a360e2ac85 (patch) | |
tree | df8df0b0067b381eab470a3b8f28d14a552a6340 /lib/AST/RecordLayoutBuilder.cpp | |
parent | ea266cad53e3d49771fa38103913d3ec7a166694 (diff) | |
download | FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.zip FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.tar.gz |
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):
https://llvm.org/svn/llvm-project/cfe/branches/release_34@197841
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 1484 |
1 files changed, 862 insertions, 622 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 42c3ba3..4390e66 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -211,7 +211,7 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD, if (!RD->isEmpty()) return; - // If we have empty structures inside an union, we can assign both + // If we have empty structures inside a union, we can assign both // the same offset. Just avoid pushing them twice in the list. ClassVectorTy& Classes = EmptyClassOffsets[Offset]; if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end()) @@ -573,10 +573,14 @@ protected: unsigned IsMsStruct : 1; - /// UnfilledBitsInLastByte - If the last field laid out was a bitfield, - /// this contains the number of bits in the last byte that can be used for - /// an adjacent bitfield if necessary. - unsigned char UnfilledBitsInLastByte; + /// UnfilledBitsInLastUnit - If the last field laid out was a bitfield, + /// this contains the number of bits in the last unit that can be used for + /// an adjacent bitfield if necessary. The unit in question is usually + /// a byte, but larger units are used if IsMsStruct. + unsigned char UnfilledBitsInLastUnit; + /// LastBitfieldTypeSize - If IsMsStruct, represents the size of the type + /// of the previous field if it was a bitfield. + unsigned char LastBitfieldTypeSize; /// MaxFieldAlignment - The maximum allowed field alignment. This is set by /// #pragma pack. @@ -588,8 +592,6 @@ protected: CharUnits NonVirtualSize; CharUnits NonVirtualAlignment; - FieldDecl *ZeroLengthBitfield; - /// PrimaryBase - the primary base class (if one exists) of the class /// we're laying out. const CXXRecordDecl *PrimaryBase; @@ -602,9 +604,6 @@ protected: /// pointer, as opposed to inheriting one from a primary base class. bool HasOwnVFPtr; - /// VBPtrOffset - Virtual base table offset. Only for MS layout. - CharUnits VBPtrOffset; - typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; /// Bases - base classes and their offsets in the record. @@ -646,13 +645,12 @@ protected: Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), ExternalLayout(false), InferAlignment(false), Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), - UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), + UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0), + MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), - ZeroLengthBitfield(0), PrimaryBase(0), - PrimaryBaseIsVirtual(false), + PrimaryBase(0), PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), - VBPtrOffset(CharUnits::fromQuantity(-1)), FirstNearlyEmptyVBase(0) { } /// Reset this RecordLayoutBuilder to a fresh state, using the given @@ -680,12 +678,6 @@ protected: return Context.getTargetInfo().getCXXABI(); } - bool isMicrosoftCXXABI() const { - return getCXXABI().isMicrosoft(); - } - - void MSLayoutVirtualBases(const CXXRecordDecl *RD); - /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects. llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator; @@ -727,21 +719,12 @@ protected: void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, CharUnits Offset); - bool needsVFTable(const CXXRecordDecl *RD) const; - bool hasNewVirtualFunction(const CXXRecordDecl *RD, - bool IgnoreDestructor = false) const; - bool isPossiblePrimaryBase(const CXXRecordDecl *Base) const; - - void computeVtordisps(const CXXRecordDecl *RD, - ClassSetTy &VtordispVBases); - /// LayoutVirtualBases - Lays out all the virtual bases. void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass); /// LayoutVirtualBase - Lays out a single virtual base. - void LayoutVirtualBase(const BaseSubobjectInfo *Base, - bool IsVtordispNeed = false); + void LayoutVirtualBase(const BaseSubobjectInfo *Base); /// LayoutBase - Will lay out a base and return the offset where it was /// placed, in chars. @@ -851,7 +834,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (isPossiblePrimaryBase(Base)) { + if (Base->isDynamicClass()) { // We found it. PrimaryBase = Base; PrimaryBaseIsVirtual = false; @@ -859,12 +842,6 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { } } - // The Microsoft ABI doesn't have primary virtual bases. - if (isMicrosoftCXXABI()) { - assert(!PrimaryBase && "Should not get here with a primary base!"); - return; - } - // Under the Itanium ABI, if there is no non-virtual primary base class, // try to compute the primary virtual base. The primary virtual base is // the first nearly empty virtual base that is not an indirect primary @@ -1043,7 +1020,7 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { // If this class needs a vtable/vf-table and didn't get one from a // primary base, add it in now. - } else if (needsVFTable(RD)) { + } else if (RD->isDynamicClass()) { assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); CharUnits PtrWidth = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); @@ -1055,26 +1032,17 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { setDataSize(getSize()); } - bool HasDirectVirtualBases = false; - bool HasNonVirtualBaseWithVBTable = false; - // Now lay out the non-virtual bases. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - // Ignore virtual bases, but remember that we saw one. - if (I->isVirtual()) { - HasDirectVirtualBases = true; + // Ignore virtual bases. + if (I->isVirtual()) continue; - } const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); - // Remember if this base has virtual bases itself. - if (BaseDecl->getNumVBases()) - HasNonVirtualBaseWithVBTable = true; - // Skip the primary base, because we've already laid it out. The // !PrimaryBaseIsVirtual check is required because we might have a // non-virtual base of the same type as a primary virtual base. @@ -1087,37 +1055,6 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { LayoutNonVirtualBase(BaseInfo); } - - // In the MS ABI, add the vb-table pointer if we need one, which is - // whenever we have a virtual base and we can't re-use a vb-table - // pointer from a non-virtual base. - if (isMicrosoftCXXABI() && - HasDirectVirtualBases && !HasNonVirtualBaseWithVBTable) { - CharUnits PtrWidth = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - CharUnits PtrAlign = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); - - // MSVC potentially over-aligns the vb-table pointer by giving it - // the max alignment of all the non-virtual objects in the class. - // This is completely unnecessary, but we're not here to pass - // judgment. - // - // Note that we've only laid out the non-virtual bases, so on the - // first pass Alignment won't be set correctly here, but if the - // vb-table doesn't end up aligned correctly we'll come through - // and redo the layout from scratch with the right alignment. - // - // TODO: Instead of doing this, just lay out the fields as if the - // vb-table were at offset zero, then retroactively bump the field - // offsets up. - PtrAlign = std::max(PtrAlign, Alignment); - - EnsureVTablePointerAlignment(PtrAlign); - VBPtrOffset = getSize(); - setSize(getSize() + PtrWidth); - setDataSize(getSize()); - } } void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) { @@ -1166,249 +1103,6 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, } } -/// needsVFTable - Return true if this class needs a vtable or vf-table -/// when laid out as a base class. These are treated the same because -/// they're both always laid out at offset zero. -/// -/// This function assumes that the class has no primary base. -bool RecordLayoutBuilder::needsVFTable(const CXXRecordDecl *RD) const { - assert(!PrimaryBase); - - // In the Itanium ABI, every dynamic class needs a vtable: even if - // this class has no virtual functions as a base class (i.e. it's - // non-polymorphic or only has virtual functions from virtual - // bases),x it still needs a vtable to locate its virtual bases. - if (!isMicrosoftCXXABI()) - return RD->isDynamicClass(); - - // In the MS ABI, we need a vfptr if the class has virtual functions - // other than those declared by its virtual bases. The AST doesn't - // tell us that directly, and checking manually for virtual - // functions that aren't overrides is expensive, but there are - // some important shortcuts: - - // - Non-polymorphic classes have no virtual functions at all. - if (!RD->isPolymorphic()) return false; - - // - Polymorphic classes with no virtual bases must either declare - // virtual functions directly or inherit them, but in the latter - // case we would have a primary base. - if (RD->getNumVBases() == 0) return true; - - return hasNewVirtualFunction(RD); -} - -/// Does the given class inherit non-virtually from any of the classes -/// in the given set? -static bool hasNonVirtualBaseInSet(const CXXRecordDecl *RD, - const ClassSetTy &set) { - for (CXXRecordDecl::base_class_const_iterator - I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - // Ignore virtual links. - if (I->isVirtual()) continue; - - // Check whether the set contains the base. - const CXXRecordDecl *base = I->getType()->getAsCXXRecordDecl(); - if (set.count(base)) - return true; - - // Otherwise, recurse and propagate. - if (hasNonVirtualBaseInSet(base, set)) - return true; - } - - return false; -} - -/// Does the given method (B::foo()) already override a method (A::foo()) -/// such that A requires a vtordisp in B? If so, we don't need to add a -/// new vtordisp for B in a yet-more-derived class C providing C::foo(). -static bool overridesMethodRequiringVtorDisp(const ASTContext &Context, - const CXXMethodDecl *M) { - CXXMethodDecl::method_iterator - I = M->begin_overridden_methods(), E = M->end_overridden_methods(); - if (I == E) return false; - - const ASTRecordLayout::VBaseOffsetsMapTy &offsets = - Context.getASTRecordLayout(M->getParent()).getVBaseOffsetsMap(); - do { - const CXXMethodDecl *overridden = *I; - - // If the overridden method's class isn't recognized as a virtual - // base in the derived class, ignore it. - ASTRecordLayout::VBaseOffsetsMapTy::const_iterator - it = offsets.find(overridden->getParent()); - if (it == offsets.end()) continue; - - // Otherwise, check if the overridden method's class needs a vtordisp. - if (it->second.hasVtorDisp()) return true; - - } while (++I != E); - return false; -} - -/// In the Microsoft ABI, decide which of the virtual bases require a -/// vtordisp field. -void RecordLayoutBuilder::computeVtordisps(const CXXRecordDecl *RD, - ClassSetTy &vtordispVBases) { - // Bail out if we have no virtual bases. - assert(RD->getNumVBases()); - - // Build up the set of virtual bases that we haven't decided yet. - ClassSetTy undecidedVBases; - for (CXXRecordDecl::base_class_const_iterator - I = RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *vbase = I->getType()->getAsCXXRecordDecl(); - undecidedVBases.insert(vbase); - } - assert(!undecidedVBases.empty()); - - // A virtual base requires a vtordisp field in a derived class if it - // requires a vtordisp field in a base class. Walk all the direct - // bases and collect this information. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *base = I->getType()->getAsCXXRecordDecl(); - const ASTRecordLayout &baseLayout = Context.getASTRecordLayout(base); - - // Iterate over the set of virtual bases provided by this class. - for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator - VI = baseLayout.getVBaseOffsetsMap().begin(), - VE = baseLayout.getVBaseOffsetsMap().end(); VI != VE; ++VI) { - // If it doesn't need a vtordisp in this base, ignore it. - if (!VI->second.hasVtorDisp()) continue; - - // If we've already seen it and decided it needs a vtordisp, ignore it. - if (!undecidedVBases.erase(VI->first)) - continue; - - // Add it. - vtordispVBases.insert(VI->first); - - // Quit as soon as we've decided everything. - if (undecidedVBases.empty()) - return; - } - } - - // Okay, we have virtual bases that we haven't yet decided about. A - // virtual base requires a vtordisp if any the non-destructor - // virtual methods declared in this class directly override a method - // provided by that virtual base. (If so, we need to emit a thunk - // for that method, to be used in the construction vftable, which - // applies an additional 'vtordisp' this-adjustment.) - - // Collect the set of bases directly overridden by any method in this class. - // It's possible that some of these classes won't be virtual bases, or won't be - // provided by virtual bases, or won't be virtual bases in the overridden - // instance but are virtual bases elsewhere. Only the last matters for what - // we're doing, and we can ignore those: if we don't directly override - // a method provided by a virtual copy of a base class, but we do directly - // override a method provided by a non-virtual copy of that base class, - // then we must indirectly override the method provided by the virtual base, - // and so we should already have collected it in the loop above. - ClassSetTy overriddenBases; - for (CXXRecordDecl::method_iterator - M = RD->method_begin(), E = RD->method_end(); M != E; ++M) { - // Ignore non-virtual methods and destructors. - if (isa<CXXDestructorDecl>(*M) || !M->isVirtual()) - continue; - - for (CXXMethodDecl::method_iterator I = M->begin_overridden_methods(), - E = M->end_overridden_methods(); I != E; ++I) { - const CXXMethodDecl *overriddenMethod = (*I); - - // Ignore methods that override methods from vbases that require - // require vtordisps. - if (overridesMethodRequiringVtorDisp(Context, overriddenMethod)) - continue; - - // As an optimization, check immediately whether we're overriding - // something from the undecided set. - const CXXRecordDecl *overriddenBase = overriddenMethod->getParent(); - if (undecidedVBases.erase(overriddenBase)) { - vtordispVBases.insert(overriddenBase); - if (undecidedVBases.empty()) return; - - // We can't 'continue;' here because one of our undecided - // vbases might non-virtually inherit from this base. - // Consider: - // struct A { virtual void foo(); }; - // struct B : A {}; - // struct C : virtual A, virtual B { virtual void foo(); }; - // We need a vtordisp for B here. - } - - // Otherwise, just collect it. - overriddenBases.insert(overriddenBase); - } - } - - // Walk the undecided v-bases and check whether they (non-virtually) - // provide any of the overridden bases. We don't need to consider - // virtual links because the vtordisp inheres to the layout - // subobject containing the base. - for (ClassSetTy::const_iterator - I = undecidedVBases.begin(), E = undecidedVBases.end(); I != E; ++I) { - if (hasNonVirtualBaseInSet(*I, overriddenBases)) - vtordispVBases.insert(*I); - } -} - -/// hasNewVirtualFunction - Does the given polymorphic class declare a -/// virtual function that does not override a method from any of its -/// base classes? -bool -RecordLayoutBuilder::hasNewVirtualFunction(const CXXRecordDecl *RD, - bool IgnoreDestructor) const { - if (!RD->getNumBases()) - return true; - - for (CXXRecordDecl::method_iterator method = RD->method_begin(); - method != RD->method_end(); - ++method) { - if (method->isVirtual() && !method->size_overridden_methods() && - !(IgnoreDestructor && method->getKind() == Decl::CXXDestructor)) { - return true; - } - } - return false; -} - -/// isPossiblePrimaryBase - Is the given base class an acceptable -/// primary base class? -bool -RecordLayoutBuilder::isPossiblePrimaryBase(const CXXRecordDecl *base) const { - // In the Itanium ABI, a class can be a primary base class if it has - // a vtable for any reason. - if (!isMicrosoftCXXABI()) - return base->isDynamicClass(); - - // In the MS ABI, a class can only be a primary base class if it - // provides a vf-table at a static offset. That means it has to be - // non-virtual base. The existence of a separate vb-table means - // that it's possible to get virtual functions only from a virtual - // base, which we have to guard against. - - // First off, it has to have virtual functions. - if (!base->isPolymorphic()) return false; - - // If it has no virtual bases, then the vfptr must be at a static offset. - if (!base->getNumVBases()) return true; - - // Otherwise, the necessary information is cached in the layout. - const ASTRecordLayout &layout = Context.getASTRecordLayout(base); - - // If the base has its own vfptr, it can be a primary base. - if (layout.hasOwnVFPtr()) return true; - - // If the base has a primary base class, then it can be a primary base. - if (layout.getPrimaryBase()) return true; - - // Otherwise it can't. - return false; -} - void RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) { @@ -1458,39 +1152,7 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, } } -void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) { - if (!RD->getNumVBases()) - return; - - ClassSetTy VtordispVBases; - computeVtordisps(RD, VtordispVBases); - - // This is substantially simplified because there are no virtual - // primary bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); - const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl); - assert(BaseInfo && "Did not find virtual base info!"); - - // If this base requires a vtordisp, add enough space for an int field. - // This is apparently always 32-bits, even on x64. - bool vtordispNeeded = false; - if (VtordispVBases.count(BaseDecl)) { - CharUnits IntSize = - CharUnits::fromQuantity(Context.getTargetInfo().getIntWidth() / 8); - - setSize(getSize() + IntSize); - setDataSize(getSize()); - vtordispNeeded = true; - } - - LayoutVirtualBase(BaseInfo, vtordispNeeded); - } -} - -void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base, - bool IsVtordispNeed) { +void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { assert(!Base->Derived && "Trying to lay out a primary virtual base!"); // Layout the base. @@ -1499,10 +1161,9 @@ void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base, // Add its base class offset. assert(!VBases.count(Base->Class) && "vbase offset already exists!"); VBases.insert(std::make_pair(Base->Class, - ASTRecordLayout::VBaseInfo(Offset, IsVtordispNeed))); + ASTRecordLayout::VBaseInfo(Offset, false))); - if (!isMicrosoftCXXABI()) - AddPrimaryVirtualBaseOffsets(Base, Offset); + AddPrimaryVirtualBaseOffsets(Base, Offset); } CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { @@ -1530,18 +1191,19 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { } } + CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlign(); + CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; + // If we have an empty base class, try to place it at offset 0. if (Base->Class->isEmpty() && (!HasExternalLayout || Offset == CharUnits::Zero()) && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { setSize(std::max(getSize(), Layout.getSize())); + UpdateAlignment(BaseAlign, UnpackedBaseAlign); return CharUnits::Zero(); } - CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlign(); - CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; - // The maximum field alignment overrides base align. if (!MaxFieldAlignment.isZero()) { BaseAlign = std::min(BaseAlign, MaxFieldAlignment); @@ -1655,24 +1317,8 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { Context.getTargetInfo().getCharAlign())); NonVirtualAlignment = Alignment; - if (isMicrosoftCXXABI()) { - if (NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) { - CharUnits AlignMember = - NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize; - - setSize(getSize() + AlignMember); - setDataSize(getSize()); - - NonVirtualSize = Context.toCharUnitsFromBits( - llvm::RoundUpToAlignment(getSizeInBits(), - Context.getTargetInfo().getCharAlign())); - } - - MSLayoutVirtualBases(RD); - } else { - // Lay out the virtual bases and add the primary virtual base offsets. - LayoutVirtualBases(RD, RD); - } + // Lay out the virtual bases and add the primary virtual base offsets. + LayoutVirtualBases(RD, RD); // Finally, round the size of the total struct up to the alignment // of the struct itself. @@ -1728,123 +1374,9 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. - const FieldDecl *LastFD = 0; - ZeroLengthBitfield = 0; - unsigned RemainingInAlignment = 0; for (RecordDecl::field_iterator Field = D->field_begin(), - FieldEnd = D->field_end(); Field != FieldEnd; ++Field) { - if (IsMsStruct) { - FieldDecl *FD = *Field; - if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) - ZeroLengthBitfield = FD; - // Zero-length bitfields following non-bitfield members are - // ignored: - else if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) - continue; - // FIXME. streamline these conditions into a simple one. - else if (Context.BitfieldFollowsBitfield(FD, LastFD) || - Context.BitfieldFollowsNonBitfield(FD, LastFD) || - Context.NonBitfieldFollowsBitfield(FD, LastFD)) { - // 1) Adjacent bit fields are packed into the same 1-, 2-, or - // 4-byte allocation unit if the integral types are the same - // size and if the next bit field fits into the current - // allocation unit without crossing the boundary imposed by the - // common alignment requirements of the bit fields. - // 2) Establish a new alignment for a bitfield following - // a non-bitfield if size of their types differ. - // 3) Establish a new alignment for a non-bitfield following - // a bitfield if size of their types differ. - std::pair<uint64_t, unsigned> FieldInfo = - Context.getTypeInfo(FD->getType()); - uint64_t TypeSize = FieldInfo.first; - unsigned FieldAlign = FieldInfo.second; - // This check is needed for 'long long' in -m32 mode. - if (TypeSize > FieldAlign && - (Context.hasSameType(FD->getType(), - Context.UnsignedLongLongTy) - ||Context.hasSameType(FD->getType(), - Context.LongLongTy))) - FieldAlign = TypeSize; - FieldInfo = Context.getTypeInfo(LastFD->getType()); - uint64_t TypeSizeLastFD = FieldInfo.first; - unsigned FieldAlignLastFD = FieldInfo.second; - // This check is needed for 'long long' in -m32 mode. - if (TypeSizeLastFD > FieldAlignLastFD && - (Context.hasSameType(LastFD->getType(), - Context.UnsignedLongLongTy) - || Context.hasSameType(LastFD->getType(), - Context.LongLongTy))) - FieldAlignLastFD = TypeSizeLastFD; - - if (TypeSizeLastFD != TypeSize) { - if (RemainingInAlignment && - LastFD && LastFD->isBitField() && - LastFD->getBitWidthValue(Context)) { - // If previous field was a bitfield with some remaining unfilled - // bits, pad the field so current field starts on its type boundary. - uint64_t FieldOffset = - getDataSizeInBits() - UnfilledBitsInLastByte; - uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.getTargetInfo().getCharAlign())); - setSize(std::max(getSizeInBits(), getDataSizeInBits())); - RemainingInAlignment = 0; - } - - uint64_t UnpaddedFieldOffset = - getDataSizeInBits() - UnfilledBitsInLastByte; - FieldAlign = std::max(FieldAlign, FieldAlignLastFD); - - // The maximum field alignment overrides the aligned attribute. - if (!MaxFieldAlignment.isZero()) { - unsigned MaxFieldAlignmentInBits = - Context.toBits(MaxFieldAlignment); - FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); - } - - uint64_t NewSizeInBits = - llvm::RoundUpToAlignment(UnpaddedFieldOffset, FieldAlign); - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.getTargetInfo().getCharAlign())); - UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; - setSize(std::max(getSizeInBits(), getDataSizeInBits())); - } - if (FD->isBitField()) { - uint64_t FieldSize = FD->getBitWidthValue(Context); - assert (FieldSize > 0 && "LayoutFields - ms_struct layout"); - if (RemainingInAlignment < FieldSize) - RemainingInAlignment = TypeSize - FieldSize; - else - RemainingInAlignment -= FieldSize; - } - } - else if (FD->isBitField()) { - uint64_t FieldSize = FD->getBitWidthValue(Context); - std::pair<uint64_t, unsigned> FieldInfo = - Context.getTypeInfo(FD->getType()); - uint64_t TypeSize = FieldInfo.first; - RemainingInAlignment = TypeSize - FieldSize; - } - LastFD = FD; - } - else if (!Context.getTargetInfo().useBitFieldTypeAlignment() && - Context.getTargetInfo().useZeroLengthBitfieldAlignment()) { - if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) - ZeroLengthBitfield = *Field; - } + FieldEnd = D->field_end(); Field != FieldEnd; ++Field) LayoutField(*Field); - } - if (IsMsStruct && RemainingInAlignment && - LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) { - // If we ended a bitfield before the full length of the type then - // pad the struct out to the full length of the last type. - uint64_t FieldOffset = - getDataSizeInBits() - UnfilledBitsInLastByte; - uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.getTargetInfo().getCharAlign())); - setSize(std::max(getSizeInBits(), getDataSizeInBits())); - } } void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1878,10 +1410,11 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, CharUnits TypeAlign = Context.getTypeAlignInChars(Type); // We're not going to use any of the unfilled bits in the last byte. - UnfilledBitsInLastByte = 0; + UnfilledBitsInLastUnit = 0; + LastBitfieldTypeSize = 0; uint64_t FieldOffset; - uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; if (IsUnion) { setDataSize(std::max(getDataSizeInBits(), FieldSize)); @@ -1896,7 +1429,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, Context.getTargetInfo().getCharAlign())); - UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; + UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; } // Place this field at the current location. @@ -1914,49 +1447,43 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); - uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; - uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; uint64_t FieldSize = D->getBitWidthValue(Context); - std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType()); uint64_t TypeSize = FieldInfo.first; unsigned FieldAlign = FieldInfo.second; - - // This check is needed for 'long long' in -m32 mode. - if (IsMsStruct && (TypeSize > FieldAlign) && - (Context.hasSameType(D->getType(), - Context.UnsignedLongLongTy) - || Context.hasSameType(D->getType(), Context.LongLongTy))) - FieldAlign = TypeSize; - if (ZeroLengthBitfield) { - std::pair<uint64_t, unsigned> FieldInfo; - unsigned ZeroLengthBitfieldAlignment; - if (IsMsStruct) { - // If a zero-length bitfield is inserted after a bitfield, - // and the alignment of the zero-length bitfield is - // greater than the member that follows it, `bar', `bar' - // will be aligned as the type of the zero-length bitfield. - if (ZeroLengthBitfield != D) { - FieldInfo = Context.getTypeInfo(ZeroLengthBitfield->getType()); - ZeroLengthBitfieldAlignment = FieldInfo.second; - // Ignore alignment of subsequent zero-length bitfields. - if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) - FieldAlign = ZeroLengthBitfieldAlignment; - if (FieldSize) - ZeroLengthBitfield = 0; - } - } else { - // The alignment of a zero-length bitfield affects the alignment - // of the next member. The alignment is the max of the zero - // length bitfield's alignment and a target specific fixed value. - unsigned ZeroLengthBitfieldBoundary = - Context.getTargetInfo().getZeroLengthBitfieldBoundary(); - if (ZeroLengthBitfieldBoundary > FieldAlign) - FieldAlign = ZeroLengthBitfieldBoundary; + if (IsMsStruct) { + // The field alignment for integer types in ms_struct structs is + // always the size. + FieldAlign = TypeSize; + // Ignore zero-length bitfields after non-bitfields in ms_struct structs. + if (!FieldSize && !LastBitfieldTypeSize) + FieldAlign = 1; + // If a bitfield is followed by a bitfield of a different size, don't + // pack the bits together in ms_struct structs. + if (LastBitfieldTypeSize != TypeSize) { + UnfilledBitsInLastUnit = 0; + LastBitfieldTypeSize = 0; } } + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; + uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; + + bool ZeroLengthBitfield = false; + if (!Context.getTargetInfo().useBitFieldTypeAlignment() && + Context.getTargetInfo().useZeroLengthBitfieldAlignment() && + FieldSize == 0) { + // The alignment of a zero-length bitfield affects the alignment + // of the next member. The alignment is the max of the zero + // length bitfield's alignment and a target specific fixed value. + ZeroLengthBitfield = true; + unsigned ZeroLengthBitfieldBoundary = + Context.getTargetInfo().getZeroLengthBitfieldBoundary(); + if (ZeroLengthBitfieldBoundary > FieldAlign) + FieldAlign = ZeroLengthBitfieldBoundary; + } + if (FieldSize > TypeSize) { LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D); return; @@ -1982,6 +1509,13 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } + // ms_struct bitfields always have to start at a round alignment. + if (IsMsStruct && !LastBitfieldTypeSize) { + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, + UnpackedFieldAlign); + } + // Check if we need to add padding to give the field the correct alignment. if (FieldSize == 0 || (MaxFieldAlignment.isZero() && @@ -1996,12 +1530,11 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Padding members don't affect overall alignment, unless zero length bitfield // alignment is enabled. - if (!D->getIdentifier() && !Context.getTargetInfo().useZeroLengthBitfieldAlignment()) + if (!D->getIdentifier() && + !Context.getTargetInfo().useZeroLengthBitfieldAlignment() && + !IsMsStruct) FieldAlign = UnpackedFieldAlign = 1; - if (!IsMsStruct) - ZeroLengthBitfield = 0; - if (ExternalLayout) FieldOffset = updateExternalFieldOffset(D, FieldOffset); @@ -2017,11 +1550,29 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // FIXME: I think FieldSize should be TypeSize here. setDataSize(std::max(getDataSizeInBits(), FieldSize)); } else { - uint64_t NewSizeInBits = FieldOffset + FieldSize; - - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.getTargetInfo().getCharAlign())); - UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; + if (IsMsStruct && FieldSize) { + // Under ms_struct, a bitfield always takes up space equal to the size + // of the type. We can't just change the alignment computation on the + // other codepath because of the way this interacts with #pragma pack: + // in a packed struct, we need to allocate misaligned space in the + // struct to hold the bitfield. + if (!UnfilledBitsInLastUnit) { + setDataSize(FieldOffset + TypeSize); + UnfilledBitsInLastUnit = TypeSize - FieldSize; + } else if (UnfilledBitsInLastUnit < FieldSize) { + setDataSize(getDataSizeInBits() + TypeSize); + UnfilledBitsInLastUnit = TypeSize - FieldSize; + } else { + UnfilledBitsInLastUnit -= FieldSize; + } + LastBitfieldTypeSize = TypeSize; + } else { + uint64_t NewSizeInBits = FieldOffset + FieldSize; + uint64_t BitfieldAlignment = Context.getTargetInfo().getCharAlign(); + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, BitfieldAlignment)); + UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; + LastBitfieldTypeSize = 0; + } } // Update the size. @@ -2038,10 +1589,11 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { return; } - uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; // Reset the unfilled bits. - UnfilledBitsInLastByte = 0; + UnfilledBitsInLastUnit = 0; + LastBitfieldTypeSize = 0; bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); CharUnits FieldOffset = @@ -2069,30 +1621,6 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; - if (ZeroLengthBitfield) { - CharUnits ZeroLengthBitfieldBoundary = - Context.toCharUnitsFromBits( - Context.getTargetInfo().getZeroLengthBitfieldBoundary()); - if (ZeroLengthBitfieldBoundary == CharUnits::Zero()) { - // If a zero-length bitfield is inserted after a bitfield, - // and the alignment of the zero-length bitfield is - // greater than the member that follows it, `bar', `bar' - // will be aligned as the type of the zero-length bitfield. - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); - CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; - if (ZeroLengthBitfieldAlignment > FieldAlign) - FieldAlign = ZeroLengthBitfieldAlignment; - } else if (ZeroLengthBitfieldBoundary > FieldAlign) { - // Align 'bar' based on a fixed alignment specified by the target. - assert(Context.getTargetInfo().useZeroLengthBitfieldAlignment() && - "ZeroLengthBitfieldBoundary should only be used in conjunction" - " with useZeroLengthBitfieldAlignment."); - FieldAlign = ZeroLengthBitfieldBoundary; - } - ZeroLengthBitfield = 0; - } - if (IsMsStruct) { // If MS bitfield layout is required, figure out what type is being // laid out and align the field to the width of that type. @@ -2189,7 +1717,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // Finally, round the size of the record up to the alignment of the // record itself. - uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; + uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; uint64_t UnpackedSizeInBits = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(UnpackedAlignment)); @@ -2209,13 +1737,6 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { return; } - - // MSVC doesn't round up to the alignment of the record with virtual bases. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (isMicrosoftCXXABI() && RD->getNumVBases()) - return; - } - // Set the size to the final size. setSize(RoundedSize); @@ -2354,7 +1875,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, // A class that is not externally visible doesn't have a key function. (Or // at least, there's no point to assigning a key function to such a class; // this doesn't affect the ABI.) - if (RD->getLinkage() != ExternalLinkage) + if (!RD->isExternallyVisible()) return 0; // Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6. @@ -2453,6 +1974,732 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) { llvm_unreachable("bad tail-padding use kind"); } +static bool isMsLayout(const RecordDecl* D) { + return D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft(); +} + +// This section contains an implementation of struct layout that is, up to the +// included tests, compatible with cl.exe (2012). The layout produced is +// significantly different than those produced by the Itanium ABI. Here we note +// the most important differences. +// +// * The alignment of bitfields in unions is ignored when computing the +// alignment of the union. +// * The existance of zero-width bitfield that occurs after anything other than +// a non-zero length bitfield is ignored. +// * The Itanium equivalent vtable pointers are split into a vfptr (virtual +// function pointer) and a vbptr (virtual base pointer). They can each be +// shared with a, non-virtual bases. These bases need not be the same. vfptrs +// always occur at offset 0. vbptrs can occur at an +// arbitrary offset and are placed after non-virtual bases but before fields. +// * Virtual bases sometimes require a 'vtordisp' field that is laid out before +// the virtual base and is used in conjunction with virtual overrides during +// construction and destruction. +// * vfptrs are allocated in a block of memory equal to the alignment of the +// fields and non-virtual bases at offset 0 in 32 bit mode and in a pointer +// sized block of memory in 64 bit mode. +// * vbptrs are allocated in a block of memory equal to the alignment of the +// fields and non-virtual bases. This block is at a potentially unaligned +// offset. If the allocation slot is unaligned and the alignment is less than +// or equal to the pointer size, additional space is allocated so that the +// pointer can be aligned properly. This causes very strange effects on the +// placement of objects after the allocated block. (see the code). +// * vtordisps are allocated in a block of memory with size and alignment equal +// to the alignment of the completed structure (before applying __declspec( +// align())). The vtordisp always occur at the end of the allocation block, +// immediately prior to the virtual base. +// * The last zero sized non-virtual base is allocated after the placement of +// vbptr if one exists and can be placed at the end of the struct, potentially +// aliasing either the first member or another struct allocated after this +// one. +// * The last zero size virtual base may be placed at the end of the struct. +// and can potentially alias a zero sized type in the next struct. +// * If the last field is a non-zero length bitfield and we have any virtual +// bases then some extra padding is added before the virtual bases for no +// obvious reason. +// * When laying out empty non-virtual bases, an extra byte of padding is added +// if the non-virtual base before the empty non-virtual base has a vbptr. + + +namespace { +struct MicrosoftRecordLayoutBuilder { + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; + MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {} +private: + MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) + LLVM_DELETED_FUNCTION; + void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION; +public: + + void layout(const RecordDecl *RD); + void cxxLayout(const CXXRecordDecl *RD); + /// \brief Initializes size and alignment and honors some flags. + void initializeLayout(const RecordDecl *RD); + /// \brief Initialized C++ layout, compute alignment and virtual alignment and + /// existance of vfptrs and vbptrs. Alignment is needed before the vfptr is + /// laid out. + void initializeCXXLayout(const CXXRecordDecl *RD); + void layoutVFPtr(const CXXRecordDecl *RD); + void layoutNonVirtualBases(const CXXRecordDecl *RD); + void layoutNonVirtualBase(const CXXRecordDecl *RD); + void layoutVBPtr(const CXXRecordDecl *RD); + /// \brief Lays out the fields of the record. Also rounds size up to + /// alignment. + void layoutFields(const RecordDecl *RD); + void layoutField(const FieldDecl *FD); + void layoutBitField(const FieldDecl *FD); + /// \brief Lays out a single zero-width bit-field in the record and handles + /// special cases associated with zero-width bit-fields. + void layoutZeroWidthBitField(const FieldDecl *FD); + void layoutVirtualBases(const CXXRecordDecl *RD); + void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp); + /// \brief Flushes the lazy virtual base and conditionally rounds up to + /// alignment. + void finalizeCXXLayout(const CXXRecordDecl *RD); + void honorDeclspecAlign(const RecordDecl *RD); + + /// \brief Updates the alignment of the type. This function doesn't take any + /// properties (such as packedness) into account. getAdjustedFieldInfo() + /// adjustes for packedness. + void updateAlignment(CharUnits NewAlignment) { + Alignment = std::max(Alignment, NewAlignment); + } + /// \brief Gets the size and alignment taking attributes into account. + std::pair<CharUnits, CharUnits> getAdjustedFieldInfo(const FieldDecl *FD); + /// \brief Places a field at offset 0. + void placeFieldAtZero() { FieldOffsets.push_back(0); } + /// \brief Places a field at an offset in CharUnits. + void placeFieldAtOffset(CharUnits FieldOffset) { + FieldOffsets.push_back(Context.toBits(FieldOffset)); + } + /// \brief Places a bitfield at a bit offset. + void placeFieldAtBitOffset(uint64_t FieldOffset) { + FieldOffsets.push_back(FieldOffset); + } + /// \brief Compute the set of virtual bases for which vtordisps are required. + llvm::SmallPtrSet<const CXXRecordDecl *, 2> + computeVtorDispSet(const CXXRecordDecl *RD); + + const ASTContext &Context; + /// \brief The size of the record being laid out. + CharUnits Size; + /// \brief The current alignment of the record layout. + CharUnits Alignment; + /// \brief The collection of field offsets. + SmallVector<uint64_t, 16> FieldOffsets; + /// \brief The maximum allowed field alignment. This is set by #pragma pack. + CharUnits MaxFieldAlignment; + /// \brief Alignment does not occur for virtual bases unless something + /// forces it to by explicitly using __declspec(align()) + bool AlignAfterVBases : 1; + bool IsUnion : 1; + /// \brief True if the last field laid out was a bitfield and was not 0 + /// width. + bool LastFieldIsNonZeroWidthBitfield : 1; + /// \brief The size of the allocation of the currently active bitfield. + /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield + /// is true. + CharUnits CurrentBitfieldSize; + /// \brief The number of remaining bits in our last bitfield allocation. + /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is + /// true. + unsigned RemainingBitsInField; + + /// \brief The data alignment of the record layout. + CharUnits DataSize; + /// \brief The alignment of the non-virtual portion of the record layout + /// without the impact of the virtual pointers. + /// Only used for C++ layouts. + CharUnits BasesAndFieldsAlignment; + /// \brief The alignment of the non-virtual portion of the record layout + /// Only used for C++ layouts. + CharUnits NonVirtualAlignment; + /// \brief The additional alignment imposed by the virtual bases. + CharUnits VirtualAlignment; + /// \brief The primary base class (if one exists). + const CXXRecordDecl *PrimaryBase; + /// \brief The class we share our vb-pointer with. + const CXXRecordDecl *SharedVBPtrBase; + /// \brief True if the class has a vftable pointer that can be extended + /// by this class or classes derived from it. Such a vfptr will always occur + /// at offset 0. + bool HasExtendableVFPtr : 1; + /// \brief True if the class has a (not necessarily its own) vbtable pointer. + bool HasVBPtr : 1; + /// \brief Offset to the virtual base table pointer (if one exists). + CharUnits VBPtrOffset; + /// \brief Base classes and their offsets in the record. + BaseOffsetsMapTy Bases; + /// \brief virtual base classes and their offsets in the record. + ASTRecordLayout::VBaseOffsetsMapTy VBases; + /// \brief The size of a pointer. + CharUnits PointerSize; + /// \brief The alignment of a pointer. + CharUnits PointerAlignment; + /// \brief Holds an empty base we haven't yet laid out. + const CXXRecordDecl *LazyEmptyBase; + /// \brief Lets us know if the last base we laid out was empty. Only used + /// when adjusting the placement of a last zero-sized base in 64 bit mode. + bool LastBaseWasEmpty; + /// \brief Lets us know if we're in 64-bit mode + bool Is64BitMode; + /// \brief True if the last non-virtual base has a vbptr. + bool LastNonVirtualBaseHasVBPtr; +}; +} // namespace + +std::pair<CharUnits, CharUnits> +MicrosoftRecordLayoutBuilder::getAdjustedFieldInfo(const FieldDecl *FD) { + std::pair<CharUnits, CharUnits> FieldInfo = + Context.getTypeInfoInChars(FD->getType()); + + // If we're not on win32 and using ms_struct the field alignment will be wrong + // for 64 bit types, so we fix that here. + if (FD->getASTContext().getTargetInfo().getTriple().getOS() != + llvm::Triple::Win32) { + QualType T = Context.getBaseElementType(FD->getType()); + if (const BuiltinType *BTy = T->getAs<BuiltinType>()) { + CharUnits TypeSize = Context.getTypeSizeInChars(BTy); + if (TypeSize > FieldInfo.second) + FieldInfo.second = TypeSize; + } + } + + // Respect packed attribute. + if (FD->hasAttr<PackedAttr>()) + FieldInfo.second = CharUnits::One(); + // Respect pack pragma. + else if (!MaxFieldAlignment.isZero()) + FieldInfo.second = std::min(FieldInfo.second, MaxFieldAlignment); + // Respect alignment attributes. + if (unsigned fieldAlign = FD->getMaxAlignment()) { + CharUnits FieldAlign = Context.toCharUnitsFromBits(fieldAlign); + AlignAfterVBases = true; + FieldInfo.second = std::max(FieldInfo.second, FieldAlign); + } + return FieldInfo; +} + +void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { + IsUnion = RD->isUnion(); + Is64BitMode = Context.getTargetInfo().getPointerWidth(0) == 64; + + Size = CharUnits::Zero(); + Alignment = CharUnits::One(); + AlignAfterVBases = false; + + // Compute the maximum field alignment. + MaxFieldAlignment = CharUnits::Zero(); + // Honor the default struct packing maximum alignment flag. + if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) + MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); + // Honor the packing attribute. + if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()) + MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment()); + // Packed attribute forces max field alignment to be 1. + if (RD->hasAttr<PackedAttr>()) + MaxFieldAlignment = CharUnits::One(); +} + +void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { + initializeLayout(RD); + layoutFields(RD); + honorDeclspecAlign(RD); +} + +void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { + initializeLayout(RD); + initializeCXXLayout(RD); + layoutVFPtr(RD); + layoutNonVirtualBases(RD); + layoutVBPtr(RD); + layoutFields(RD); + DataSize = Size; + NonVirtualAlignment = Alignment; + layoutVirtualBases(RD); + finalizeCXXLayout(RD); + honorDeclspecAlign(RD); +} + +void +MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) { + // Calculate pointer size and alignment. + PointerSize = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + PointerAlignment = PointerSize; + if (!MaxFieldAlignment.isZero()) + PointerAlignment = std::min(PointerAlignment, MaxFieldAlignment); + + // Initialize information about the bases. + HasVBPtr = false; + HasExtendableVFPtr = false; + SharedVBPtrBase = 0; + PrimaryBase = 0; + VirtualAlignment = CharUnits::One(); + AlignAfterVBases = Is64BitMode; + + // If the record has a dynamic base class, attempt to choose a primary base + // class. It is the first (in direct base class order) non-virtual dynamic + // base class, if one exists. + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); + i != e; ++i) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + // Handle forced alignment. + if (Layout.getAlignAfterVBases()) + AlignAfterVBases = true; + // Handle virtual bases. + if (i->isVirtual()) { + VirtualAlignment = std::max(VirtualAlignment, Layout.getAlignment()); + HasVBPtr = true; + continue; + } + // We located a primary base class! + if (!PrimaryBase && Layout.hasExtendableVFPtr()) { + PrimaryBase = BaseDecl; + HasExtendableVFPtr = true; + } + // We located a base to share a VBPtr with! + if (!SharedVBPtrBase && Layout.hasVBPtr()) { + SharedVBPtrBase = BaseDecl; + HasVBPtr = true; + } + updateAlignment(Layout.getAlignment()); + } + + // Use LayoutFields to compute the alignment of the fields. The layout + // is discarded. This is the simplest way to get all of the bit-field + // behavior correct and is not actually very expensive. + layoutFields(RD); + Size = CharUnits::Zero(); + BasesAndFieldsAlignment = Alignment; + FieldOffsets.clear(); +} + +void MicrosoftRecordLayoutBuilder::layoutVFPtr(const CXXRecordDecl *RD) { + // If we have a primary base then our VFPtr was already laid out + if (PrimaryBase) + return; + + // Look at all of our methods to determine if we need a VFPtr. We need a + // vfptr if we define a new virtual function. + if (!HasExtendableVFPtr && RD->isDynamicClass()) + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); + !HasExtendableVFPtr && i != e; ++i) + HasExtendableVFPtr = i->isVirtual() && i->size_overridden_methods() == 0; + if (!HasExtendableVFPtr) + return; + + // MSVC 32 (but not 64) potentially over-aligns the vf-table pointer by giving + // it the max alignment of all the non-virtual data in the class. The + // resulting layout is essentially { vftbl, { nvdata } }. This is completely + // unnecessary, but we're not here to pass judgment. + updateAlignment(PointerAlignment); + if (Is64BitMode) + Size = Size.RoundUpToAlignment(PointerAlignment) + PointerSize; + else + Size = Size.RoundUpToAlignment(PointerAlignment) + Alignment; +} + +void +MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { + LazyEmptyBase = 0; + LastBaseWasEmpty = false; + LastNonVirtualBaseHasVBPtr = false; + + // Lay out the primary base first. + if (PrimaryBase) + layoutNonVirtualBase(PrimaryBase); + + // Iterate through the bases and lay out the non-virtual ones. + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); + i != e; ++i) { + if (i->isVirtual()) + continue; + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl()); + if (BaseDecl != PrimaryBase) + layoutNonVirtualBase(BaseDecl); + } +} + +void +MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(const CXXRecordDecl *RD) { + const ASTRecordLayout *Layout = RD ? &Context.getASTRecordLayout(RD) : 0; + + // If we have a lazy empty base we haven't laid out yet, do that now. + if (LazyEmptyBase) { + const ASTRecordLayout &LazyLayout = + Context.getASTRecordLayout(LazyEmptyBase); + Size = Size.RoundUpToAlignment(LazyLayout.getAlignment()); + // If the last non-virtual base has a vbptr we add a byte of padding for no + // obvious reason. + if (LastNonVirtualBaseHasVBPtr) + Size++; + Bases.insert(std::make_pair(LazyEmptyBase, Size)); + // Empty bases only consume space when followed by another empty base. + if (RD && Layout->getNonVirtualSize().isZero()) { + LastBaseWasEmpty = true; + Size++; + } + LazyEmptyBase = 0; + LastNonVirtualBaseHasVBPtr = false; + } + + // RD is null when flushing the final lazy base. + if (!RD) + return; + + if (Layout->getNonVirtualSize().isZero()) { + LazyEmptyBase = RD; + return; + } + + // Insert the base here. + CharUnits BaseOffset = Size.RoundUpToAlignment(Layout->getAlignment()); + Bases.insert(std::make_pair(RD, BaseOffset)); + Size = BaseOffset + Layout->getDataSize(); + // Note: we don't update alignment here because it was accounted + // for during initalization. + LastBaseWasEmpty = false; + LastNonVirtualBaseHasVBPtr = Layout->hasVBPtr(); +} + +void MicrosoftRecordLayoutBuilder::layoutVBPtr(const CXXRecordDecl *RD) { + if (!HasVBPtr) + VBPtrOffset = CharUnits::fromQuantity(-1); + else if (SharedVBPtrBase) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase); + VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset(); + } else { + VBPtrOffset = Size.RoundUpToAlignment(PointerAlignment); + CharUnits OldSize = Size; + Size = VBPtrOffset + PointerSize; + if (BasesAndFieldsAlignment <= PointerAlignment) { + // Handle strange padding rules for the lazily placed base. I have no + // explanation for why the last virtual base is padded in such an odd way. + // Two things to note about this padding are that the rules are different + // if the alignment of the bases+fields is <= to the alignemnt of a + // pointer and that the rule in 64-bit mode behaves differently depending + // on if the second to last base was also zero sized. + Size += OldSize % BasesAndFieldsAlignment.getQuantity(); + } else { + if (Is64BitMode) + Size += LastBaseWasEmpty ? CharUnits::One() : CharUnits::Zero(); + else + Size = OldSize + BasesAndFieldsAlignment; + } + updateAlignment(PointerAlignment); + } + + // Flush the lazy empty base. + layoutNonVirtualBase(0); +} + +void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) { + LastFieldIsNonZeroWidthBitfield = false; + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) + layoutField(*Field); + Size = Size.RoundUpToAlignment(Alignment); +} + +void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { + if (FD->isBitField()) { + layoutBitField(FD); + return; + } + LastFieldIsNonZeroWidthBitfield = false; + + std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); + CharUnits FieldSize = FieldInfo.first; + CharUnits FieldAlign = FieldInfo.second; + + updateAlignment(FieldAlign); + if (IsUnion) { + placeFieldAtZero(); + Size = std::max(Size, FieldSize); + } else { + // Round up the current record size to the field's alignment boundary. + CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + placeFieldAtOffset(FieldOffset); + Size = FieldOffset + FieldSize; + } +} + +void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { + unsigned Width = FD->getBitWidthValue(Context); + if (Width == 0) { + layoutZeroWidthBitField(FD); + return; + } + + std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); + CharUnits FieldSize = FieldInfo.first; + CharUnits FieldAlign = FieldInfo.second; + + // Clamp the bitfield to a containable size for the sake of being able + // to lay them out. Sema will throw an error. + if (Width > Context.toBits(FieldSize)) + Width = Context.toBits(FieldSize); + + // Check to see if this bitfield fits into an existing allocation. Note: + // MSVC refuses to pack bitfields of formal types with different sizes + // into the same allocation. + if (!IsUnion && LastFieldIsNonZeroWidthBitfield && + CurrentBitfieldSize == FieldSize && Width <= RemainingBitsInField) { + placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField); + RemainingBitsInField -= Width; + return; + } + + LastFieldIsNonZeroWidthBitfield = true; + CurrentBitfieldSize = FieldSize; + if (IsUnion) { + placeFieldAtZero(); + Size = std::max(Size, FieldSize); + // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. + } else { + // Allocate a new block of memory and place the bitfield in it. + CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + placeFieldAtOffset(FieldOffset); + Size = FieldOffset + FieldSize; + updateAlignment(FieldAlign); + RemainingBitsInField = Context.toBits(FieldSize) - Width; + } +} + +void +MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { + // Zero-width bitfields are ignored unless they follow a non-zero-width + // bitfield. + std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); + CharUnits FieldSize = FieldInfo.first; + CharUnits FieldAlign = FieldInfo.second; + + if (!LastFieldIsNonZeroWidthBitfield) { + placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size); + // TODO: Add a Sema warning that MS ignores alignment for zero + // sized bitfields that occur after zero-size bitfields or non bitfields. + return; + } + + LastFieldIsNonZeroWidthBitfield = false; + if (IsUnion) { + placeFieldAtZero(); + Size = std::max(Size, FieldSize); + } else { + // Round up the current record size to the field's alignment boundary. + CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + placeFieldAtOffset(FieldOffset); + Size = FieldOffset; + updateAlignment(FieldAlign); + } +} + +void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { + if (!HasVBPtr) + return; + + updateAlignment(VirtualAlignment); + + // Zero-sized v-bases obey the alignment attribute so apply it here. The + // alignment attribute is normally accounted for in FinalizeLayout. + if (unsigned MaxAlign = RD->getMaxAlignment()) + updateAlignment(Context.toCharUnitsFromBits(MaxAlign)); + + llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp = + computeVtorDispSet(RD); + + // If the last field we laid out was a non-zero length bitfield then add some + // extra padding for no obvious reason. + if (LastFieldIsNonZeroWidthBitfield) + Size += CurrentBitfieldSize; + + // Iterate through the virtual bases and lay them out. + for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), + e = RD->vbases_end(); + i != e; ++i) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl()); + layoutVirtualBase(BaseDecl, HasVtordisp.count(BaseDecl)); + } +} + +void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const CXXRecordDecl *RD, + bool HasVtordisp) { + if (LazyEmptyBase) { + const ASTRecordLayout &LazyLayout = + Context.getASTRecordLayout(LazyEmptyBase); + Size = Size.RoundUpToAlignment(LazyLayout.getAlignment()); + VBases.insert( + std::make_pair(LazyEmptyBase, ASTRecordLayout::VBaseInfo(Size, false))); + // Empty bases only consume space when followed by another empty base. + // The space consumed is in an Alignment sized/aligned block and the v-base + // is placed at its alignment offset into the chunk, unless its alignment + // is less than 4 bytes, at which it is placed at 4 byte offset in the + // chunk. We have no idea why. + if (RD && Context.getASTRecordLayout(RD).getNonVirtualSize().isZero()) + Size = Size.RoundUpToAlignment(Alignment) + CharUnits::fromQuantity(4); + LazyEmptyBase = 0; + } + + // RD is null when flushing the final lazy virtual base. + if (!RD) + return; + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + if (Layout.getNonVirtualSize().isZero() && !HasVtordisp) { + LazyEmptyBase = RD; + return; + } + + CharUnits BaseNVSize = Layout.getNonVirtualSize(); + CharUnits BaseAlign = Layout.getAlignment(); + + // vtordisps are always 4 bytes (even in 64-bit mode) + if (HasVtordisp) + Size = Size.RoundUpToAlignment(Alignment) + CharUnits::fromQuantity(4); + Size = Size.RoundUpToAlignment(BaseAlign); + + // Insert the base here. + CharUnits BaseOffset = Size.RoundUpToAlignment(BaseAlign); + VBases.insert( + std::make_pair(RD, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); + Size = BaseOffset + BaseNVSize; + // Note: we don't update alignment here because it was accounted for in + // InitializeLayout. +} + +void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const CXXRecordDecl *RD) { + // Flush the lazy virtual base. + layoutVirtualBase(0, false); + + if (RD->vbases_begin() == RD->vbases_end() || AlignAfterVBases) + Size = Size.RoundUpToAlignment(Alignment); + + if (Size.isZero()) + Size = Alignment; +} + +void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl *RD) { + if (unsigned MaxAlign = RD->getMaxAlignment()) { + AlignAfterVBases = true; + updateAlignment(Context.toCharUnitsFromBits(MaxAlign)); + Size = Size.RoundUpToAlignment(Alignment); + } +} + +static bool +RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &HasVtordisp, + const CXXRecordDecl *RD) { + if (HasVtordisp.count(RD)) + return true; + // If any of a virtual bases non-virtual bases (recursively) requires a + // vtordisp than so does this virtual base. + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); + i != e; ++i) + if (!i->isVirtual() && + RequiresVtordisp( + HasVtordisp, + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()))) + return true; + return false; +} + +llvm::SmallPtrSet<const CXXRecordDecl *, 2> +MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { + llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp; + + // If any of our bases need a vtordisp for this type, so do we. Check our + // direct bases for vtordisp requirements. + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); + i != e; ++i) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator + bi = Layout.getVBaseOffsetsMap().begin(), + be = Layout.getVBaseOffsetsMap().end(); + bi != be; ++bi) + if (bi->second.hasVtorDisp()) + HasVtordisp.insert(bi->first); + } + + // If we define a constructor or destructor and override a function that is + // defined in a virtual base's vtable, that virtual bases need a vtordisp. + // Here we collect a list of classes with vtables for which our virtual bases + // actually live. The virtual bases with this property will require + // vtordisps. In addition, virtual bases that contain non-virtual bases that + // define functions we override also require vtordisps, this case is checked + // explicitly below. + if (RD->hasUserDeclaredConstructor() || RD->hasUserDeclaredDestructor()) { + llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work; + // Seed the working set with our non-destructor virtual methods. + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); + i != e; ++i) + if ((*i)->isVirtual() && !isa<CXXDestructorDecl>(*i)) + Work.insert(*i); + while (!Work.empty()) { + const CXXMethodDecl *MD = *Work.begin(); + CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(), + e = MD->end_overridden_methods(); + if (i == e) + // If a virtual method has no-overrides it lives in its parent's vtable. + HasVtordisp.insert(MD->getParent()); + else + Work.insert(i, e); + // We've finished processing this element, remove it from the working set. + Work.erase(MD); + } + } + + // Re-check all of our vbases for vtordisp requirements (in case their + // non-virtual bases have vtordisp requirements). + for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), + e = RD->vbases_end(); + i != e; ++i) { + const CXXRecordDecl *BaseDecl = i->getType()->getAsCXXRecordDecl(); + if (!HasVtordisp.count(BaseDecl) && RequiresVtordisp(HasVtordisp, BaseDecl)) + HasVtordisp.insert(BaseDecl); + } + + return HasVtordisp; +} + +/// \brief Get or compute information about the layout of the specified record +/// (struct/union/class), which indicates its size and field position +/// information. +const ASTRecordLayout * +ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const { + MicrosoftRecordLayoutBuilder Builder(*this); + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + Builder.cxxLayout(RD); + return new (*this) ASTRecordLayout( + *this, Builder.Size, Builder.Alignment, + Builder.HasExtendableVFPtr && !Builder.PrimaryBase, + Builder.HasExtendableVFPtr, + Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets.data(), + Builder.FieldOffsets.size(), Builder.DataSize, + Builder.NonVirtualAlignment, CharUnits::Zero(), Builder.PrimaryBase, + false, Builder.SharedVBPtrBase, Builder.AlignAfterVBases, Builder.Bases, + Builder.VBases); + } else { + Builder.layout(D); + return new (*this) ASTRecordLayout( + *this, Builder.Size, Builder.Alignment, Builder.Size, + Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); + } +} + /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field /// position information. @@ -2468,6 +2715,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { D = D->getDefinition(); assert(D && "Cannot get layout of forward declarations!"); + assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!"); assert(D->isCompleteDefinition() && "Cannot layout type before complete!"); // Look up this layout, if already laid out, return what we have. @@ -2476,27 +2724,15 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *Entry = ASTRecordLayouts[D]; if (Entry) return *Entry; - const ASTRecordLayout *NewEntry; + const ASTRecordLayout *NewEntry = 0; - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + if (isMsLayout(D) && !D->getASTContext().getExternalSource()) { + NewEntry = BuildMicrosoftASTRecordLayout(D); + } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { EmptySubobjectMap EmptySubobjects(*this, RD); RecordLayoutBuilder Builder(*this, &EmptySubobjects); Builder.Layout(RD); - // MSVC gives the vb-table pointer an alignment equal to that of - // the non-virtual part of the structure. That's an inherently - // multi-pass operation. If our first pass doesn't give us - // adequate alignment, try again with the specified minimum - // alignment. This is *much* more maintainable than computing the - // alignment in advance in a separately-coded pass; it's also - // significantly more efficient in the common case where the - // vb-table doesn't need extra padding. - if (Builder.VBPtrOffset != CharUnits::fromQuantity(-1) && - (Builder.VBPtrOffset % Builder.NonVirtualAlignment) != 0) { - Builder.resetWithTargetAlignment(Builder.NonVirtualAlignment); - Builder.Layout(RD); - } - // In certain situations, we are allowed to lay out objects in the // tail-padding of base classes. This is ABI-dependent. // FIXME: this should be stored in the record layout. @@ -2508,12 +2744,12 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { skipTailPadding ? Builder.getSize() : Builder.getDataSize(); CharUnits NonVirtualSize = skipTailPadding ? DataSize : Builder.NonVirtualSize; - NewEntry = new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, Builder.HasOwnVFPtr, - Builder.VBPtrOffset, + RD->isDynamicClass(), + CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets.data(), Builder.FieldOffsets.size(), @@ -2522,6 +2758,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase, Builder.PrimaryBaseIsVirtual, + 0, true, Builder.Bases, Builder.VBases); } else { RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); @@ -2538,43 +2775,45 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { ASTRecordLayouts[D] = NewEntry; if (getLangOpts().DumpRecordLayouts) { - llvm::errs() << "\n*** Dumping AST Record Layout\n"; - DumpRecordLayout(D, llvm::errs(), getLangOpts().DumpRecordLayoutsSimple); + llvm::outs() << "\n*** Dumping AST Record Layout\n"; + DumpRecordLayout(D, llvm::outs(), getLangOpts().DumpRecordLayoutsSimple); } return *NewEntry; } const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { + if (!getTargetInfo().getCXXABI().hasKeyFunctions()) + return 0; + assert(RD->getDefinition() && "Cannot get key function for forward decl!"); RD = cast<CXXRecordDecl>(RD->getDefinition()); - const CXXMethodDecl *&entry = KeyFunctions[RD]; - if (!entry) { - entry = computeKeyFunction(*this, RD); - } + LazyDeclPtr &Entry = KeyFunctions[RD]; + if (!Entry) + Entry = const_cast<CXXMethodDecl*>(computeKeyFunction(*this, RD)); - return entry; + return cast_or_null<CXXMethodDecl>(Entry.get(getExternalSource())); } -void ASTContext::setNonKeyFunction(const CXXMethodDecl *method) { - assert(method == method->getFirstDeclaration() && +void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { + assert(Method == Method->getFirstDecl() && "not working with method declaration from class definition"); // Look up the cache entry. Since we're working with the first // declaration, its parent must be the class definition, which is // the correct key for the KeyFunctions hash. - llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*>::iterator - i = KeyFunctions.find(method->getParent()); + llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator + I = KeyFunctions.find(Method->getParent()); // If it's not cached, there's nothing to do. - if (i == KeyFunctions.end()) return; + if (I == KeyFunctions.end()) return; // If it is cached, check whether it's the target method, and if so, // remove it from the cache. - if (i->second == method) { + if (I->second.get(getExternalSource()) == Method) { // FIXME: remember that we did this for module / chained PCH state? - KeyFunctions.erase(i); + KeyFunctions.erase(I); } } @@ -2676,16 +2915,19 @@ static void DumpCXXRecordLayout(raw_ostream &OS, IndentLevel++; const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - bool HasVfptr = Layout.hasOwnVFPtr(); - bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1); + bool HasOwnVFPtr = Layout.hasOwnVFPtr(); + bool HasOwnVBPtr = Layout.hasOwnVBPtr(); // Vtable pointer. - if (RD->isDynamicClass() && !PrimaryBase && - !C.getTargetInfo().getCXXABI().isMicrosoft()) { + if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(RD)) { PrintOffset(OS, Offset, IndentLevel); OS << '(' << *RD << " vtable pointer)\n"; + } else if (HasOwnVFPtr) { + PrintOffset(OS, Offset, IndentLevel); + // vfptr (for Microsoft C++ ABI) + OS << '(' << *RD << " vftable pointer)\n"; } - + // Dump (non-virtual) bases for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { @@ -2704,12 +2946,8 @@ static void DumpCXXRecordLayout(raw_ostream &OS, /*IncludeVirtualBases=*/false); } - // vfptr and vbptr (for Microsoft C++ ABI) - if (HasVfptr) { - PrintOffset(OS, Offset, IndentLevel); - OS << '(' << *RD << " vftable pointer)\n"; - } - if (HasVbptr) { + // vbptr (for Microsoft C++ ABI) + if (HasOwnVBPtr) { PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); OS << '(' << *RD << " vbtable pointer)\n"; } @@ -2762,7 +3000,8 @@ static void DumpCXXRecordLayout(raw_ostream &OS, PrintIndentNoOffset(OS, IndentLevel - 1); OS << "[sizeof=" << Layout.getSize().getQuantity(); - OS << ", dsize=" << Layout.getDataSize().getQuantity(); + if (!isMsLayout(RD)) + OS << ", dsize=" << Layout.getDataSize().getQuantity(); OS << ", align=" << Layout.getAlignment().getQuantity() << '\n'; PrintIndentNoOffset(OS, IndentLevel - 1); @@ -2789,7 +3028,8 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, OS << "\nLayout: "; OS << "<ASTRecordLayout\n"; OS << " Size:" << toBits(Info.getSize()) << "\n"; - OS << " DataSize:" << toBits(Info.getDataSize()) << "\n"; + if (!isMsLayout(RD)) + OS << " DataSize:" << toBits(Info.getDataSize()) << "\n"; OS << " Alignment:" << toBits(Info.getAlignment()) << "\n"; OS << " FieldOffsets: ["; for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) { |