From: David Majnemer Date: Sun, 13 Apr 2014 08:15:50 +0000 (+0000) Subject: MS ABI: Bitfields FielDecls only align if they allocate X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cfcd9d4f2e62a85e9d7486b73203f66dfea4da0e;p=clang MS ABI: Bitfields FielDecls only align if they allocate Don't consider a __declspec(align) on a bitfield's declaration if it didn't allocate any underlying storage. This fixes PR19414. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206132 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 04a0fab737..5eb87e7fc7 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2291,9 +2291,6 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( if (FD->hasAttr()) Info.Alignment = CharUnits::One(); Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); - // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. - if (!(FD->isBitField() && IsUnion)) - Alignment = std::max(Alignment, Info.Alignment); return Info; } @@ -2472,6 +2469,7 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { } LastFieldIsNonZeroWidthBitfield = false; ElementInfo Info = getAdjustedElementInfo(FD); + Alignment = std::max(Alignment, Info.Alignment); if (IsUnion) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); @@ -2507,11 +2505,13 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { if (IsUnion) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); + // 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(Info.Alignment); placeFieldAtOffset(FieldOffset); Size = FieldOffset + Info.Size; + Alignment = std::max(Alignment, Info.Alignment); RemainingBitsInField = Context.toBits(Info.Size) - Width; } } @@ -2531,11 +2531,13 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { if (IsUnion) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); + // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Round up the current record size to the field's alignment boundary. CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); placeFieldAtOffset(FieldOffset); Size = FieldOffset; + Alignment = std::max(Alignment, Info.Alignment); } } diff --git a/test/Sema/ms_bitfield_layout.c b/test/Sema/ms_bitfield_layout.c index f2010c1622..8444f469d5 100644 --- a/test/Sema/ms_bitfield_layout.c +++ b/test/Sema/ms_bitfield_layout.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts %s 2>/dev/null \ +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fms-extensions -fdump-record-layouts %s 2>/dev/null \ // RUN: | FileCheck %s -// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts %s 2>/dev/null \ +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple x86_64-pc-win32 -fms-extensions -fdump-record-layouts %s 2>/dev/null \ // RUN: | FileCheck %s typedef struct A { @@ -111,6 +111,16 @@ typedef struct H { // CHECK: Alignment:16 // CHECK: FieldOffsets: [0, 16, 16, 16]> +typedef struct I { + short : 8; + __declspec(align(16)) short : 8; +} I; + +// CHECK: Type: struct I +// CHECK: Size:16 +// CHECK: Alignment:16 +// CHECK: FieldOffsets: [0, 8] + #pragma pack(push, 1) typedef struct A1 { @@ -221,6 +231,16 @@ typedef struct H1 { // CHECK: Alignment:8 // CHECK: FieldOffsets: [0, 32, 32, 32]> +typedef struct I1 { + short : 8; + __declspec(align(16)) short : 8; +} I1; + +// CHECK: Type: struct I1 +// CHECK: Size:16 +// CHECK: Alignment:8 +// CHECK: FieldOffsets: [0, 8] + #pragma pack(pop) int x[ @@ -232,6 +252,7 @@ sizeof(E ) + sizeof(F ) + sizeof(G ) + sizeof(H ) + +sizeof(I ) + sizeof(A1) + sizeof(B1) + sizeof(C1) + @@ -240,4 +261,5 @@ sizeof(E1) + sizeof(F1) + sizeof(G1) + sizeof(H1) + +sizeof(I1) + 0];