c++11's alignas() ignored inside #pragma pack

This test shows that alignas() is ignored when used with #pragma.
Is this intentional behavior?

#pragma pack(push, 1)
struct S1 { char a; short b; double c; alignas(32) double d; char e; double f; };
#pragma pack(pop)

int main()
{
return sizeof(struct S1);
}

  • Thanks, Fariborz

Implementation says that it is intentional:

// The maximum field alignment overrides the aligned attribute.
if (!MaxFieldAlignment.isZero()) {
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
}

  • Fariborz

Implementation says that it is intentional:

  // The maximum field alignment overrides the aligned attribute.
  if (!MaxFieldAlignment.isZero()) {
    FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
    UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
  }
- Fariborz

I too find this very surprising. Does this match GCC / MSVC behavior for
#pragma pack? I don't think it matches __attribute__((packed)).

I don’t have access to GCC. But MSVC’s behavior takes into account current pack setting and enforces alignas() of the field.

  • Fariborz

I just tried this and both gcc and clang return 28.

Presumably they handle alignas the same way they handle
__declspec(align(N)), which overrides packing. MSVC appears to have two
notions of alignment, required and advisory, while the C++ standard, Clang,
and GCC only have one. One way to observe this is to see that they will
align an int64 to 8 bytes in a struct, but they will not realign the stack
to 8 bytes when that struct is stack allocated.

Also, Clang does respect alignas in this case when targeting the Microsoft
C++ ABI.

I tried the test case with these options for MS ABI:

clang -cc1 -triple x86_64-windows-msvc -std=c++11 -S t.cpp

Assembly indicates that it does not seem to respect alignas. Should I be using other options?

main:
movl $28, %eax
movl $0, -4(%rsp)
retq

  • Fariborz

I tried the test case with these options for MS ABI:

clang -cc1 -triple x86_64-windows-msvc -std=c++11 -S t.cpp

Assembly indicates that it does not seem to respect alignas. Should I be using other options?

main:
movl $28, %eax
movl $0, -4(%rsp)
retq

Oops. I was using an old clang. Sorry for the noise.

main:
movl $64, %eax
retq

Would it be possible to have clang support the alignas inside a pragma pack directive, if the structure in question is also inside a pragma ms_struct directive? There are some teams at Microsoft using clang to target non-Windows platforms but sharing code that expects MSVC structure layout. Using the Microsoft C++ ABI isn’t feasible as the platform in question is not a Microsoft Windows platform.

Thanks,
Schwieb
Microsoft Mac Team

Would it be possible to have clang support the alignas inside a pragma
pack directive, if the structure in question is also inside a
pragma ms_struct directive? There are some teams at Microsoft using clang
to target non-Windows platforms but sharing code that expects MSVC
structure layout. Using the Microsoft C++ ABI isn’t feasible as the
platform in question is not a Microsoft Windows platform.

Our documentation says:

"clang supports the Microsoft #pragma pack feature for controlling record
layout. GCC also contains support for this feature, however where MSVC and
GCC are incompatible clang follows the MSVC definition."

... so I think we should do the obviously sane thing here in all cases
(that is, alignas on a field should beat #pragma pack).

Thanks,

Sounds good to me. What’s the best way to track this? Should I file a bug somewhere? (Usually I work directly with Fariborz and Argyrios and other Apple folks in Radar, but this isn’t for an Apple-specific issue so it should go towards the open clang community instead…)

Thanks,

Schwieb

A fix is out for review here: http://reviews.llvm.org/D4649