#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)
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
// 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(AlignmentCalcImpl<T>) - sizeof(T));
+ static constexpr unsigned Alignment = static_cast<unsigned int>(
+ sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T));
#else
- enum { Alignment =
- static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) };
+ 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 };
V7::~V7() {}
V8::~V8() {}
+struct Abstract1 {
+ virtual ~Abstract1() {}
+ virtual void method() = 0;
+
+ char c;
+};
+
+struct Abstract2 : Abstract1 {
+ virtual ~Abstract2() {}
+ double d;
+};
+
+struct Final final : Abstract2 {
+ void method() override {}
+};
+
// Ensure alignment is a compile-time constant.
char LLVM_ATTRIBUTE_UNUSED test_arr1
[AlignOf<char>::Alignment > 0]
EXPECT_LE(alignOf<V1>(), alignOf<V6>());
EXPECT_LE(alignOf<V1>(), alignOf<V7>());
EXPECT_LE(alignOf<V1>(), alignOf<V8>());
+
+ EXPECT_LE(alignOf<char>(), alignOf<Abstract1>());
+ EXPECT_LE(alignOf<double>(), alignOf<Abstract2>());
+ EXPECT_LE(alignOf<Abstract2>(), alignOf<Final>());
}
TEST(AlignOfTest, BasicAlignedArray) {