New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LLVM's ManagedStatic.h fails with VS 2019 <atomic> and clang-cl due to init-order-fiasco and constexpr confusion #40712
Comments
assigned to @rnk |
After discussing this further here, we think this is definitely an LLVM bug, not a clang bug or a VC STL bug. |
VSO#406237 is "C1XX does not do constant initialization where the standard requires". Basically, the compiler doesn't do constant initialization unless you are declaring an instance of a thing which is itself actually constexpr. This let us implement P0883 for clang but not for c1xx yet. Billy O'Neal |
Reid - after rL357655 I'm seeing a very similar llvm-tblgen error on VS2017 - I've only been able to repro on msbuild debug builds so far. |
Reverted in rL357685 |
So, if I understand correctly, my fix, rL357655, ran into exactly the issue that Billy is describing with the Visual C++ compiler from VS 2017. =/ I have yet to find a proper solution. |
I relanded a fix back in April in r359135. |
There was a bug of constexpr ctor in VS2019 compiler until ver 16.5, that really caused the problem. |
Reopened to deal with the 16.5+ case |
The fix for MSVC v16.5+ loaded. |
This affects building the 10.0 release build with VS 16.6: https://llvm.discourse.group/t/llvm-not-building-in-vusual-studio/1139 I'd like to propose we merge https://reviews.llvm.org/D80433 / rG46e5c5fe778b into the branch. |
Simon, I'm reletively a newcomer. Could you please explain how to do that? |
We just need to get a consensus on this ticket that rG46e5c5fe778b should be merged into the 10.X release branch and Tom will handle the actual merge (by blocking [Bug #45309] he has visibility on merge candidates). Reid - any comments? |
*** Bug llvm/llvm-bugzilla-archive#46108 has been marked as a duplicate of this bug. *** |
Reid, is this OK to backport? |
This looks safe to me, so I'm going to merge this. |
Merged: 28a6713 |
*** Bug llvm/llvm-bugzilla-archive#49027 has been marked as a duplicate of this bug. *** |
mentioned in issue #44654 |
mentioned in issue llvm/llvm-bugzilla-archive#46108 |
mentioned in issue llvm/llvm-bugzilla-archive#49027 |
Extended Description
I installed VS 2019 and tried to self-host clang with the new headers, but it didn't work. The symptom was this:
[1 processes, 17/531 @ 3.4/s : 4.984s ] Building AttributesCompatFunc.inc...
FAILED: lib/IR/AttributesCompatFunc.inc
cmd.exe /C "cd /D C:\src\llvm-project\build && C:\src\llvm-project\build\bin\llvm-tblgen.exe -gen-attrs -I C:/src/llvm-project/llvm/lib/IR -I C:/src/llvm-project/llvm/include C:/src/llvm-project/llvm/lib/IR/AttributesCompatFunc.td -o lib/IR/AttributesCompatFunc.inc -d lib/IR/AttributesCompatFunc.inc.d"
llvm-tblgen.exe: Unknown command line argument '-gen-attrs'. Try: 'C:\src\llvm-project\build\bin\llvm-tblgen.exe -help'
llvm-tblgen.exe: Did you mean '-stats'?
ninja: build stopped: subcommand failed.
The issue here is that command line options aren't being registered. This is because TopLevelSubCommand is a ManagedStatic. What happens is that the cl::opt initializers run first, then ManagedStatic is incorrectly not linker initialized, we run the ManagedStatic ctor, and we zero out the pointer to the previously constructed list of command line flags.
The issue is that ManagedStaticBase wants to be linker initialized, but the way it achieves that is by not having a constructor at all. It has members that look like this:
class ManagedStaticBase {
protected:
// This should only be used as a static variable, which guarantees that this
// will be zero initialized.
mutable std::atomic<void *> Ptr;
mutable void (DeleterFn)(void);
mutable const ManagedStaticBase *Next;
With clang-cl, for some reason the default constructor for this class isn't considered to be constexpr. When I try to explicitly make it constexpr, clang complains:
C:\src\llvm-project\llvm\include\llvm/Support/ManagedStatic.h(47,3): error: defaulted definition of default constructor is not constexpr
constexpr ManagedStaticBase() = default;
^
1 error generated.
So, clang thinks the defaulted one won't be constexpr, but it doesn't say why. Even if it's correct, it should probably point the user at the uninitialized members. If I initialize the members explicitly like this:
mutable std::atomic<void *> Ptr{nullptr};
mutable void (DeleterFn)(void) = nullptr;
mutable const ManagedStaticBase *Next = nullptr;
Then the defaulted default ctor becomes constexpr and everything works as expected.
The atomic headers have some interesting ifdefs that seem to allude to this issue:
struct _Atomic_base : _Atomic_impl<_Bytes> {
...
#ifdef clang // TRANSITION, VSO#406237
constexpr _Atomic_base() _NOEXCEPT_COND(is_nothrow_default_constructible_v<_Ty>) : _My_val() {}
#else // ^^^ no workaround ^^^ // vvv workaround vvv
_Atomic_base() = default;
#endif // VSO#406237
The odd thing is that if this constexpr default ctor didn't exist, we might be in business? Hard to say.
Another way of looking at this bug, if it's a clang bug, is, why is the following an error?
struct atomic_ptr {
constexpr atomic_ptr() = default;
void *Ptr = nullptr;
};
struct Foo {
atomic_ptr Ptr;
int y;
constexpr Foo() = default; // why an error?
};
extern Foo obj;
Foo obj;
Just because 'y' has no initializer, Foo can't be constexpr, even if I ask for it to be?
In the end, I think this is a clang bug, but it might be an STL bug, so I added Billy and STL.
Anyway, there's an obvious workaround, which is to add a real constexpr constructor to ManagedStatic, assuming that works with all the toolchains we support. I'm going to try that.
The text was updated successfully, but these errors were encountered: