This is an archive of the discontinued LLVM Phabricator instance.

[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)
ClosedPublic

Authored by d.zobnin.bugzilla on Apr 21 2016, 5:43 AM.

Details

Summary

This patch attempts to improve implementation of several MS pragmas that use stack (vtordisp, { bss | code | const | data }_seg) and fix some compatibility issues.
Please take a look at the patch and let me know whether it's something worth working on and whether I'm on the right way of doing this.

This patch:

  1. Changes implementation of #pragma vtordisp to use existing PragmaStack<> template class that *_seg pragmas use;
  2. Fixes "#pragma vtordisp()" reset behavior -- it shouldn't affect the stack;
  3. Supports "save-and-restore" of pragma state stacks on entering / exiting a C++ method body, as MSVC does.

If this work is accepted, I propose several to-do's:

  1. Change #pragma pack implementation to use the same approach as other "stack" pragmas use;
  2. Introduce diagnostics on popping named stack slots, as MSVC does

Currently I tried to make Clang behave exactly as MSVC behaves, though, I can think of possible better solutions, please see "Implementation notes" below.

Motivation:

Currently Clang implements "stack" pragmas in several ways: "vtordisp" and "pack" have their own stacks in Sema, pragma actions are performed differently.

MSVC seems to have a common implementation of all these pragmas. One common feature is "save-restore" on entering / exiting a C++ method body:

#pragma pack(4)
#pragma pack(show)

struct S {
  void f() {
    #pragma pack(push, 8)
    #pragma pack(show)
  }
};

#pragma pack(show)

MSVC's output: 4, 8, 4
Clang's output: 4, 8, 8

MSVC seems to introduce artificial sentinel slots on entering a C++ method body and pops them on exit. Consider

#pragma pack(push, 4)
struct S {
  void f() {
    #pragma pack(pop)
  }
};

MSVC emits:

warning C4159: #pragma pack(pop,...): has popped previously pushed identifier '<InternalPragmaState>'
warning C4160: #pragma pack(pop,...): did not find previously pushed identifier '<InternalPragmaState>'

The same approach is used for "vtordisp" pragma, although it doesn't support #pragma vtordisp (pop, id) syntax.
Please note that in the above example the stack gets corrupted and might lead to unexpected behavior later.

I implemented "save-and-restore" feature for #pragma vtordisp in http://reviews.llvm.org/D14467 by copying a skack to a RAII object and back, no matter how many times "pop" is used. Pragmas other than "vtordisp" in Clang don't support this feature yet.

Implementation notes:

MSVC seems to use the same name "<InternalPragmaState>" even for methods of nested classes. It is legal in correct cases, because "#pragma <name>(pop, id)" will look for the closest slot with mathing name, but if the nested sentinel slot is mistakenly popped, it will cause popping the stack up to surrounding sentinel.
Maybe, if we choose this approach, we could use unique sentinel names for better recovery? Or even mark the sentinels to prevent a programmer from popping them by accident?

Best regards,
Denis Zobnin

Diff Detail

Repository
rL LLVM

Event Timeline

d.zobnin.bugzilla retitled this revision from to [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg).
d.zobnin.bugzilla updated this object.
d.zobnin.bugzilla added a reviewer: rnk.
d.zobnin.bugzilla added a subscriber: cfe-commits.
rnk accepted this revision.Apr 27 2016, 1:06 PM
rnk edited edge metadata.

lgtm, thanks this is a nice cleanup!

include/clang/Sema/Sema.h
338–342 ↗(On Diff #54484)

These are now used for more than just section names. Can you replace "name" with value in all the comments?

385–386 ↗(On Diff #54484)

I don't see any users of this overload, where is it needed?

This revision is now accepted and ready to land.Apr 27 2016, 1:06 PM
thakis added a subscriber: thakis.Apr 27 2016, 1:33 PM

Thanks for the patch! To add to your proposed todo list (which sounds great): All these stack-using pragmas aren't serialized to pch files at the moment either. Maybe you want to work on that too (either serialize the stacks, or emit a warning if the stacks aren't completely popped at the end of the pch header).

This revision was automatically updated to reflect the committed changes.

Reid, thanks for review! I've changed the patch according to your comments and also moved implementation of RAII object to SemaAttr.cpp file (implementation in header broke many buildbots).

Nico, I will look at serialization and try to implement the desired behavior, thank you!