hubert.reinterpretcast created this revision.
hubert.reinterpretcast added reviewers: aaron.ballman, faisalv, rsmith.
hubert.reinterpretcast added a subscriber: cfe-commits.

This change fixes issues with `LLVM_CONSTEXPR` functions and 
`TrailingObjects::FixedSizeStorage`. In particular, some of the functions 
marked `LLVM_CONSTEXPR` used by `FixedSizeStorage` were not implemented such 
that they evaluate successfully as part of a constant expression despite 
constant arguments.

This change also implements a more traditional template-meta path to 
accommodate MSVC.

https://reviews.llvm.org/D22668

Files:
  include/llvm/Support/AlignOf.h
  include/llvm/Support/MathExtras.h
  include/llvm/Support/TrailingObjects.h

Index: include/llvm/Support/TrailingObjects.h
===================================================================
--- include/llvm/Support/TrailingObjects.h
+++ include/llvm/Support/TrailingObjects.h
@@ -146,8 +146,13 @@
   using ParentType::getTrailingObjectsImpl;
   using ParentType::additionalSizeToAllocImpl;
 
+  struct RequiresRealignment {
+    static const bool value =
+        llvm::AlignOf<PrevTy>::Alignment < llvm::AlignOf<NextTy>::Alignment;
+  };
+
   static LLVM_CONSTEXPR bool requiresRealignment() {
-    return llvm::AlignOf<PrevTy>::Alignment < llvm::AlignOf<NextTy>::Alignment;
+    return RequiresRealignment::value;
   }
 
   // These two functions are helper functions for
@@ -197,11 +202,27 @@
       typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) {
     return additionalSizeToAllocImpl(
         (requiresRealignment()
-             ? llvm::alignTo(SizeSoFar, llvm::alignOf<NextTy>())
+             ? llvm::alignTo<llvm::alignOf<NextTy>()>(SizeSoFar)
              : SizeSoFar) +
             sizeof(NextTy) * Count1,
         MoreCounts...);
   }
+
+  // additionalSizeToAllocImpl for contexts where a constant expression is
+  // required.
+  // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr
+  template <size_t SizeSoFar, size_t Count1, size_t... MoreCounts>
+  struct AdditionalSizeToAllocImpl {
+    static_assert(sizeof...(MoreTys) == sizeof...(MoreCounts),
+                  "Number of counts do not match number of types");
+    static const size_t value = ParentType::template AdditionalSizeToAllocImpl<
+        (RequiresRealignment::value
+             ? llvm::AlignTo<llvm::AlignOf<NextTy>::Alignment>::
+                   template from_value<SizeSoFar>::value
+             : SizeSoFar) +
+            sizeof(NextTy) * Count1,
+        MoreCounts...>::value;
+  };
 };
 
 // The base case of the TrailingObjectsImpl inheritance recursion,
@@ -218,6 +239,13 @@
     return SizeSoFar;
   }
 
+  // additionalSizeToAllocImpl for contexts where a constant expression is
+  // required.
+  // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr
+  template <size_t SizeSoFar> struct AdditionalSizeToAllocImpl {
+    static const size_t value = SizeSoFar;
+  };
+
   template <bool CheckAlignment> static void verifyTrailingObjectsAlignment() {}
 };
 
@@ -343,6 +371,21 @@
     return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
   }
 
+  // totalSizeToAlloc for contexts where a constant expression is required.
+  // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr
+  template <typename... Tys> struct TotalSizeToAlloc {
+    static_assert(
+        std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value,
+        "Arguments to TotalSizeToAlloc do not match with TrailingObjects");
+    template <size_t... Counts> struct with_counts {
+      static_assert(sizeof...(TrailingTys) == sizeof...(Counts),
+                    "Number of counts do not match number of types");
+      static const size_t value =
+          sizeof(BaseTy) +
+          ParentType::template AdditionalSizeToAllocImpl<0, Counts...>::value;
+    };
+  };
+
   /// A type where its ::with_counts template member has a ::type member
   /// suitable for use as uninitialized storage for an object with the given
   /// trailing object counts. The template arguments are similar to those
@@ -360,7 +403,9 @@
   /// \endcode
   template <typename... Tys> struct FixedSizeStorage {
     template <size_t... Counts> struct with_counts {
-      enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
+      enum {
+        Size = TotalSizeToAlloc<Tys...>::template with_counts<Counts...>::value
+      };
       typedef llvm::AlignedCharArray<
           llvm::AlignOf<BaseTy>::Alignment, Size
           > type;
Index: include/llvm/Support/MathExtras.h
===================================================================
--- include/llvm/Support/MathExtras.h
+++ include/llvm/Support/MathExtras.h
@@ -671,6 +671,25 @@
   return (Value + Align - 1 - Skew) / Align * Align + Skew;
 }
 
+/// Returns the next integer (mod 2**64) that is greater than or equal to
+/// \p Value and is a multiple of \c Align. \c Align must be non-zero.
+template <uint64_t Align>
+LLVM_CONSTEXPR inline uint64_t alignTo(uint64_t Value) {
+  static_assert(Align != 0u, "Align must be non-zero");
+  return (Value + Align - 1) / Align * Align;
+}
+
+// alignTo for contexts where a constant expression is required.
+// FIXME: remove when LLVM_CONSTEXPR becomes really constexpr
+template <uint64_t Align>
+struct AlignTo {
+  static_assert(Align != 0u, "Align must be non-zero");
+  template <uint64_t Value>
+  struct from_value {
+    static const uint64_t value = (Value + Align - 1) / Align * Align;
+  };
+};
+
 /// Returns the largest uint64_t less than or equal to \p Value and is
 /// \p Skew mod \p Align. \p Align must be non-zero
 inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
Index: include/llvm/Support/AlignOf.h
===================================================================
--- include/llvm/Support/AlignOf.h
+++ include/llvm/Support/AlignOf.h
@@ -103,7 +103,7 @@
 ///  class besides some cosmetic cleanliness.  Example usage:
 ///  alignOf<int>() returns the alignment of an int.
 template <typename T>
-inline unsigned alignOf() { return AlignOf<T>::Alignment; }
+LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf<T>::Alignment; }
 
 /// \struct AlignedCharArray
 /// \brief Helper for building an aligned character array type.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to