]> granicus.if.org Git - llvm/commitdiff
Replace llvm::isPodLike<...> by llvm::is_trivially_copyable<...>
authorSerge Guelton <sguelton@quarkslab.com>
Sun, 20 Jan 2019 21:19:56 +0000 (21:19 +0000)
committerSerge Guelton <sguelton@quarkslab.com>
Sun, 20 Jan 2019 21:19:56 +0000 (21:19 +0000)
As noted in https://bugs.llvm.org/show_bug.cgi?id=36651, the specialization for
isPodLike<std::pair<...>> did not match the expectation of
std::is_trivially_copyable which makes the memcpy optimization invalid.

This patch renames the llvm::isPodLike trait into llvm::is_trivially_copyable.
Unfortunately std::is_trivially_copyable is not portable across compiler / STL
versions. So a portable version is provided too.

Note that the following specialization were invalid:

    std::pair<T0, T1>
    llvm::Optional<T>

Tests have been added to assert that former specialization are respected by the
standard usage of llvm::is_trivially_copyable, and that when a decent version
of std::is_trivially_copyable is available, llvm::is_trivially_copyable is
compared to std::is_trivially_copyable.

As of this patch, llvm::Optional is no longer considered trivially copyable,
even if T is. This is to be fixed in a later patch, as it has impact on a
long-running bug (see r347004)

Note that GCC warns about this UB, but this got silented by https://reviews.llvm.org/D50296.

Differential Revision: https://reviews.llvm.org/D54472

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351701 91177308-0d34-0410-b5e6-96231b3b80d8

34 files changed:
docs/ProgrammersManual.rst
include/llvm/ADT/ArrayRef.h
include/llvm/ADT/DenseMap.h
include/llvm/ADT/ImmutableList.h
include/llvm/ADT/Optional.h
include/llvm/ADT/PointerIntPair.h
include/llvm/ADT/SmallVector.h
include/llvm/ADT/StringRef.h
include/llvm/ADT/bit.h
include/llvm/Analysis/BlockFrequencyInfoImpl.h
include/llvm/Bitcode/BitCodes.h
include/llvm/CodeGen/DIE.h
include/llvm/CodeGen/RegisterPressure.h
include/llvm/CodeGen/ScheduleDAG.h
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/CodeGen/SlotIndexes.h
include/llvm/CodeGen/TargetPassConfig.h
include/llvm/IR/CFG.h
include/llvm/IR/ValueHandle.h
include/llvm/MC/MCInst.h
include/llvm/Support/ScaledNumber.h
include/llvm/Support/type_traits.h
lib/Transforms/Scalar/SROA.cpp
tools/llvm-diff/DifferenceEngine.cpp
unittests/ADT/ArrayRefTest.cpp
unittests/ADT/ImmutableListTest.cpp
unittests/ADT/PointerIntPairTest.cpp
unittests/ADT/StringRefTest.cpp
unittests/Analysis/BlockFrequencyInfoTest.cpp
unittests/Bitcode/BitstreamReaderTest.cpp
unittests/CodeGen/CMakeLists.txt
unittests/CodeGen/MachineInstrTest.cpp
unittests/IR/CFGBuilder.cpp
unittests/Support/ScaledNumberTest.cpp

index 0903a22fc3e8a3eac759ff8d034e299e2dbe30c7..7faba112ffe71cc2c4a80096d0e2ad01a3a8aca2 100644 (file)
@@ -1456,7 +1456,7 @@ SmallVector has grown a few other minor advantages over std::vector, causing
 #. std::vector is exception-safe, and some implementations have pessimizations
    that copy elements when SmallVector would move them.
 
-#. SmallVector understands ``isPodLike<Type>`` and uses realloc aggressively.
+#. SmallVector understands ``llvm::is_trivially_copyable<Type>`` and uses realloc aggressively.
 
 #. Many LLVM APIs take a SmallVectorImpl as an out parameter (see the note
    below).
