diff options
author | Anders Carlsson <andersca@mac.com> | 2009-08-08 19:38:24 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-08-08 19:38:24 +0000 |
commit | a5dd722bdf2f74a1a249fe6661d96a7236aee0f0 (patch) | |
tree | 34381da15854ab2e7cf5cb2781a2d16a97e81c6c /lib/CodeGen/CGRecordLayoutBuilder.cpp | |
parent | 8c241a2844428eb1589c7b77fc6c1888295a2045 (diff) |
Take #pragma pack into account when laying out structs. Fixes rdar://problem/7095436.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78490 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index d3699bb992..4576b808f0 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -27,13 +27,15 @@ using namespace clang; using namespace CodeGen; void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { + Alignment = Types.getContext().getASTRecordLayout(D).getAlignment() / 8; + if (D->isUnion()) { LayoutUnion(D); return; } Packed = D->hasAttr<PackedAttr>(); - + if (LayoutFields(D)) return; @@ -115,6 +117,21 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); unsigned TypeAlignment = getTypeAlignment(Ty); + // If the type alignment is larger then the struct alignment, we must use + // a packed struct. + if (TypeAlignment > Alignment) { + assert(!Packed && "Alignment is wrong even with packed struct!"); + return false; + } + + if (const RecordType *RT = D->getType()->getAs<RecordType>()) { + const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); + if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) { + if (PPA->getAlignment() != TypeAlignment * 8 && !Packed) + return false; + } + } + // Round up the field offset to the alignment of the field type. uint64_t AlignedNextFieldOffsetInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes, TypeAlignment); @@ -193,6 +210,7 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { assert(!D->isUnion() && "Can't call LayoutFields on a union!"); + assert(Alignment && "Did not set alignment!"); const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); |