Skip to content

Commit 9036cd2

Browse files
committed
[LLVM][Support] Add getTrailingObjects() for single trailing type
Add a specialization of getTrailingObjects() for a single trailing type. This is a common case and with the specialization you don't need to specify the single trailing type redundantly. Also add an overload for getTrailingObjects which takes size and returns an ArryaRef/MutableArrayRef as that's a common use case as well.
1 parent 70cf616 commit 9036cd2

File tree

2 files changed

+57
-20
lines changed

2 files changed

+57
-20
lines changed

llvm/include/llvm/Support/TrailingObjects.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#ifndef LLVM_SUPPORT_TRAILINGOBJECTS_H
4747
#define LLVM_SUPPORT_TRAILINGOBJECTS_H
4848

49+
#include "llvm/ADT/ArrayRef.h"
4950
#include "llvm/Support/Alignment.h"
5051
#include "llvm/Support/Compiler.h"
5152
#include "llvm/Support/MathExtras.h"
@@ -301,6 +302,41 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
301302
static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
302303
}
303304

305+
// getTrailingObjects() specialization for a single trailing type.
306+
using FirstTrailingType =
307+
typename std::tuple_element_t<0, std::tuple<TrailingTys...>>;
308+
309+
const FirstTrailingType *getTrailingObjects() const {
310+
static_assert(sizeof...(TrailingTys) == 1,
311+
"Can use non-templated getTrailingObjects() only when there "
312+
"is a single trailing type");
313+
return getTrailingObjects<FirstTrailingType>();
314+
}
315+
316+
FirstTrailingType *getTrailingObjects() {
317+
static_assert(sizeof...(TrailingTys) == 1,
318+
"Can use non-templated getTrailingObjects() only when there "
319+
"is a single trailing type");
320+
return getTrailingObjects<FirstTrailingType>();
321+
}
322+
323+
// Functions that return the trailing objects as ArrayRefs.
324+
template <typename T> MutableArrayRef<T> getTrailingObjects(size_t N) {
325+
return {getTrailingObjects<T>(), N};
326+
}
327+
328+
template <typename T> ArrayRef<T> getTrailingObjects(size_t N) const {
329+
return {getTrailingObjects<T>(), N};
330+
}
331+
332+
MutableArrayRef<FirstTrailingType> getTrailingObjects(size_t N) {
333+
return {getTrailingObjects(), N};
334+
}
335+
336+
ArrayRef<FirstTrailingType> getTrailingObjects(size_t N) const {
337+
return {getTrailingObjects(), N};
338+
}
339+
304340
/// Returns the size of the trailing data, if an object were
305341
/// allocated with the given counts (The counts are in the same order
306342
/// as the template arguments). This does not include the size of the

llvm/unittests/Support/TrailingObjectsTest.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,32 @@
1212
using namespace llvm;
1313

1414
namespace {
15-
// This class, beyond being used by the test case, a nice
16-
// demonstration of the intended usage of TrailingObjects, with a
17-
// single trailing array.
18-
class Class1 final : protected TrailingObjects<Class1, short> {
15+
// This class, beyond being used by the test case, a nice demonstration of the
16+
// intended usage of TrailingObjects, with a single trailing array.
17+
class Class1 final : private TrailingObjects<Class1, short> {
1918
friend TrailingObjects;
2019

2120
unsigned NumShorts;
2221

2322
protected:
24-
size_t numTrailingObjects(OverloadToken<short>) const { return NumShorts; }
25-
2623
Class1(int *ShortArray, unsigned NumShorts) : NumShorts(NumShorts) {
24+
// This tests the non-templated getTrailingObjects() when using a single
25+
// trailing type.
2726
std::uninitialized_copy(ShortArray, ShortArray + NumShorts,
28-
getTrailingObjects<short>());
27+
getTrailingObjects());
28+
29+
EXPECT_EQ(getTrailingObjects(), getTrailingObjects<short>());
2930
}
3031

3132
public:
3233
static Class1 *create(int *ShortArray, unsigned NumShorts) {
3334
void *Mem = ::operator new(totalSizeToAlloc<short>(NumShorts));
3435
return new (Mem) Class1(ShortArray, NumShorts);
3536
}
36-
void operator delete(void *p) { ::operator delete(p); }
37+
void operator delete(void *Ptr) { ::operator delete(Ptr); }
3738

38-
short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; }
39+
// This indexes into the ArrayRef<> returned by `getTrailingObjects`.
40+
short get(unsigned Num) const { return getTrailingObjects(NumShorts)[Num]; }
3941

4042
unsigned numShorts() const { return NumShorts; }
4143

@@ -48,9 +50,9 @@ class Class1 final : protected TrailingObjects<Class1, short> {
4850
using TrailingObjects::getTrailingObjects;
4951
};
5052

51-
// Here, there are two singular optional object types appended. Note
52-
// that the alignment of Class2 is automatically increased to account
53-
// for the alignment requirements of the trailing objects.
53+
// Here, there are two singular optional object types appended. Note that the
54+
// alignment of Class2 is automatically increased to account for the alignment
55+
// requirements of the trailing objects.
5456
class Class2 final : protected TrailingObjects<Class2, double, short> {
5557
friend TrailingObjects;
5658

@@ -81,7 +83,7 @@ class Class2 final : protected TrailingObjects<Class2, double, short> {
8183
*C->getTrailingObjects<double>() = D;
8284
return C;
8385
}
84-
void operator delete(void *p) { ::operator delete(p); }
86+
void operator delete(void *Ptr) { ::operator delete(Ptr); }
8587

8688
short getShort() const {
8789
if (!HasShort)
@@ -171,10 +173,9 @@ TEST(TrailingObjects, TwoArg) {
171173
delete C2;
172174
}
173175

174-
// This test class is not trying to be a usage demo, just asserting
175-
// that three args does actually work too (it's the same code as
176-
// handles the second arg, so it's basically covered by the above, but
177-
// just in case..)
176+
// This test class is not trying to be a usage demo, just asserting that three
177+
// args does actually work too (it's the same code as handles the second arg, so
178+
// it's basically covered by the above, but just in case..)
178179
class Class3 final : public TrailingObjects<Class3, double, short, bool> {
179180
friend TrailingObjects;
180181

@@ -236,9 +237,9 @@ TEST(TrailingObjects, Realignment) {
236237
}
237238
}
238239

239-
// Test the use of TrailingObjects with a template class. This
240-
// previously failed to compile due to a bug in MSVC's member access
241-
// control/lookup handling for OverloadToken.
240+
// Test the use of TrailingObjects with a template class. This previously failed
241+
// to compile due to a bug in MSVC's member access control/lookup handling for
242+
// OverloadToken.
242243
template <typename Derived>
243244
class Class5Tmpl : private llvm::TrailingObjects<Derived, float, int> {
244245
using TrailingObjects = typename llvm::TrailingObjects<Derived, float>;

0 commit comments

Comments
 (0)