[llvm] [LLVM][Support] Add getTrailingObjects() for single trailing type (PR #138970)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 8 08:15:32 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Rahul Joshi (jurahul)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/138970.diff


2 Files Affected:

- (modified) llvm/include/llvm/Support/TrailingObjects.h (+36) 
- (modified) llvm/unittests/Support/TrailingObjectsTest.cpp (+18-18) 


``````````diff
diff --git a/llvm/include/llvm/Support/TrailingObjects.h b/llvm/include/llvm/Support/TrailingObjects.h
index 07cf08df45a6a..02c7ccf911aa8 100644
--- a/llvm/include/llvm/Support/TrailingObjects.h
+++ b/llvm/include/llvm/Support/TrailingObjects.h
@@ -46,6 +46,7 @@
 #ifndef LLVM_SUPPORT_TRAILINGOBJECTS_H
 #define LLVM_SUPPORT_TRAILINGOBJECTS_H
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/MathExtras.h"
@@ -301,6 +302,41 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
         static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
   }
 
+  // getTrailingObjects() specialization for a single trailing type.
+  using FirstTrailingType =
+      typename std::tuple_element_t<0, std::tuple<TrailingTys...>>;
+
+  const FirstTrailingType *getTrailingObjects() const {
+    static_assert(sizeof...(TrailingTys) == 1,
+                  "Can use non-templated getTrailingObjects() only when there "
+                  "is a single trailing type");
+    return getTrailingObjects<FirstTrailingType>();
+  }
+
+  FirstTrailingType *getTrailingObjects() {
+    static_assert(sizeof...(TrailingTys) == 1,
+                  "Can use non-templated getTrailingObjects() only when there "
+                  "is a single trailing type");
+    return getTrailingObjects<FirstTrailingType>();
+  }
+
+  // Functions that return the trailing objects as ArrayRefs.
+  template <typename T> MutableArrayRef<T> getTrailingObjects(size_t N) {
+    return {getTrailingObjects<T>(), N};
+  }
+
+  template <typename T> ArrayRef<T> getTrailingObjects(size_t N) const {
+    return {getTrailingObjects<T>(), N};
+  }
+
+  MutableArrayRef<FirstTrailingType> getTrailingObjects(size_t N) {
+    return {getTrailingObjects(), N};
+  }
+
+  ArrayRef<FirstTrailingType> getTrailingObjects(size_t N) const {
+    return {getTrailingObjects(), N};
+  }
+
   /// Returns the size of the trailing data, if an object were
   /// allocated with the given counts (The counts are in the same order
   /// as the template arguments). This does not include the size of the
diff --git a/llvm/unittests/Support/TrailingObjectsTest.cpp b/llvm/unittests/Support/TrailingObjectsTest.cpp
index e36979e75d7f7..c461301207db0 100644
--- a/llvm/unittests/Support/TrailingObjectsTest.cpp
+++ b/llvm/unittests/Support/TrailingObjectsTest.cpp
@@ -14,19 +14,19 @@
 using namespace llvm;
 
 namespace {
-// This class, beyond being used by the test case, a nice
-// demonstration of the intended usage of TrailingObjects, with a
-// single trailing array.
-class Class1 final : protected TrailingObjects<Class1, short> {
+// This class, beyond being used by the test case, a nice demonstration of the
+// intended usage of TrailingObjects, with a single trailing array.
+class Class1 final : private TrailingObjects<Class1, short> {
   friend TrailingObjects;
 
   unsigned NumShorts;
 
 protected:
-  size_t numTrailingObjects(OverloadToken<short>) const { return NumShorts; }
-
   Class1(ArrayRef<int> ShortArray) : NumShorts(ShortArray.size()) {
-    llvm::copy(ShortArray, getTrailingObjects<short>());
+    // This tests the non-templated getTrailingObjects() when using a single
+    // trailing type.
+    llvm::copy(ShortArray, getTrailingObjects());
+    EXPECT_EQ(getTrailingObjects(), getTrailingObjects<short>());
   }
 
 public:
@@ -36,7 +36,8 @@ class Class1 final : protected TrailingObjects<Class1, short> {
   }
   void operator delete(void *Ptr) { ::operator delete(Ptr); }
 
-  short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; }
+  // This indexes into the ArrayRef<> returned by `getTrailingObjects`.
+  short get(unsigned Num) const { return getTrailingObjects(NumShorts)[Num]; }
 
   unsigned numShorts() const { return NumShorts; }
 
@@ -49,9 +50,9 @@ class Class1 final : protected TrailingObjects<Class1, short> {
   using TrailingObjects::getTrailingObjects;
 };
 
-// Here, there are two singular optional object types appended.  Note
-// that the alignment of Class2 is automatically increased to account
-// for the alignment requirements of the trailing objects.
+// Here, there are two singular optional object types appended. Note that the
+// alignment of Class2 is automatically increased to account for the alignment
+// requirements of the trailing objects.
 class Class2 final : protected TrailingObjects<Class2, double, short> {
   friend TrailingObjects;
 
@@ -172,10 +173,9 @@ TEST(TrailingObjects, TwoArg) {
   delete C2;
 }
 
-// This test class is not trying to be a usage demo, just asserting
-// that three args does actually work too (it's the same code as
-// handles the second arg, so it's basically covered by the above, but
-// just in case..)
+// This test class is not trying to be a usage demo, just asserting that three
+// args does actually work too (it's the same code as handles the second arg, so
+// it's basically covered by the above, but just in case..)
 class Class3 final : public TrailingObjects<Class3, double, short, bool> {
   friend TrailingObjects;
 
@@ -237,9 +237,9 @@ TEST(TrailingObjects, Realignment) {
 }
 }
 
-// Test the use of TrailingObjects with a template class. This
-// previously failed to compile due to a bug in MSVC's member access
-// control/lookup handling for OverloadToken.
+// Test the use of TrailingObjects with a template class. This previously failed
+// to compile due to a bug in MSVC's member access control/lookup handling for
+// OverloadToken.
 template <typename Derived>
 class Class5Tmpl : private llvm::TrailingObjects<Derived, float, int> {
   using TrailingObjects = typename llvm::TrailingObjects<Derived, float>;

``````````

</details>


https://github.com/llvm/llvm-project/pull/138970


More information about the llvm-commits mailing list