This is an archive of the discontinued LLVM Phabricator instance.

PR37275 packed attribute should not apply to base classes
ClosedPublic

Authored by rsmith on Apr 27 2018, 3:55 PM.

Details

Summary

Clang incorrectly applies the packed attribute to base classes. Per GCC's documentation and as can be observed from its behavior, packed only applies to members, not base classes.

This change is conditioned behind -fclang-abi-compat so that an ABI break can be avoided by users if desired.

Diff Detail

Repository
rL LLVM

Event Timeline

rsmith created this revision.Apr 27 2018, 3:55 PM
rsmith updated this revision to Diff 144415.Apr 27 2018, 3:58 PM

Added release notes.

rjmccall accepted this revision.Apr 27 2018, 10:44 PM

I wonder if that was originally just an oversight that got turned into official policy. Anyway, if it's the policy, it's what we have to do; LGTM.

Have you checked whether we do the right thing with #pragma pack on MSVC?

This revision is now accepted and ready to land.Apr 27 2018, 10:44 PM

Have you checked whether we do the right thing with #pragma pack on MSVC?

Great question, I hadn't. Both MSVC and GCC treat #pragma pack as applying to base classes, which is what we do with/without this patch. I'll add some tests to cover that.

This revision was automatically updated to reflect the committed changes.

I wonder if that was originally just an oversight that got turned into official policy. Anyway, if it's the policy, it's what we have to do; LGTM.

I think it's actually correct behavior. Why would an attribute on a derived class be allowed to alter the layout of a base class? It would mean you can't convert Derived* to Base* safely.

I wonder if that was originally just an oversight that got turned into official policy. Anyway, if it's the policy, it's what we have to do; LGTM.

I think it's actually correct behavior. Why would an attribute on a derived class be allowed to alter the layout of a base class? It would mean you can't convert Derived* to Base* safely.

With Clang's old behavior, base classes were treated exactly like fields -- their layout was not changed per se, but their minimum alignment was reduced. Yes, that means you can't convert Derived* to Base* safely, but the packed attribute means you can't use &object.member to convert Class* to Member* safely either, so that's not an entirely unique problem. Probably more serious is that GCC doesn't permit a T& to bind to a packed field, so treating base classes as packed would interfere with passing a Derived lvalue to a Base&, which does seem like a much more severe restriction for base classes than for fields.