209 lines · cpp
1//===- STLForwardCompatTest.cpp - Unit tests for STLForwardCompat ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/STLForwardCompat.h"10#include "CountCopyAndMove.h"11#include "gtest/gtest.h"12 13#include <optional>14#include <type_traits>15#include <utility>16 17namespace {18 19template <typename T>20class STLForwardCompatRemoveCVRefTest : public ::testing::Test {};21 22using STLForwardCompatRemoveCVRefTestTypes = ::testing::Types<23 // clang-format off24 std::pair<int, int>,25 std::pair<int &, int>,26 std::pair<const int, int>,27 std::pair<volatile int, int>,28 std::pair<const volatile int &, int>,29 std::pair<int *, int *>,30 std::pair<int *const, int *>,31 std::pair<const int *, const int *>,32 std::pair<int *&, int *>33 // clang-format on34 >;35 36TYPED_TEST_SUITE(STLForwardCompatRemoveCVRefTest,37 STLForwardCompatRemoveCVRefTestTypes, );38 39TYPED_TEST(STLForwardCompatRemoveCVRefTest, RemoveCVRef) {40 using From = typename TypeParam::first_type;41 using To = typename TypeParam::second_type;42 EXPECT_TRUE(43 (std::is_same<typename llvm::remove_cvref<From>::type, To>::value));44}45 46TYPED_TEST(STLForwardCompatRemoveCVRefTest, RemoveCVRefT) {47 using From = typename TypeParam::first_type;48 EXPECT_TRUE((std::is_same<typename llvm::remove_cvref<From>::type,49 llvm::remove_cvref_t<From>>::value));50}51 52template <typename T> class TypeIdentityTest : public ::testing::Test {53public:54 using TypeIdentity = llvm::type_identity<T>;55};56 57struct A {58 struct B {};59};60using TypeIdentityTestTypes =61 ::testing::Types<int, volatile int, A, const A::B>;62 63TYPED_TEST_SUITE(TypeIdentityTest, TypeIdentityTestTypes, /*NameGenerator*/);64 65TYPED_TEST(TypeIdentityTest, Identity) {66 // TestFixture is the instantiated TypeIdentityTest.67 EXPECT_TRUE(68 (std::is_same_v<TypeParam, typename TestFixture::TypeIdentity::type>));69}70 71TEST(TransformTest, TransformStd) {72 std::optional<int> A;73 74 std::optional<int> B = llvm::transformOptional(A, [&](int N) { return N + 1; });75 EXPECT_FALSE(B.has_value());76 77 A = 3;78 std::optional<int> C = llvm::transformOptional(A, [&](int N) { return N + 1; });79 EXPECT_TRUE(C.has_value());80 EXPECT_EQ(4, *C);81}82 83TEST(TransformTest, MoveTransformStd) {84 using llvm::CountCopyAndMove;85 86 std::optional<CountCopyAndMove> A;87 88 CountCopyAndMove::ResetCounts();89 std::optional<int> B = llvm::transformOptional(90 std::move(A), [&](const CountCopyAndMove &M) { return M.val + 2; });91 EXPECT_FALSE(B.has_value());92 EXPECT_EQ(0, CountCopyAndMove::TotalCopies());93 EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);94 EXPECT_EQ(0, CountCopyAndMove::MoveAssignments);95 EXPECT_EQ(0, CountCopyAndMove::Destructions);96 97 A = CountCopyAndMove(5);98 CountCopyAndMove::ResetCounts();99 std::optional<int> C = llvm::transformOptional(100 std::move(A), [&](const CountCopyAndMove &M) { return M.val + 2; });101 EXPECT_TRUE(C.has_value());102 EXPECT_EQ(7, *C);103 EXPECT_EQ(0, CountCopyAndMove::TotalCopies());104 EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);105 EXPECT_EQ(0, CountCopyAndMove::MoveAssignments);106 EXPECT_EQ(0, CountCopyAndMove::Destructions);107}108 109TEST(TransformTest, TransformLlvm) {110 std::optional<int> A;111 112 std::optional<int> B =113 llvm::transformOptional(A, [&](int N) { return N + 1; });114 EXPECT_FALSE(B.has_value());115 116 A = 3;117 std::optional<int> C =118 llvm::transformOptional(A, [&](int N) { return N + 1; });119 EXPECT_TRUE(C.has_value());120 EXPECT_EQ(4, *C);121}122 123TEST(TransformTest, MoveTransformLlvm) {124 using llvm::CountCopyAndMove;125 126 std::optional<CountCopyAndMove> A;127 128 CountCopyAndMove::ResetCounts();129 std::optional<int> B = llvm::transformOptional(130 std::move(A), [&](const CountCopyAndMove &M) { return M.val + 2; });131 EXPECT_FALSE(B.has_value());132 EXPECT_EQ(0, CountCopyAndMove::TotalCopies());133 EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);134 EXPECT_EQ(0, CountCopyAndMove::MoveAssignments);135 EXPECT_EQ(0, CountCopyAndMove::Destructions);136 137 A = CountCopyAndMove(5);138 CountCopyAndMove::ResetCounts();139 std::optional<int> C = llvm::transformOptional(140 std::move(A), [&](const CountCopyAndMove &M) { return M.val + 2; });141 EXPECT_TRUE(C.has_value());142 EXPECT_EQ(7, *C);143 EXPECT_EQ(0, CountCopyAndMove::TotalCopies());144 EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);145 EXPECT_EQ(0, CountCopyAndMove::MoveAssignments);146 EXPECT_EQ(0, CountCopyAndMove::Destructions);147}148 149TEST(TransformTest, TransformCategory) {150 struct StructA {151 int x;152 };153 struct StructB : StructA {154 StructB(StructA &&A) : StructA(std::move(A)) {}155 };156 157 std::optional<StructA> A{StructA{}};158 llvm::transformOptional(A, [](auto &&s) {159 EXPECT_FALSE(std::is_rvalue_reference_v<decltype(s)>);160 return StructB{std::move(s)};161 });162 163 llvm::transformOptional(std::move(A), [](auto &&s) {164 EXPECT_TRUE(std::is_rvalue_reference_v<decltype(s)>);165 return StructB{std::move(s)};166 });167}168 169TEST(TransformTest, ToUnderlying) {170 enum E { A1 = 0, B1 = -1 };171 static_assert(llvm::to_underlying(A1) == 0);172 static_assert(llvm::to_underlying(B1) == -1);173 174 enum E2 : unsigned char { A2 = 0, B2 };175 static_assert(176 std::is_same_v<unsigned char, decltype(llvm::to_underlying(A2))>);177 static_assert(llvm::to_underlying(A2) == 0);178 static_assert(llvm::to_underlying(B2) == 1);179 180 enum class E3 { A3 = -1, B3 };181 static_assert(std::is_same_v<int, decltype(llvm::to_underlying(E3::A3))>);182 static_assert(llvm::to_underlying(E3::A3) == -1);183 static_assert(llvm::to_underlying(E3::B3) == 0);184}185 186TEST(STLForwardCompatTest, IdentityCxx20) {187 llvm::identity identity;188 189 // Test with an lvalue.190 int X = 42;191 int &Y = identity(X);192 EXPECT_EQ(&X, &Y);193 194 // Test with a const lvalue.195 const int CX = 10;196 const int &CY = identity(CX);197 EXPECT_EQ(&CX, &CY);198 199 // Test with an rvalue.200 EXPECT_EQ(identity(123), 123);201 202 // Test perfect forwarding.203 static_assert(std::is_same_v<int &, decltype(identity(X))>);204 static_assert(std::is_same_v<const int &, decltype(identity(CX))>);205 static_assert(std::is_same_v<int &&, decltype(identity(int(5)))>);206}207 208} // namespace209