index e6834269c0c57aa4bd9d1444538b1b642a1410e2..75bb7d690cc0e95fe8857171b4342faa0fc6f9e3 100644 (file)
@@ -525,12 +525,6 @@ namespace llvm {
 
   /// @}
 
-  // ArrayRefs can be treated like a POD type.
-  template <typename T> struct isPodLike;
-  template <typename T> struct isPodLike<ArrayRef<T>> {
-    static const bool value = true;
-  };
-
   template <typename T> hash_code hash_value(ArrayRef<T> S) {
     return hash_combine_range(S.begin(), S.end());
   }
index 289cc4a0347f9b8a6204c2787f0e598f0e7e9a77..e7cd370df6ff2ef21793119e55f898ac423302ca 100644 (file)
@@ -145,7 +145,8 @@ public:
     }
 
     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
-    if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) {
+    if (is_trivially_copyable<KeyT>::value &&
+        is_trivially_copyable<ValueT>::value) {
       // Use a simpler loop when these are trivial types.
       for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
         P->getFirst() = EmptyKey;
@@ -421,7 +422,8 @@ protected:
     setNumEntries(other.getNumEntries());
     setNumTombstones(other.getNumTombstones());
 
-    if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
+    if (is_trivially_copyable<KeyT>::value &&
+        is_trivially_copyable<ValueT>::value)
       memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(),
              getNumBuckets() * sizeof(BucketT));
     else
index 37c91cdd3692240f06884523840082cbf1371925..c9ee494734e7f2d1f721b8b81552154205647887 100644 (file)
@@ -241,10 +241,6 @@ template<typename T> struct DenseMapInfo<ImmutableList<T>> {
   }
 };
 
-template <typename T> struct isPodLike;
-template <typename T>
-struct isPodLike<ImmutableList<T>> { static const bool value = true; };
-
 } // end namespace llvm
 
 #endif // LLVM_ADT_IMMUTABLELIST_H
index 32401da517edd3da924933e01978288fd89f2e61..25a3185064f413225f0c63db53ea87114657dd75 100644 (file)
@@ -30,7 +30,7 @@ class raw_ostream;
 
 namespace optional_detail {
 /// Storage for any type.
-template <typename T, bool = isPodLike<T>::value> struct OptionalStorage {
+template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
   AlignedCharArrayUnion<T> storage;
   bool hasVal = false;
 
@@ -185,11 +185,6 @@ public:
 #endif
 };
 
-template <typename T> struct isPodLike<Optional<T>> {
-  // An Optional<T> is pod-like if T is.
-  static const bool value = isPodLike<T>::value;
-};
-
 template <typename T, typename U>
 bool operator==(const Optional<T> &X, const Optional<U> &Y) {
   if (X && Y)
index b73e3c9ba82d41e0223b6a90d2c5916ae0ce42f9..b132de819874103c1fd8e89cbcb6820c662d6b21 100644 (file)
@@ -175,12 +175,6 @@ struct PointerIntPairInfo {
   }
 };
 
-template <typename T> struct isPodLike;
-template <typename PointerTy, unsigned IntBits, typename IntType>
-struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType>> {
-  static const bool value = true;
-};
-
 // Provide specialization of DenseMapInfo for PointerIntPair.
 template <typename PointerTy, unsigned IntBits, typename IntType>
 struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> {
index 7650001d6174a5602d6f078e33f8ef068be47a73..34efb05d43d9692628489ffaca5d956c08f7f1ff 100644 (file)
@@ -179,9 +179,9 @@ public:
   }
 };
 
-/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
+/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method
 /// implementations that are designed to work with non-POD-like T's.
-template <typename T, bool = isPodLike<T>::value>
+template <typename T, bool = is_trivially_copyable<T>::value>
 class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
 protected:
   SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
@@ -235,8 +235,8 @@ public:
 };
 
 // Define this out-of-line to dissuade the C++ compiler from inlining it.
-template <typename T, bool isPodLike>
-void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
+template <typename T, bool TriviallyCopyable>
+void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
   if (MinSize > UINT32_MAX)
     report_bad_alloc_error("SmallVector capacity overflow during allocation");
 
