[llvm] r359135 - Try once more to ensure constant initializaton of ManagedStatics

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 24 13:13:24 PDT 2019


Author: rnk
Date: Wed Apr 24 13:13:23 2019
New Revision: 359135

URL: http://llvm.org/viewvc/llvm-project?rev=359135&view=rev
Log:
Try once more to ensure constant initializaton of ManagedStatics

First, use the old style of linker initialization for MSVC 2019 in
addition to 2017. MSVC 2019 emits a dynamic initializer for
ManagedStatic when compiled in debug mode, and according to zturner,
also sometimes in release mode. I wasn't able to reproduce that, but it
seems best to stick with the old code that works.

When clang is using the MSVC STL, we have to give ManagedStatic a
constexpr constructor that fully zero initializes all fields, otherwise
it emits a dynamic initializer. The MSVC STL implementation of
std::atomic has a non-trivial (but constexpr) default constructor that
zero initializes the atomic value. Because one of the fields has a
non-trivial constructor, ManagedStatic ends up with a non-trivial ctor.
The ctor is not constexpr, so clang ends up emitting a dynamic
initializer, even though it simply does zero initialization. To make it
constexpr, we must initialize all fields of the ManagedStatic.

However, while the constructor that takes a pointer is marked constexpr,
clang says it does not evaluate to a constant because it contains a cast
from a pointer to an integer. I filed this as:
https://developercommunity.visualstudio.com/content/problem/545566/stdatomic-value-constructor-is-not-actually-conste.html

Once we do that, we can add back the
LLVM_REQUIRE_CONSTANT_INITIALIZATION marker, and so far as I'm aware it
compiles successfully on all supported targets.

Modified:
    llvm/trunk/include/llvm/Support/ManagedStatic.h
    llvm/trunk/lib/Support/CommandLine.cpp

Modified: llvm/trunk/include/llvm/Support/ManagedStatic.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ManagedStatic.h?rev=359135&r1=359134&r2=359135&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ManagedStatic.h (original)
+++ llvm/trunk/include/llvm/Support/ManagedStatic.h Wed Apr 24 13:13:23 2019
@@ -32,20 +32,24 @@ template <typename T, size_t N> struct o
   static void call(void *Ptr) { delete[](T *)Ptr; }
 };
 
-// If the current compiler is MSVC 2017 or earlier, then we have to work around
-// a bug where MSVC emits code to perform dynamic initialization even if the
-// class has a constexpr constructor. Instead, fall back to the C++98 strategy
-// where there are no constructors or member initializers. We can remove this
-// when MSVC 2019 (19.20+) is our minimum supported version.
-#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1920
-#define LLVM_AVOID_CONSTEXPR_CTOR
+// ManagedStatic must be initialized to zero, and it must *not* have a dynamic
+// initializer because managed statics are often created while running other
+// dynamic initializers. In standard C++11, the best way to accomplish this is
+// with a constexpr default constructor. However, different versions of the
+// Visual C++ compiler have had bugs where, even though the constructor may be
+// constexpr, a dynamic initializer may be emitted depending on optimization
+// settings. For the affected versions of MSVC, use the old linker
+// initialization pattern of not providing a constructor and leaving the fields
+// uninitialized.
+#if !defined(_MSC_VER) || defined(__clang__)
+#define LLVM_USE_CONSTEXPR_CTOR
 #endif
 
 /// ManagedStaticBase - Common base class for ManagedStatic instances.
 class ManagedStaticBase {
 protected:
-#ifndef LLVM_AVOID_CONSTEXPR_CTOR
-  mutable std::atomic<void *> Ptr{nullptr};
+#ifdef LLVM_USE_CONSTEXPR_CTOR
+  mutable std::atomic<void *> Ptr{};
   mutable void (*DeleterFn)(void *) = nullptr;
   mutable const ManagedStaticBase *Next = nullptr;
 #else
@@ -59,7 +63,7 @@ protected:
   void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
 
 public:
-#ifndef LLVM_AVOID_CONSTEXPR_CTOR
+#ifdef LLVM_USE_CONSTEXPR_CTOR
   constexpr ManagedStaticBase() = default;
 #endif
 

Modified: llvm/trunk/lib/Support/CommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CommandLine.cpp?rev=359135&r1=359134&r2=359135&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CommandLine.cpp (original)
+++ llvm/trunk/lib/Support/CommandLine.cpp Wed Apr 24 13:13:23 2019
@@ -412,6 +412,7 @@ void OptionCategory::registerCategory()
 // that this ManagedStatic uses constant initailization and not dynamic
 // initialization because it is referenced from cl::opt constructors, which run
 // dynamically in an arbitrary order.
+LLVM_REQUIRE_CONSTANT_INITIALIZATION
 ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
 
 // A special subcommand that can be used to put an option into all subcommands.




More information about the llvm-commits mailing list