[ADT] Try to work around a crash in MSVC.
authorChandler Carruth <chandlerc@gmail.com>
Tue, 3 Jul 2018 05:46:20 +0000 (05:46 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 3 Jul 2018 05:46:20 +0000 (05:46 +0000)
Putting `sizeof(T) <= 16` into the parameter of a `std::conditional`
causes every version of MSVC I've tried to crash:

  https://godbolt.org/g/eqVULL

Really frustrating, but an extra layer of indirection through an
instantiated type gives a working way to access this computed constant.

llvm-svn: 336170

llvm/include/llvm/ADT/FunctionExtras.h

index 2cce7b3..95b3054 100644 (file)
@@ -46,6 +46,13 @@ template <typename ReturnT, typename... ParamTs>
 class unique_function<ReturnT(ParamTs...)> {
   static constexpr int InlineStorageSize = sizeof(void *) * 3;
 
+  // MSVC has a bug and ICEs if we give it a particular dependent value
+  // expression as part of the `std::conditional` below. To work around this,
+  // we build that into a template struct's constexpr bool.
+  template <typename T> struct IsSizeLessThanThresholdT {
+    static constexpr bool value = sizeof(T) <= (2 * sizeof(void *));
+  };
+
   // Provide a type function to map parameters that won't observe extra copies
   // or moves and which are small enough to likely pass in register to values
   // and all other types to l-value reference types. We use this to compute the
@@ -60,7 +67,7 @@ class unique_function<ReturnT(ParamTs...)> {
       !std::is_reference<T>::value &&
           llvm::is_trivially_copy_constructible<T>::value &&
           llvm::is_trivially_move_constructible<T>::value &&
-          sizeof(T) <= (2 * sizeof(void *)),
+          IsSizeLessThanThresholdT<T>::value,
       T, T &>::type;
 
   // The type of the erased function pointer we use as a callback to dispatch to