@@ -259,9 +259,8 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
   this->Capacity = NewCapacity;
 }
 
-
-/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
-/// implementations that are designed to work with POD-like T's.
+/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
+/// method implementations that are designed to work with POD-like T's.
 template <typename T>
 class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
 protected:
@@ -330,7 +329,7 @@ public:
 protected:
   // Default ctor - Initialize to empty.
   explicit SmallVectorImpl(unsigned N)
-      : SmallVectorTemplateBase<T, isPodLike<T>::value>(N) {}
+      : SmallVectorTemplateBase<T>(N) {}
 
 public:
   SmallVectorImpl(const SmallVectorImpl &) = delete;
index a98ed94ff28c810d4d06f1a7b0e1836dd16aa29f..76687a94bca51be2bbf8c48a1cce8e6bff4178bc 100644 (file)
@@ -927,10 +927,6 @@ namespace llvm {
   LLVM_NODISCARD
   hash_code hash_value(StringRef S);
 
-  // StringRefs can be treated like a POD type.
-  template <typename T> struct isPodLike;
-  template <> struct isPodLike<StringRef> { static const bool value = true; };
-
 } // end namespace llvm
 
 #endif // LLVM_ADT_STRINGREF_H
index 9b084c840ad0f9494930fa163424e2a8534b3867..a790d5ed2d21a4d41d8c87c334823d374898cd05 100644 (file)
@@ -40,11 +40,11 @@ template <typename To, typename From
           , typename = typename std::enable_if<__is_trivially_copyable(To)>::type
           , typename = typename std::enable_if<__is_trivially_copyable(From)>::type
 #else
-  // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
-  // llvm/Support/type_traits.h's isPodLike we don't want to provide a
-  // good-enough answer here: developers in that configuration will hit
-  // compilation failures on the bots instead of locally. That's acceptable
-  // because it's very few developers, and only until we move past C++11.
+// This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
+// llvm/Support/type_traits.h's is_trivially_copyable we don't want to
+// provide a good-enough answer here: developers in that configuration will hit
+// compilation failures on the bots instead of locally. That's acceptable
+// because it's very few developers, and only until we move past C++11.
 #endif
 >
 inline To bit_cast(const From &from) noexcept {
index 31e361cc30bfcb996061ed71d067d77fdc97fc72..813bad49888043598feb9fa0afa3b1f06bda9f04 100644 (file)
@@ -159,10 +159,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, BlockMass X) {
 
 } // end namespace bfi_detail
 
-template <> struct isPodLike<bfi_detail::BlockMass> {
-  static const bool value = true;
-};
-
 /// Base class for BlockFrequencyInfoImpl
 ///
 /// BlockFrequencyInfoImplBase has supporting data structures and some
@@ -186,9 +182,9 @@ public:
   struct BlockNode {
     using IndexType = uint32_t;
 
-    IndexType Index = std::numeric_limits<uint32_t>::max();
+    IndexType Index;
 
-    BlockNode() = default;
+    BlockNode() : Index(std::numeric_limits<uint32_t>::max()) {}
     BlockNode(IndexType Index) : Index(Index) {}
 
     bool operator==(const BlockNode &X) const { return Index == X.Index; }
index 4cc38bf28baf819459a225faf9212e54c8935fad..a0d8dfd68bf7177554b19b717d2feb0d26fe5d02 100644 (file)
@@ -159,8 +159,6 @@ public:
 
 };
 
-template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
-
 /// BitCodeAbbrev - This class represents an abbreviation record.  An
 /// abbreviation allows a complex record that has redundancy to be stored in a
 /// specialized format instead of the fully-general, fully-vbr, format.
