[CodeView] Improve the line table dumper
[oota-llvm.git] / include / llvm / Support / AlignOf.h
index f564fd353d8c7ded57db5fbd03cd8411d1f4fc87..5268c8d16986801b4f5f3fcf707369d28cf134b0 100644 (file)
 
 #include "llvm/Support/Compiler.h"
 #include <cstddef>
+#include <type_traits>
 
 namespace llvm {
-template <typename T>
+
+namespace detail {
+
+// For everything other than an abstract class we can calulate alignment by
+// building a class with a single character and a member of the given type.
+template <typename T, bool = std::is_abstract<T>::value>
 struct AlignmentCalcImpl {
   char x;
 #if defined(_MSC_VER)
 // Disables "structure was padded due to __declspec(align())" warnings that are
 // generated by any class using AlignOf<T> with a manually specified alignment.
-// Although the warning is disabled in the LLVM project we need this pragma 
+// Although the warning is disabled in the LLVM project we need this pragma
 // as AlignOf.h is a published support header that's available for use
-// out-of-tree, and we would like that to ompile cleanly at /W4.
+// out-of-tree, and we would like that to compile cleanly at /W4.
 #pragma warning(suppress : 4324)
 #endif
   T t;
@@ -35,6 +41,25 @@ private:
   AlignmentCalcImpl() {} // Never instantiate.
 };
 
+// Abstract base class helper, this will have the minimal alignment and size
+// for any abstract class. We don't even define its destructor because this
+// type should never be used in a way that requires it.
+struct AlignmentCalcImplBase {
+  virtual ~AlignmentCalcImplBase() = 0;
+};
+
+// When we have an abstract class type, specialize the alignment computation
+// engine to create another abstract class that derives from both an empty
+// abstract base class and the provided type. This has the same effect as the
+// above except that it handles the fact that we can't actually create a member
+// of type T.
+template <typename T>
+struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T {
+  virtual ~AlignmentCalcImpl() = 0;
+};
+
+} // End detail namespace.
+
 /// AlignOf - A templated class that contains an enum value representing
 ///  the alignment of the template argument.  For example,
 ///  AlignOf<int>::Alignment represents the alignment of type "int".  The
@@ -44,9 +69,20 @@ private:
 ///  compile-time constant (e.g., for template instantiation).
 template <typename T>
 struct AlignOf {
-  enum { Alignment =
-         static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) };
-
+#ifndef _MSC_VER
+  // Avoid warnings from GCC like:
+  //   comparison between 'enum llvm::AlignOf<X>::<anonymous>' and 'enum
+  //   llvm::AlignOf<Y>::<anonymous>' [-Wenum-compare]
+  // by using constexpr instead of enum.
+  // (except on MSVC, since it doesn't support constexpr yet).
+  static constexpr unsigned Alignment = static_cast<unsigned int>(
+      sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T));
+#else
+  enum {
+    Alignment = static_cast<unsigned int>(sizeof(detail::AlignmentCalcImpl<T>) -
+                                          sizeof(T))
+  };
+#endif
   enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
   enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
   enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
@@ -58,6 +94,10 @@ struct AlignOf {
   enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
 };
 
+#ifndef _MSC_VER
+template <typename T> constexpr unsigned AlignOf<T>::Alignment;
+#endif
+
 /// alignOf - A templated function that returns the minimum alignment of
 ///  of a type.  This provides no extra functionality beyond the AlignOf
 ///  class besides some cosmetic cleanliness.  Example usage:
@@ -198,12 +238,12 @@ union SizerImpl {
 } // end namespace detail
 
 /// \brief This union template exposes a suitably aligned and sized character
-/// array member which can hold elements of any of up to four types.
+/// array member which can hold elements of any of up to ten types.
 ///
 /// These types may be arrays, structs, or any other types. The goal is to
 /// expose a char array buffer member which can be used as suitable storage for
-/// a placement new of any of these types. Support for more than seven types can
-/// be added at the cost of more boiler plate.
+/// a placement new of any of these types. Support for more than ten types can
+/// be added at the cost of more boilerplate.
 template <typename T1,
           typename T2 = char, typename T3 = char, typename T4 = char,
           typename T5 = char, typename T6 = char, typename T7 = char,