This is an archive of the discontinued LLVM Phabricator instance.

PR24595: clang-cl fails to compile vswriter.h header from Windows SDK 8.1 in 32 bit mode
ClosedPublic

Authored by andreybokhanko on Aug 27 2015, 3:04 AM.

Details

Summary

As described in PR24595, clang-cl fails to compile vswriter.h header from Windows SDK 8.1 in 32 bit mode. This patch fixes this.

More on vswriter.h is here: https://msdn.microsoft.com/en-us/library/aa384627(v=vs.85).aspx

I'm not sure adding a new warning is the right approach -- maybe we should downgrade "err_conflicting_overriding_cc_attributes" to a Warning with DefaultError attribute?

Diff Detail

Repository
rL LLVM

Event Timeline

andreybokhanko retitled this revision from to PR24595: clang-cl fails to compile vswriter.h header from Windows SDK 8.1 in 32 bit mode.
andreybokhanko updated this object.
andreybokhanko added a reviewer: rnk.
andreybokhanko added a subscriber: cfe-commits.
rnk edited edge metadata.Aug 27 2015, 9:38 AM

MSVC appears to ignore __stdcall on virtual destructors, and I think the correct fix is for us to do the same.

See this test case:

$ cat t.cpp
struct A { virtual __stdcall ~A(); };
A::~A() {}
$ cl -c t.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t.cpp
$ dumpbin /symbols t.obj | grep ~A
00B 00000000 SECT3  notype ()    External     | ??1A@@UAE@XZ (public: virtual __thiscall A::~A(void))

Notice the "__thiscall" part of the symbol name. The assembly also shows that it pulls 'this' from ecx.

andreybokhanko edited edge metadata.

Reid, thanks for looking into this!

As I discovered, MS compiler transforms stdcall to thiscall for all structors (not only virtual ones) in 32 bit mode. In 64 bit mode, it transforms stdcall to cdecl for everything.

Clang already does the same in 64 bit mode; my updated patch makes us transform stdcall to thiscall for structors in 32 bit mode in MSVC environment.

Please re-review.

Yours,
Andrey