index aae6c6ecd284c75c66dcb91df1daeb31c69b12b9..9e7167fd88c71ba0045b129ecd46d8c34078145b 100644 (file)
@@ -799,7 +799,7 @@ class DIEUnit {
   const uint16_t Version; /// The Dwarf version number for this unit.
   const uint8_t AddrSize; /// The size in bytes of an address for this unit.
 protected:
-  ~DIEUnit() = default;
+  virtual ~DIEUnit() = default;
 
 public:
   DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag);
index 2797d8fa908b90ac60a1b8c89ea92d97248c0f62..5bbaa03fd75158695c8015ce3bfb858fdbfa0fc5 100644 (file)
@@ -131,10 +131,6 @@ public:
   }
 };
 
-template <> struct isPodLike<PressureChange> {
-   static const bool value = true;
-};
-
 /// List of PressureChanges in order of increasing, unique PSetID.
 ///
 /// Use a small fixed number, because we can fit more PressureChanges in an
index 6d33dda15663bc329340eea400aa75f74554bcc6..68614dded8179935f7cea6a67c297d9f2b33f8af 100644 (file)
@@ -238,9 +238,6 @@ class TargetRegisterInfo;
     void dump(const TargetRegisterInfo *TRI = nullptr) const;
   };
 
-  template <>
-  struct isPodLike<SDep> { static const bool value = true; };
-
   /// Scheduling unit. This is a node in the scheduling DAG.
   class SUnit {
   private:
index 09d058da0b6eb08ad8e7ad3c1afbe469497038bf..ec0fce6202bccac165d56585900415641fb6727f 100644 (file)
@@ -231,7 +231,6 @@ template<> struct DenseMapInfo<SDValue> {
     return LHS == RHS;
   }
 };
-template <> struct isPodLike<SDValue> { static const bool value = true; };
 
 /// Allow casting operators to work directly on
 /// SDValues as if they were SDNode*'s.
index 90904d6702fd8f6b3655337a9bec0de7a2e9c30b..63461d61bf3485532a53d095270f1f6206da9e1e 100644 (file)
@@ -301,8 +301,6 @@ class raw_ostream;
     }
   };
 
-  template <> struct isPodLike<SlotIndex> { static const bool value = true; };
-
   inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) {
     li.print(os);
     return os;
index c021958d93a05cf69524ade9679ea58df930d49e..5567ff6f27a4837954972f48185ce898423f5db0 100644 (file)
@@ -74,9 +74,6 @@ public:
   }
 };
 
-template <> struct isPodLike<IdentifyingPassPtr> {
-  static const bool value = true;
-};
 
 /// Target-Independent Code Generator Pass Configuration Options.
 ///
index 98e61ee47a5bb55cc1caf6a268a9be35e4ff045b..55aff7137e86f61a3735a842691c6adf432b21c9 100644 (file)
@@ -237,10 +237,6 @@ public:
   }
 };
 
-template <typename T, typename U> struct isPodLike<SuccIterator<T, U>> {
-  static const bool value = isPodLike<T>::value;
-};
-
 using succ_iterator = SuccIterator<Instruction, BasicBlock>;
 using succ_const_iterator = SuccIterator<const Instruction, const BasicBlock>;
 using succ_range = iterator_range<succ_iterator>;
index 4e17ae34d288f8a5383fbf40fa8c2833f6326f7f..1135d796f7ed7def28191f78d224c03a9a3e2c13 100644 (file)
@@ -308,15 +308,6 @@ struct DenseMapInfo<AssertingVH<T>> {
   }
 };
 
-template <typename T>
-struct isPodLike<AssertingVH<T>> {
-#ifdef NDEBUG
-  static const bool value = true;
-#else
-  static const bool value = false;
-#endif
-};
-
 /// Value handle that tracks a Value across RAUW.
 ///
 /// TrackingVH is designed for situations where a client needs to hold a handle
@@ -548,14 +539,6 @@ template <typename T> struct DenseMapInfo<PoisoningVH<T>> {
   }
 };
 
-template <typename T> struct isPodLike<PoisoningVH<T>> {
-#ifdef NDEBUG
-  static const bool value = true;
-#else
-  static const bool value = false;
-#endif
-};
-
 } // end namespace llvm
 
 #endif // LLVM_IR_VALUEHANDLE_H
