From cb39a85070daf4a13a9596aa5b2c6fa261a2a36b Mon Sep 17 00:00:00 2001 From: Serge Guelton Date: Sun, 20 Jan 2019 21:19:56 +0000 Subject: [PATCH] Replace llvm::isPodLike<...> by llvm::is_trivially_copyable<...> As noted in https://bugs.llvm.org/show_bug.cgi?id=36651, the specialization for isPodLike> 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 llvm::Optional 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 --- docs/ProgrammersManual.rst | 2 +- include/llvm/ADT/ArrayRef.h | 6 -- include/llvm/ADT/DenseMap.h | 6 +- include/llvm/ADT/ImmutableList.h | 4 - include/llvm/ADT/Optional.h | 7 +- include/llvm/ADT/PointerIntPair.h | 6 -- include/llvm/ADT/SmallVector.h | 15 ++-- include/llvm/ADT/StringRef.h | 4 - include/llvm/ADT/bit.h | 10 +-- .../llvm/Analysis/BlockFrequencyInfoImpl.h | 8 +- include/llvm/Bitcode/BitCodes.h | 2 - include/llvm/CodeGen/DIE.h | 2 +- include/llvm/CodeGen/RegisterPressure.h | 4 - include/llvm/CodeGen/ScheduleDAG.h | 3 - include/llvm/CodeGen/SelectionDAGNodes.h | 1 - include/llvm/CodeGen/SlotIndexes.h | 2 - include/llvm/CodeGen/TargetPassConfig.h | 3 - include/llvm/IR/CFG.h | 4 - include/llvm/IR/ValueHandle.h | 17 ---- include/llvm/MC/MCInst.h | 2 - include/llvm/Support/ScaledNumber.h | 4 - include/llvm/Support/type_traits.h | 84 ++++++++++++------- lib/Transforms/Scalar/SROA.cpp | 7 -- tools/llvm-diff/DifferenceEngine.cpp | 2 +- unittests/ADT/ArrayRefTest.cpp | 3 + unittests/ADT/ImmutableListTest.cpp | 3 + unittests/ADT/PointerIntPairTest.cpp | 8 ++ unittests/ADT/StringRefTest.cpp | 2 + unittests/Analysis/BlockFrequencyInfoTest.cpp | 4 + unittests/Bitcode/BitstreamReaderTest.cpp | 3 + unittests/CodeGen/CMakeLists.txt | 1 + unittests/CodeGen/MachineInstrTest.cpp | 2 + unittests/IR/CFGBuilder.cpp | 9 ++ unittests/Support/ScaledNumberTest.cpp | 3 + 34 files changed, 115 insertions(+), 128 deletions(-) diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index 0903a22fc3e..7faba112ffe 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -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`` and uses realloc aggressively. +#. SmallVector understands ``llvm::is_trivially_copyable`` and uses realloc aggressively. #. Many LLVM APIs take a SmallVectorImpl as an out parameter (see the note below). diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index e6834269c0c..75bb7d690cc 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -525,12 +525,6 @@ namespace llvm { /// @} - // ArrayRefs can be treated like a POD type. - template struct isPodLike; - template struct isPodLike> { - static const bool value = true; - }; - template hash_code hash_value(ArrayRef S) { return hash_combine_range(S.begin(), S.end()); } diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 289cc4a0347..e7cd370df6f 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -145,7 +145,8 @@ public: } const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); - if (isPodLike::value && isPodLike::value) { + if (is_trivially_copyable::value && + is_trivially_copyable::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::value && isPodLike::value) + if (is_trivially_copyable::value && + is_trivially_copyable::value) memcpy(reinterpret_cast(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 37c91cdd369..c9ee494734e 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -241,10 +241,6 @@ template struct DenseMapInfo> { } }; -template struct isPodLike; -template -struct isPodLike> { static const bool value = true; }; - } // end namespace llvm #endif // LLVM_ADT_IMMUTABLELIST_H diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 32401da517e..25a3185064f 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -30,7 +30,7 @@ class raw_ostream; namespace optional_detail { /// Storage for any type. -template ::value> struct OptionalStorage { +template ::value> struct OptionalStorage { AlignedCharArrayUnion storage; bool hasVal = false; @@ -185,11 +185,6 @@ public: #endif }; -template struct isPodLike> { - // An Optional is pod-like if T is. - static const bool value = isPodLike::value; -}; - template bool operator==(const Optional &X, const Optional &Y) { if (X && Y) diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index b73e3c9ba82..b132de81987 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -175,12 +175,6 @@ struct PointerIntPairInfo { } }; -template struct isPodLike; -template -struct isPodLike> { - static const bool value = true; -}; - // Provide specialization of DenseMapInfo for PointerIntPair. template struct DenseMapInfo> { diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 7650001d617..34efb05d43d 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -179,9 +179,9 @@ public: } }; -/// SmallVectorTemplateBase - This is where we put method +/// SmallVectorTemplateBase - This is where we put method /// implementations that are designed to work with non-POD-like T's. -template ::value> +template ::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon { protected: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} @@ -235,8 +235,8 @@ public: }; // Define this out-of-line to dissuade the C++ compiler from inlining it. -template -void SmallVectorTemplateBase::grow(size_t MinSize) { +template +void SmallVectorTemplateBase::grow(size_t MinSize) { if (MinSize > UINT32_MAX) report_bad_alloc_error("SmallVector capacity overflow during allocation"); @@ -259,9 +259,8 @@ void SmallVectorTemplateBase::grow(size_t MinSize) { this->Capacity = NewCapacity; } - -/// SmallVectorTemplateBase - This is where we put method -/// implementations that are designed to work with POD-like T's. +/// SmallVectorTemplateBase - This is where we put +/// method implementations that are designed to work with POD-like T's. template class SmallVectorTemplateBase : public SmallVectorTemplateCommon { protected: @@ -330,7 +329,7 @@ public: protected: // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned N) - : SmallVectorTemplateBase::value>(N) {} + : SmallVectorTemplateBase(N) {} public: SmallVectorImpl(const SmallVectorImpl &) = delete; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index a98ed94ff28..76687a94bca 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -927,10 +927,6 @@ namespace llvm { LLVM_NODISCARD hash_code hash_value(StringRef S); - // StringRefs can be treated like a POD type. - template struct isPodLike; - template <> struct isPodLike { static const bool value = true; }; - } // end namespace llvm #endif // LLVM_ADT_STRINGREF_H diff --git a/include/llvm/ADT/bit.h b/include/llvm/ADT/bit.h index 9b084c840ad..a790d5ed2d2 100644 --- a/include/llvm/ADT/bit.h +++ b/include/llvm/ADT/bit.h @@ -40,11 +40,11 @@ template ::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 { diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 31e361cc30b..813bad49888 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -159,10 +159,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, BlockMass X) { } // end namespace bfi_detail -template <> struct isPodLike { - 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::max(); + IndexType Index; - BlockNode() = default; + BlockNode() : Index(std::numeric_limits::max()) {} BlockNode(IndexType Index) : Index(Index) {} bool operator==(const BlockNode &X) const { return Index == X.Index; } diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index 4cc38bf28ba..a0d8dfd68bf 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -159,8 +159,6 @@ public: }; -template <> struct isPodLike { 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. diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index aae6c6ecd28..9e7167fd88c 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -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); diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 2797d8fa908..5bbaa03fd75 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -131,10 +131,6 @@ public: } }; -template <> struct isPodLike { - 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 diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 6d33dda1566..68614dded81 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -238,9 +238,6 @@ class TargetRegisterInfo; void dump(const TargetRegisterInfo *TRI = nullptr) const; }; - template <> - struct isPodLike { static const bool value = true; }; - /// Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 09d058da0b6..ec0fce6202b 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -231,7 +231,6 @@ template<> struct DenseMapInfo { return LHS == RHS; } }; -template <> struct isPodLike { static const bool value = true; }; /// Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 90904d6702f..63461d61bf3 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -301,8 +301,6 @@ class raw_ostream; } }; - template <> struct isPodLike { static const bool value = true; }; - inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { li.print(os); return os; diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h index c021958d93a..5567ff6f27a 100644 --- a/include/llvm/CodeGen/TargetPassConfig.h +++ b/include/llvm/CodeGen/TargetPassConfig.h @@ -74,9 +74,6 @@ public: } }; -template <> struct isPodLike { - static const bool value = true; -}; /// Target-Independent Code Generator Pass Configuration Options. /// diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index 98e61ee47a5..55aff7137e8 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -237,10 +237,6 @@ public: } }; -template struct isPodLike> { - static const bool value = isPodLike::value; -}; - using succ_iterator = SuccIterator; using succ_const_iterator = SuccIterator; using succ_range = iterator_range; diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 4e17ae34d28..1135d796f7e 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -308,15 +308,6 @@ struct DenseMapInfo> { } }; -template -struct isPodLike> { -#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 struct DenseMapInfo> { } }; -template struct isPodLike> { -#ifdef NDEBUG - static const bool value = true; -#else - static const bool value = false; -#endif -}; - } // end namespace llvm #endif // LLVM_IR_VALUEHANDLE_H diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 4cb88b3c97e..9675b786745 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -153,8 +153,6 @@ public: bool evaluateAsConstantImm(int64_t &Imm) const; }; -template <> struct isPodLike { static const bool value = true; }; - /// Instances of this class represent a single low-level machine /// instruction. class MCInst { diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index e84c044df04..552da34f357 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -886,10 +886,6 @@ template void ScaledNumber::shiftRight(int32_t Shift) { Digits >>= Shift; } -template struct isPodLike; -template struct isPodLike> { - static const bool value = true; -}; } // end namespace llvm diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 7d68a12e66f..b8cf12d03d2 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -24,35 +24,6 @@ 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 -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::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::value; -#endif -}; - -// std::pair's are pod-like if their elements are. -template -struct isPodLike> { - static const bool value = isPodLike::value && isPodLike::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 union move_construction_triviality_helper { move_construction_triviality_helper(move_construction_triviality_helper&&) = default; ~move_construction_triviality_helper() = default; }; + +template +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 : std::true_type {}; template struct is_trivially_move_constructible : 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 +class is_trivially_copyable { + + // copy constructors + static constexpr bool has_trivial_copy_constructor = + std::is_copy_constructible>::value; + static constexpr bool has_deleted_copy_constructor = + !std::is_copy_constructible::value; + + // move constructors + static constexpr bool has_trivial_move_constructor = + std::is_move_constructible>::value; + static constexpr bool has_deleted_move_constructor = + !std::is_move_constructible::value; + + // copy assign + static constexpr bool has_trivial_copy_assign = + std::is_copy_assignable>::value; + static constexpr bool has_deleted_copy_assign = + !std::is_copy_assignable::value; + + // move assign + static constexpr bool has_trivial_move_assign = + std::is_move_assignable>::value; + static constexpr bool has_deleted_move_assign = + !std::is_move_assignable::value; + + // destructor + static constexpr bool has_trivial_destructor = + std::is_destructible>::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::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 diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index be65d16120c..991e9c7c52f 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -221,13 +221,6 @@ public: } // end anonymous namespace -namespace llvm { - -template struct isPodLike; -template <> struct isPodLike { 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 diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp index a1c6005ae9c..bc93ece8649 100644 --- a/tools/llvm-diff/DifferenceEngine.cpp +++ b/tools/llvm-diff/DifferenceEngine.cpp @@ -67,7 +67,7 @@ public: unsigned NewSize = Storage.size() - 1; if (NewSize) { // Move the slot at the end to the beginning. - if (isPodLike::value) + if (is_trivially_copyable::value) Storage[0] = Storage[NewSize]; else std::swap(Storage[0], Storage[NewSize]); diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp index ba540688cb5..a5609f89ff9 100644 --- a/unittests/ADT/ArrayRefTest.cpp +++ b/unittests/ADT/ArrayRefTest.cpp @@ -248,4 +248,7 @@ TEST(ArrayRefTest, makeArrayRef) { EXPECT_TRUE(AR2.equals(AR2Ref)); } +static_assert(is_trivially_copyable>::value, + "trivially copyable"); + } // end anonymous namespace diff --git a/unittests/ADT/ImmutableListTest.cpp b/unittests/ADT/ImmutableListTest.cpp index bd5289d6b29..b0b1e0e6c29 100644 --- a/unittests/ADT/ImmutableListTest.cpp +++ b/unittests/ADT/ImmutableListTest.cpp @@ -267,4 +267,7 @@ TEST_F(ImmutableListTest, LongListOrderingTest) { ASSERT_EQ(6, i); } +static_assert(is_trivially_copyable>>::value, + "trivially copyable"); + } // namespace diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp index 95e280330a7..6b3a4c055c9 100644 --- a/unittests/ADT/PointerIntPairTest.cpp +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -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>::value, + "trivially copyable"); } TEST(PointerIntPairTest, DefaultInitialize) { @@ -96,6 +99,11 @@ TEST(PointerIntPairTest, ManyUnusedBits) { EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1, PointerLikeTypeTraits::NumLowBitsAvailable); + + static_assert( + is_trivially_copyable< + PointerIntPair>::value, + "trivially copyable"); } } // end anonymous namespace diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index fbb60e6ce26..6f83dc3224a 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -1061,4 +1061,6 @@ TEST(StringRefTest, StringLiteral) { EXPECT_EQ(StringRef("Bar"), Strings[1]); } +static_assert(is_trivially_copyable::value, "trivially copyable"); + } // end anonymous namespace diff --git a/unittests/Analysis/BlockFrequencyInfoTest.cpp b/unittests/Analysis/BlockFrequencyInfoTest.cpp index 5572f5ba597..2aeba947a74 100644 --- a/unittests/Analysis/BlockFrequencyInfoTest.cpp +++ b/unittests/Analysis/BlockFrequencyInfoTest.cpp @@ -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::value, + "trivially copyable"); + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp index e9e6d9a1d07..85954858609 100644 --- a/unittests/Bitcode/BitstreamReaderTest.cpp +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -147,4 +147,7 @@ TEST(BitstreamReaderTest, shortRead) { } } +static_assert(is_trivially_copyable::value, + "trivially copyable"); + } // end anonymous namespace diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt index 5ef8c2afb8c..772c075de12 100644 --- a/unittests/CodeGen/CMakeLists.txt +++ b/unittests/CodeGen/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_unittest(CodeGenTests MachineInstrTest.cpp MachineOperandTest.cpp ScalableVectorMVTsTest.cpp + TypeTraitsTest.cpp ) add_subdirectory(GlobalISel) diff --git a/unittests/CodeGen/MachineInstrTest.cpp b/unittests/CodeGen/MachineInstrTest.cpp index 880e013b99f..2678a4589f9 100644 --- a/unittests/CodeGen/MachineInstrTest.cpp +++ b/unittests/CodeGen/MachineInstrTest.cpp @@ -272,4 +272,6 @@ TEST(MachineInstrPrintingTest, DebugLocPrinting) { StringRef(OS.str()).endswith("filename:1:5")); } +static_assert(is_trivially_copyable::value, "trivially copyable"); + } // end namespace diff --git a/unittests/IR/CFGBuilder.cpp b/unittests/IR/CFGBuilder.cpp index ca7a0555dd0..a2016f7e6cb 100644 --- a/unittests/IR/CFGBuilder.cpp +++ b/unittests/IR/CFGBuilder.cpp @@ -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(B.getOrAddBlock("c")->getTerminator())); EXPECT_TRUE(isa(B.getOrAddBlock("d")->getTerminator())); } + +static_assert(is_trivially_copyable::value, + "trivially copyable"); +static_assert(is_trivially_copyable::value, + "trivially copyable"); +static_assert(is_trivially_copyable::value, "trivially copyable"); +static_assert(is_trivially_copyable::value, + "trivially copyable"); diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp index 449c0477b0a..3fa63b7bf3c 100644 --- a/unittests/Support/ScaledNumberTest.cpp +++ b/unittests/Support/ScaledNumberTest.cpp @@ -562,4 +562,7 @@ TEST(ScaledNumberHelpersTest, toIntBug) { EXPECT_EQ(1u, (n * n).toInt()); } +static_assert(is_trivially_copyable>::value, + "trivially copyable"); + } // end namespace -- 2.50.1