rnk added inline comments.Sep 1 2015, 9:01 AM
lib/Sema/SemaType.cpp
2272 ↗(On Diff #33678)

s/is_ctor_or_dtor/IsCtorOrDtor/, it's the local variable convention.

5857–5858 ↗(On Diff #33678)

I think a more accurate statement would be that MSVC ignores explicit calling convention attributes on structors in all modes. Compile this example with MSVC for x64:

struct HVA {
  double a, b, c, d;
};
struct A {
  __vectorcall A(HVA x);
  double f;
};
A::A(HVA x) : f(x.a + x.b + x.c + x.d) {}

Note the warning:

warning C4166: illegal calling convention for constructor/destructor

And HVA is passed indirectly instead of in XMM0-3.

You should consider adding a warning like this when we adjust structor conventions from something other than __stdcall. MSVC doesn't appear to warn on __stdcall structors, probably because it is used accidentally in places like vswriter.h.

5860 ↗(On Diff #33678)

A better test for if we should treat structors specially would be:

Context.getTargetInfo().getCXXABI().isMicrosoft()

It's really the MSVC C++ ABI that requires that structors have special conventions. I think it has to do with exception handling.

5868 ↗(On Diff #33678)

In hindsight, a better name for this variable would be DefaultCC.

5871–5875 ↗(On Diff #33678)

I think it would be better to wrap both ifs here in if (!IsCtorOrDtor). We should always adjust ctors and dtors.

Patch updated after fixing all (but one) of Reid's comments.

andreybokhanko marked 4 inline comments as done.Sep 3 2015, 8:17 AM
andreybokhanko added inline comments.
lib/Sema/SemaType.cpp
5873–5877 ↗(On Diff #33945)

I tried, but this leads to massive stability fails. I'm willing to investigate and fix them (if needed), but in a separate patch, OK?

rnk added inline comments.Sep 3 2015, 8:38 AM
lib/Sema/SemaType.cpp
5855–5856 ↗(On Diff #33945)

DefaultCC is only meaningful when we're dealing with non-structor member functions. In the structor case, you're conflating it with ToCC. Let's sink the DefaultCC definition down into the 'else' block, since it's only meaningful there.

5857 ↗(On Diff #33945)

ToCC is always the same in both cases:

CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);

Let's just keep that here, and return early if CurrCC == ToCC, since the common case is that we don't need to do anything.

5864–5865 ↗(On Diff #33945)

This is reimplementing ASTContext::getDefaultCallingConv. Let's not duplicate that logic.

5867–5868 ↗(On Diff #33945)

This can be covered by returning earlier if CurrCC == ToCC.

5870–5872 ↗(On Diff #33945)

This seems wrong, see this test case:

struct A {
  __cdecl A(int x);
  int f;
};
A::A(int x) : f(x) {}

32-bit MSVC turns it into thiscall.

I think what you're really seeing is that variadic constructors need to stay cdecl. getDefaultCallingConvention already handles this case.

5873–5877 ↗(On Diff #33945)

I'd really rather get the *structor calling convention logic right on the first try.

Reid,

Sorry for delayed reply. All your comments are fixed (it turned out that usage of DefaultCC instead of ToCC is the root of all evil; after I fixed this, all other problems went away).

Patch updated; please re-review.

Andrey

andreybokhanko marked 8 inline comments as done.Sep 10 2015, 12:32 PM
rnk accepted this revision.Sep 10 2015, 3:30 PM
rnk edited edge metadata.

lgtm, thanks!

test/CodeGenCXX/ctor-dtor-alias.cpp
170 ↗(On Diff #34477)

Isn't this still in the test9 namespace? Shouldn't this change be reverted?

test/CodeGenCXX/microsoft-abi-structors.cpp
411 ↗(On Diff #34477)

Hah, looks like we encountered this long ago and didn't go back for it. :)

This revision is now accepted and ready to land.Sep 10 2015, 3:30 PM

Reid, thank you for the review!

One last confirmation (see below), and I'll go ahead.

Yours,
Andrey

test/CodeGenCXX/ctor-dtor-alias.cpp
170 ↗(On Diff #34477)

Now, after making the change you requested (wrapping checks in "default" part of adjustMemberFunctionCC function with !IsCtorOrDtor (SemaType.cpp:5876)) we start to call ~foo() here, so the check should be changed to:

// CHECK4: call void bitcast (void (%"struct.test9::foo"*)* @_ZN5test93fooD2Ev

Please confirm you are OK with this change and I'll go ahead with commit.

rnk added inline comments.Sep 11 2015, 8:16 AM
lib/Sema/SemaType.cpp
5876 ↗(On Diff #34477)

This looks like the !IsCtorOrDtor check that affects Itanium. Isn't it already handled for MS C++ above?

test/CodeGenCXX/ctor-dtor-alias.cpp
170 ↗(On Diff #34477)

That seems like a bug, we don't want this change to affect destructors on Linux or mingw.

andreybokhanko added inline comments.Sep 12 2015, 9:42 AM
lib/Sema/SemaType.cpp
5876 ↗(On Diff #34477)

Reid, now I'm completely confused... I thought you asked me to insert this check for Itanium ABI as well (in your comment from Sep 1st). Am I mistaken? If yes, I can remove it and restore ctor-dtor-alias.cpp test back to original version.

rnk added inline comments.Sep 12 2015, 9:56 AM
lib/Sema/SemaType.cpp
5876 ↗(On Diff #34477)

Sorry, it shouldn't affect Itanium. What you have without this check is fine.

This revision was automatically updated to reflect the committed changes.

OK -- I removed the check in Itanium ABI part, restored back the test and committed the patch.

Thanks for reviewing!