index 4cb88b3c97e47e152ffec9a698c115aab0bafefb..9675b786745f10301a0c2a920c71c436a60fa43e 100644 (file)
@@ -153,8 +153,6 @@ public:
   bool evaluateAsConstantImm(int64_t &Imm) const;
 };
 
-template <> struct isPodLike<MCOperand> { static const bool value = true; };
-
 /// Instances of this class represent a single low-level machine
 /// instruction.
 class MCInst {
index e84c044df047f5c0faaa72209c349b84f2b33316..552da34f357b78c54f90a2bba2d1387040c931d7 100644 (file)
@@ -886,10 +886,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
   Digits >>= Shift;
 }
 
-template <typename T> struct isPodLike;
-template <typename T> struct isPodLike<ScaledNumber<T>> {
-  static const bool value = true;
-};
 
 } // end namespace llvm
 
index 7d68a12e66f662cdac802384effc7d008ef28507..b8cf12d03d286e16d5711775a7c2899186b53ee4 100644 (file)
 
 namespace llvm {
 
-/// isPodLike - This is a type trait that is used to determine whether a given
-/// type can be copied around with memcpy instead of running ctors etc.
-template <typename T>
-struct isPodLike {
-  // std::is_trivially_copyable is available in libc++ with clang, libstdc++
-  // that comes with GCC 5.  MSVC 2015 and newer also have
-  // std::is_trivially_copyable.
-#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) ||      \
-    (defined(__GNUC__) && __GNUC__ >= 5) || defined(_MSC_VER)
-  // If the compiler supports the is_trivially_copyable trait use it, as it
-  // matches the definition of isPodLike closely.
-  static const bool value = std::is_trivially_copyable<T>::value;
-#elif __has_feature(is_trivially_copyable)
-  // Use the internal name if the compiler supports is_trivially_copyable but we
-  // don't know if the standard library does. This is the case for clang in
-  // conjunction with libstdc++ from GCC 4.x.
-  static const bool value = __is_trivially_copyable(T);
-#else
-  // If we don't know anything else, we can (at least) assume that all non-class
-  // types are PODs.
-  static const bool value = !std::is_class<T>::value;
-#endif
-};
-
-// std::pair's are pod-like if their elements are.
-template<typename T, typename U>
-struct isPodLike<std::pair<T, U>> {
-  static const bool value = isPodLike<T>::value && isPodLike<U>::value;
-};
 
 /// Metafunction that determines whether the given type is either an
 /// integral type or an enumeration type, including enum classes.
@@ -119,6 +90,11 @@ template<typename T> union move_construction_triviality_helper {
     move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
     ~move_construction_triviality_helper() = default;
 };
+
+template<class T>
+union trivial_helper {
+    T t;
+};
 } // end namespace detail
 
 /// An implementation of `std::is_trivially_copy_constructible` since we have
@@ -143,6 +119,56 @@ struct is_trivially_move_constructible<T &> : std::true_type {};
 template <typename T>
 struct is_trivially_move_constructible<T &&> : std::true_type {};
 
