diff options
Diffstat (limited to 'lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 9f90ec5ff6e0..baafd6836c63 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -108,6 +108,9 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, return true; } + // Check if we have a pointer to data member in this field. + CheckForPointerToDataMember(D->getType()); + assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!"); uint64_t FieldOffsetInBytes = FieldOffset / 8; @@ -162,6 +165,8 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { uint64_t Size = 0; unsigned Align = 0; + bool HasOnlyZeroSizedBitFields = true; + unsigned FieldNo = 0; for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { @@ -181,6 +186,8 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { } else Types.addFieldInfo(*Field, 0); + HasOnlyZeroSizedBitFields = false; + const llvm::Type *FieldTy = Types.ConvertTypeForMemRecursive(Field->getType()); unsigned FieldAlign = Types.getTargetData().getABITypeAlignment(FieldTy); @@ -207,7 +214,8 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { } } if (!Align) { - assert((D->field_begin() == D->field_end()) && "LayoutUnion - Align 0"); + assert(HasOnlyZeroSizedBitFields && + "0-align record did not have all zero-sized bit-fields!"); Align = 1; } @@ -333,23 +341,34 @@ uint64_t CGRecordLayoutBuilder::getTypeSizeInBytes(const llvm::Type *Ty) const { return Types.getTargetData().getTypeAllocSize(Ty); } -void CGRecordLayoutBuilder::CheckForMemberPointer(const FieldDecl *FD) { +void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) { // This record already contains a member pointer. - if (ContainsMemberPointer) + if (ContainsPointerToDataMember) return; // Can only have member pointers if we're compiling C++. if (!Types.getContext().getLangOptions().CPlusPlus) return; - QualType Ty = FD->getType(); - - if (Ty->isMemberPointerType()) { - // We have a member pointer! - ContainsMemberPointer = true; - return; - } + T = Types.getContext().getBaseElementType(T); + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { + if (!MPT->getPointeeType()->isFunctionType()) { + // We have a pointer to data member. + ContainsPointerToDataMember = true; + } + } else if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + // FIXME: It would be better if there was a way to explicitly compute the + // record layout instead of converting to a type. + Types.ConvertTagDeclType(RD); + + const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); + + if (Layout.containsPointerToDataMember()) + ContainsPointerToDataMember = true; + } } CGRecordLayout * @@ -381,5 +400,5 @@ CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types, Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size); } - return new CGRecordLayout(Ty, Builder.ContainsMemberPointer); + return new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember); } |