1//=== - llvm/unittest/Support/TrailingObjectsTest.cpp ---------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/Support/TrailingObjects.h" 11#include "gtest/gtest.h" 12 13using namespace llvm; 14 15namespace { 16// This class, beyond being used by the test case, a nice 17// demonstration of the intended usage of TrailingObjects, with a 18// single trailing array. 19class Class1 final : protected TrailingObjects<Class1, short> { 20 friend TrailingObjects; 21 22 unsigned NumShorts; 23 24protected: 25 size_t numTrailingObjects(OverloadToken<short>) const { return NumShorts; } 26 27 Class1(int *ShortArray, unsigned NumShorts) : NumShorts(NumShorts) { 28 std::uninitialized_copy(ShortArray, ShortArray + NumShorts, 29 getTrailingObjects<short>()); 30 } 31 32public: 33 static Class1 *create(int *ShortArray, unsigned NumShorts) { 34 void *Mem = ::operator new(totalSizeToAlloc<short>(NumShorts)); 35 return new (Mem) Class1(ShortArray, NumShorts); 36 } 37 38 short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; } 39 40 unsigned numShorts() const { return NumShorts; } 41 42 // Pull some protected members in as public, for testability. 43 using TrailingObjects::totalSizeToAlloc; 44 using TrailingObjects::additionalSizeToAlloc; 45 using TrailingObjects::getTrailingObjects; 46}; 47 48// Here, there are two singular optional object types appended. Note 49// that the alignment of Class2 is automatically increased to account 50// for the alignment requirements of the trailing objects. 51class Class2 final : protected TrailingObjects<Class2, double, short> { 52 friend TrailingObjects; 53 54 bool HasShort, HasDouble; 55 56protected: 57 size_t numTrailingObjects(OverloadToken<short>) const { 58 return HasShort ? 1 : 0; 59 } 60 size_t numTrailingObjects(OverloadToken<double>) const { 61 return HasDouble ? 1 : 0; 62 } 63 64 Class2(bool HasShort, bool HasDouble) 65 : HasShort(HasShort), HasDouble(HasDouble) {} 66 67public: 68 static Class2 *create(short S = 0, double D = 0.0) { 69 bool HasShort = S != 0; 70 bool HasDouble = D != 0.0; 71 72 void *Mem = 73 ::operator new(totalSizeToAlloc<double, short>(HasDouble, HasShort)); 74 Class2 *C = new (Mem) Class2(HasShort, HasDouble); 75 if (HasShort) 76 *C->getTrailingObjects<short>() = S; 77 if (HasDouble) 78 *C->getTrailingObjects<double>() = D; 79 return C; 80 } 81 82 short getShort() const { 83 if (!HasShort) 84 return 0; 85 return *getTrailingObjects<short>(); 86 } 87 88 double getDouble() const { 89 if (!HasDouble) 90 return 0.0; 91 return *getTrailingObjects<double>(); 92 } 93 94 // Pull some protected members in as public, for testability. 95 using TrailingObjects::totalSizeToAlloc; 96 using TrailingObjects::additionalSizeToAlloc; 97 using TrailingObjects::getTrailingObjects; 98}; 99 100TEST(TrailingObjects, OneArg) { 101 int arr[] = {1, 2, 3}; 102 Class1 *C = Class1::create(arr, 3); 103 EXPECT_EQ(sizeof(Class1), sizeof(unsigned)); 104 EXPECT_EQ(Class1::additionalSizeToAlloc<short>(1), sizeof(short)); 105 EXPECT_EQ(Class1::additionalSizeToAlloc<short>(3), sizeof(short) * 3); 106 107 EXPECT_EQ(Class1::totalSizeToAlloc<short>(1), sizeof(Class1) + sizeof(short)); 108 EXPECT_EQ(Class1::totalSizeToAlloc<short>(3), 109 sizeof(Class1) + sizeof(short) * 3); 110 111 EXPECT_EQ(C->getTrailingObjects<short>(), reinterpret_cast<short *>(C + 1)); 112 EXPECT_EQ(C->get(0), 1); 113 EXPECT_EQ(C->get(2), 3); 114 delete C; 115} 116 117TEST(TrailingObjects, TwoArg) { 118 Class2 *C1 = Class2::create(4); 119 Class2 *C2 = Class2::create(0, 4.2); 120 121 EXPECT_EQ(sizeof(Class2), llvm::RoundUpToAlignment(sizeof(bool) * 2, 122 llvm::alignOf<double>())); 123 EXPECT_EQ(llvm::alignOf<Class2>(), llvm::alignOf<double>()); 124 125 EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(1, 0)), 126 sizeof(double)); 127 EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(0, 1)), 128 sizeof(short)); 129 EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(3, 1)), 130 sizeof(double) * 3 + sizeof(short)); 131 132 EXPECT_EQ((Class2::totalSizeToAlloc<double, short>(1, 1)), 133 sizeof(Class2) + sizeof(double) + sizeof(short)); 134 135 EXPECT_EQ(C1->getDouble(), 0); 136 EXPECT_EQ(C1->getShort(), 4); 137 EXPECT_EQ(C1->getTrailingObjects<double>(), 138 reinterpret_cast<double *>(C1 + 1)); 139 EXPECT_EQ(C1->getTrailingObjects<short>(), reinterpret_cast<short *>(C1 + 1)); 140 141 EXPECT_EQ(C2->getDouble(), 4.2); 142 EXPECT_EQ(C2->getShort(), 0); 143 EXPECT_EQ(C2->getTrailingObjects<double>(), 144 reinterpret_cast<double *>(C2 + 1)); 145 EXPECT_EQ(C2->getTrailingObjects<short>(), 146 reinterpret_cast<short *>(reinterpret_cast<double *>(C2 + 1) + 1)); 147 delete C1; 148 delete C2; 149} 150 151// This test class is not trying to be a usage demo, just asserting 152// that three args does actually work too (it's the same code as 153// handles the second arg, so it's basically covered by the above, but 154// just in case..) 155class Class3 final : public TrailingObjects<Class3, double, short, bool> { 156 friend TrailingObjects; 157 158 size_t numTrailingObjects(OverloadToken<double>) const { return 1; } 159 size_t numTrailingObjects(OverloadToken<short>) const { return 1; } 160}; 161 162TEST(TrailingObjects, ThreeArg) { 163 EXPECT_EQ((Class3::additionalSizeToAlloc<double, short, bool>(1, 1, 3)), 164 sizeof(double) + sizeof(short) + 3 * sizeof(bool)); 165 EXPECT_EQ(sizeof(Class3), 166 llvm::RoundUpToAlignment(1, llvm::alignOf<double>())); 167 std::unique_ptr<char[]> P(new char[1000]); 168 Class3 *C = reinterpret_cast<Class3 *>(P.get()); 169 EXPECT_EQ(C->getTrailingObjects<double>(), reinterpret_cast<double *>(C + 1)); 170 EXPECT_EQ(C->getTrailingObjects<short>(), 171 reinterpret_cast<short *>(reinterpret_cast<double *>(C + 1) + 1)); 172 EXPECT_EQ( 173 C->getTrailingObjects<bool>(), 174 reinterpret_cast<bool *>( 175 reinterpret_cast<short *>(reinterpret_cast<double *>(C + 1) + 1) + 176 1)); 177} 178} 179