+// An implementation of `std::is_trivially_copyable` since STL version
+// is not equally supported by all compilers, especially GCC 4.9.
+// Uniform implementation of this trait is important for ABI compatibility
+// as it has an impact on SmallVector's ABI (among others).
+template <typename T>
+class is_trivially_copyable {
+
+  // copy constructors
+  static constexpr bool has_trivial_copy_constructor =
+      std::is_copy_constructible<detail::trivial_helper<T>>::value;
+  static constexpr bool has_deleted_copy_constructor =
+      !std::is_copy_constructible<T>::value;
+
+  // move constructors
+  static constexpr bool has_trivial_move_constructor =
+      std::is_move_constructible<detail::trivial_helper<T>>::value;
+  static constexpr bool has_deleted_move_constructor =
+      !std::is_move_constructible<T>::value;
+
+  // copy assign
+  static constexpr bool has_trivial_copy_assign =
+      std::is_copy_assignable<detail::trivial_helper<T>>::value;
+  static constexpr bool has_deleted_copy_assign =
+      !std::is_copy_assignable<T>::value;
+
+  // move assign
+  static constexpr bool has_trivial_move_assign =
+      std::is_move_assignable<detail::trivial_helper<T>>::value;
+  static constexpr bool has_deleted_move_assign =
+      !std::is_move_assignable<T>::value;
+
+  // destructor
+  static constexpr bool has_trivial_destructor =
+      std::is_destructible<detail::trivial_helper<T>>::value;
+
+  public:
+
+  static constexpr bool value =
+      has_trivial_destructor &&
+      (has_deleted_move_assign || has_trivial_move_assign) &&
+      (has_deleted_move_constructor || has_trivial_move_constructor) &&
+      (has_deleted_copy_assign || has_trivial_copy_assign) &&
+      (has_deleted_copy_constructor || has_trivial_copy_constructor);
+
+#if (__has_feature(is_trivially_copyable) || (defined(__GNUC__) && __GNUC__ >= 5))
+  static_assert(value == std::is_trivially_copyable<T>::value, "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
+#endif
+};
+
+
 } // end namespace llvm
 
 // If the compiler supports detecting whether a class is final, define
index be65d16120c41a04d3f212f3c4ba0198a45e664b..991e9c7c52f6268d402cc50644428979c2d706dd 100644 (file)
@@ -221,13 +221,6 @@ public:
 
 } // end anonymous namespace
 
-namespace llvm {
-
-template <typename T> struct isPodLike;
-template <> struct isPodLike<Slice> { static const bool value = true; };
-
-} // end namespace llvm
-
 /// Representation of the alloca slices.
 ///
 /// This class represents the slices of an alloca which are formed by its
index a1c6005ae9cb00625ebfe60a443e3ec31be4f127..bc93ece864900bb8105a8c811b6f1f5a0f38b956 100644 (file)
@@ -67,7 +67,7 @@ public:
     unsigned NewSize = Storage.size() - 1;
     if (NewSize) {
       // Move the slot at the end to the beginning.
-      if (isPodLike<T>::value)
+      if (is_trivially_copyable<T>::value)
         Storage[0] = Storage[NewSize];
       else
         std::swap(Storage[0], Storage[NewSize]);
index ba540688cb535cbf6fc786ea03c448dd4dea6859..a5609f89ff95bd3ba647af3f9a6c5142dca6b205 100644 (file)
@@ -248,4 +248,7 @@ TEST(ArrayRefTest, makeArrayRef) {
   EXPECT_TRUE(AR2.equals(AR2Ref));
 }
 
+static_assert(is_trivially_copyable<ArrayRef<int>>::value,
+              "trivially copyable");
+
 } // end anonymous namespace
index bd5289d6b29d05e1a1fe82cee39d83dc052c6520..b0b1e0e6c29f41dab16949cc8e4a4c2d8d1e9354 100644 (file)
@@ -267,4 +267,7 @@ TEST_F(ImmutableListTest, LongListOrderingTest) {
   ASSERT_EQ(6, i);
 }
 
+static_assert(is_trivially_copyable<ImmutableList<Wrapper<long>>>::value,
+              "trivially copyable");
+
 } // namespace
index 95e280330a70eb67b09f46c218b102ced251a1b9..6b3a4c055c9e7d4adcbd1d04116655afa80d2507 100644 (file)
@@ -61,6 +61,9 @@ TEST(PointerIntPairTest, GetSet) {
   Pair2.setPointerAndInt(&s, E::Case3);
   EXPECT_EQ(&s, Pair2.getPointer());
   EXPECT_EQ(E::Case3, Pair2.getInt());
+
+  static_assert(is_trivially_copyable<PointerIntPair<S *, 2, E>>::value,
+                "trivially copyable");
 }
 
 TEST(PointerIntPairTest, DefaultInitialize) {
@@ -96,6 +99,11 @@ TEST(PointerIntPairTest, ManyUnusedBits) {
 
   EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1,
             PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable);
+
+  static_assert(
+      is_trivially_copyable<
+          PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits>>::value,
+      "trivially copyable");
 }
 
 } // end anonymous namespace
index fbb60e6ce2647a472f58260ed3deca9cfd8ff6ad..6f83dc3224a3d30f92533174f0178dfad34a6f29 100644 (file)
@@ -1061,4 +1061,6 @@ TEST(StringRefTest, StringLiteral) {
   EXPECT_EQ(StringRef("Bar"), Strings[1]);
 }
 
+static_assert(is_trivially_copyable<StringRef>::value, "trivially copyable");
+
 } // end anonymous namespace
index 5572f5ba597fddd21ad53858dcd66f1a706402c0..2aeba947a745c4c283d84c30e95fabbfd36165ae 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/AsmParser/Parser.h"
@@ -90,5 +91,8 @@ TEST_F(BlockFrequencyInfoTest, Basic) {
   EXPECT_EQ(BFI.getBlockFreq(BB3).getFrequency(), BB3Freq);
 }
 
+static_assert(is_trivially_copyable<bfi_detail::BlockMass>::value,
+              "trivially copyable");
+
 } // end anonymous namespace
 } // end namespace llvm
index e9e6d9a1d079ddd1f4052568f70eba03520242b4..859548586099e551531374cb4d200bf36080fc33 100644 (file)
@@ -147,4 +147,7 @@ TEST(BitstreamReaderTest, shortRead) {
   }
 }
 
+static_assert(is_trivially_copyable<BitCodeAbbrevOp>::value,
+              "trivially copyable");
+
 } // end anonymous namespace
index 5ef8c2afb8c1ef2fe946ccee1beea1e7233f0768..772c075de123f5f57ae104438b20d53a8f5eb656 100644 (file)
@@ -19,6 +19,7 @@ add_llvm_unittest(CodeGenTests
   MachineInstrTest.cpp
   MachineOperandTest.cpp
   ScalableVectorMVTsTest.cpp
+  TypeTraitsTest.cpp
   )
 
 add_subdirectory(GlobalISel)
index 880e013b99f9b02e2626e557b36643c651afcdf8..2678a4589f9f9ba0fd28196395a8c4abec2269d6 100644 (file)
@@ -272,4 +272,6 @@ TEST(MachineInstrPrintingTest, DebugLocPrinting) {
       StringRef(OS.str()).endswith("filename:1:5"));
 }
 
+static_assert(is_trivially_copyable<MCOperand>::value, "trivially copyable");
+
 } // end namespace
index ca7a0555dd05b18a3854f88aa381e2d45d678d73..a2016f7e6cba344798a71cad8dfd2dd2db273126 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "CFGBuilder.h"
 
+#include "llvm/IR/CFG.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Support/Debug.h"
@@ -265,3 +266,11 @@ TEST(CFGBuilder, Rebuild) {
   EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("c")->getTerminator()));
   EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("d")->getTerminator()));
 }
+
+static_assert(is_trivially_copyable<succ_iterator>::value,
+              "trivially copyable");
+static_assert(is_trivially_copyable<succ_const_iterator>::value,
+              "trivially copyable");
+static_assert(is_trivially_copyable<succ_range>::value, "trivially copyable");
+static_assert(is_trivially_copyable<succ_const_range>::value,
+              "trivially copyable");
index 449c0477b0ac1b45037f54ba429dc2cbf9cd306f..3fa63b7bf3c72b84d069de0adb2b393b56c0a23b 100644 (file)
@@ -562,4 +562,7 @@ TEST(ScaledNumberHelpersTest, toIntBug) {
   EXPECT_EQ(1u, (n * n).toInt<uint32_t>());
 }
 
+static_assert(is_trivially_copyable<ScaledNumber<uint32_t>>::value,
+              "trivially copyable");
+
 } // end namespace