1 //===- llvm/unittest/ADT/OptionalTest.cpp - Optional unit tests -----------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/Optional.h" 10 #include "llvm/ADT/SmallString.h" 11 #include "llvm/ADT/StringMap.h" 12 #include "llvm/Support/raw_ostream.h" 13 #include "gtest/gtest-spi.h" 14 #include "gtest/gtest.h" 15 16 #include <array> 17 18 19 using namespace llvm; 20 21 static_assert(std::is_trivially_copyable<Optional<int>>::value, 22 "trivially copyable"); 23 24 static_assert(std::is_trivially_copyable<Optional<std::array<int, 3>>>::value, 25 "trivially copyable"); 26 27 void OptionalWorksInConstexpr() { 28 constexpr auto x1 = Optional<int>(); 29 constexpr Optional<int> x2{}; 30 static_assert(!x1.has_value() && !x2.has_value(), 31 "Default construction and hasValue() are contexpr"); 32 static_assert(!x1.has_value() && !x2.has_value(), 33 "Default construction and hasValue() are contexpr"); 34 constexpr auto y1 = Optional<int>(3); 35 constexpr Optional<int> y2{3}; 36 static_assert(y1.value() == y2.value() && y1.value() == 3, 37 "Construction with value and getValue() are constexpr"); 38 static_assert(y1.value() == y2.value() && y1.value() == 3, 39 "Construction with value and getValue() are constexpr"); 40 static_assert(Optional<int>{3} >= 2 && Optional<int>{1} < Optional<int>{2}, 41 "Comparisons work in constexpr"); 42 } 43 44 namespace { 45 46 struct NonDefaultConstructible { 47 static unsigned CopyConstructions; 48 static unsigned Destructions; 49 static unsigned CopyAssignments; 50 explicit NonDefaultConstructible(int) { 51 } 52 NonDefaultConstructible(const NonDefaultConstructible&) { 53 ++CopyConstructions; 54 } 55 NonDefaultConstructible &operator=(const NonDefaultConstructible&) { 56 ++CopyAssignments; 57 return *this; 58 } 59 ~NonDefaultConstructible() { 60 ++Destructions; 61 } 62 static void ResetCounts() { 63 CopyConstructions = 0; 64 Destructions = 0; 65 CopyAssignments = 0; 66 } 67 }; 68 69 unsigned NonDefaultConstructible::CopyConstructions = 0; 70 unsigned NonDefaultConstructible::Destructions = 0; 71 unsigned NonDefaultConstructible::CopyAssignments = 0; 72 73 static_assert( 74 !std::is_trivially_copyable<Optional<NonDefaultConstructible>>::value, 75 "not trivially copyable"); 76 77 TEST(OptionalTest, NonDefaultConstructibleTest) { 78 Optional<NonDefaultConstructible> O; 79 EXPECT_FALSE(O); 80 } 81 82 TEST(OptionalTest, ResetTest) { 83 NonDefaultConstructible::ResetCounts(); 84 Optional<NonDefaultConstructible> O(NonDefaultConstructible(3)); 85 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 86 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 87 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 88 NonDefaultConstructible::ResetCounts(); 89 O.reset(); 90 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 91 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 92 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 93 } 94 95 TEST(OptionalTest, InitializationLeakTest) { 96 NonDefaultConstructible::ResetCounts(); 97 Optional<NonDefaultConstructible>(NonDefaultConstructible(3)); 98 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 99 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 100 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 101 } 102 103 TEST(OptionalTest, CopyConstructionTest) { 104 NonDefaultConstructible::ResetCounts(); 105 { 106 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 107 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 108 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 109 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 110 NonDefaultConstructible::ResetCounts(); 111 Optional<NonDefaultConstructible> B(A); 112 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 113 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 114 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 115 NonDefaultConstructible::ResetCounts(); 116 } 117 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 118 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 119 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 120 } 121 122 TEST(OptionalTest, ConstructingCopyAssignmentTest) { 123 NonDefaultConstructible::ResetCounts(); 124 { 125 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 126 Optional<NonDefaultConstructible> B; 127 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 128 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 129 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 130 NonDefaultConstructible::ResetCounts(); 131 B = A; 132 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 133 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 134 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 135 NonDefaultConstructible::ResetCounts(); 136 } 137 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 138 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 139 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 140 } 141 142 TEST(OptionalTest, CopyingCopyAssignmentTest) { 143 NonDefaultConstructible::ResetCounts(); 144 { 145 Optional<NonDefaultConstructible> A(NonDefaultConstructible(3)); 146 Optional<NonDefaultConstructible> B(NonDefaultConstructible(4)); 147 EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions); 148 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 149 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 150 NonDefaultConstructible::ResetCounts(); 151 B = A; 152 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 153 EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments); 154 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 155 NonDefaultConstructible::ResetCounts(); 156 } 157 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 158 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 159 EXPECT_EQ(2u, NonDefaultConstructible::Destructions); 160 } 161 162 TEST(OptionalTest, DeletingCopyAssignmentTest) { 163 NonDefaultConstructible::ResetCounts(); 164 { 165 Optional<NonDefaultConstructible> A; 166 Optional<NonDefaultConstructible> B(NonDefaultConstructible(3)); 167 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions); 168 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 169 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 170 NonDefaultConstructible::ResetCounts(); 171 B = A; 172 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 173 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 174 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 175 NonDefaultConstructible::ResetCounts(); 176 } 177 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 178 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 179 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 180 } 181 182 TEST(OptionalTest, NullCopyConstructionTest) { 183 NonDefaultConstructible::ResetCounts(); 184 { 185 Optional<NonDefaultConstructible> A; 186 Optional<NonDefaultConstructible> B; 187 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 188 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 189 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 190 NonDefaultConstructible::ResetCounts(); 191 B = A; 192 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 193 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 194 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 195 NonDefaultConstructible::ResetCounts(); 196 } 197 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 198 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 199 EXPECT_EQ(0u, NonDefaultConstructible::Destructions); 200 } 201 202 TEST(OptionalTest, InPlaceConstructionNonDefaultConstructibleTest) { 203 NonDefaultConstructible::ResetCounts(); 204 { Optional<NonDefaultConstructible> A{in_place, 1}; } 205 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions); 206 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments); 207 EXPECT_EQ(1u, NonDefaultConstructible::Destructions); 208 } 209 210 TEST(OptionalTest, GetValueOr) { 211 Optional<int> A; 212 EXPECT_EQ(42, A.value_or(42)); 213 EXPECT_EQ(42, A.getValueOr(42)); 214 215 A = 5; 216 EXPECT_EQ(5, A.value_or(42)); 217 EXPECT_EQ(5, A.getValueOr(42)); 218 } 219 220 struct MultiArgConstructor { 221 int x, y; 222 MultiArgConstructor(int x, int y) : x(x), y(y) {} 223 explicit MultiArgConstructor(int x, bool positive) 224 : x(x), y(positive ? x : -x) {} 225 226 MultiArgConstructor(const MultiArgConstructor &) = delete; 227 MultiArgConstructor(MultiArgConstructor &&) = delete; 228 MultiArgConstructor &operator=(const MultiArgConstructor &) = delete; 229 MultiArgConstructor &operator=(MultiArgConstructor &&) = delete; 230 231 friend bool operator==(const MultiArgConstructor &LHS, 232 const MultiArgConstructor &RHS) { 233 return LHS.x == RHS.x && LHS.y == RHS.y; 234 } 235 236 static unsigned Destructions; 237 ~MultiArgConstructor() { 238 ++Destructions; 239 } 240 static void ResetCounts() { 241 Destructions = 0; 242 } 243 }; 244 unsigned MultiArgConstructor::Destructions = 0; 245 246 static_assert(!std::is_trivially_copyable<Optional<MultiArgConstructor>>::value, 247 "not trivially copyable"); 248 249 TEST(OptionalTest, Emplace) { 250 MultiArgConstructor::ResetCounts(); 251 Optional<MultiArgConstructor> A; 252 253 A.emplace(1, 2); 254 EXPECT_TRUE(A.has_value()); 255 EXPECT_TRUE(A.has_value()); 256 EXPECT_EQ(1, A->x); 257 EXPECT_EQ(2, A->y); 258 EXPECT_EQ(0u, MultiArgConstructor::Destructions); 259 260 A.emplace(5, false); 261 EXPECT_TRUE(A.has_value()); 262 EXPECT_TRUE(A.has_value()); 263 EXPECT_EQ(5, A->x); 264 EXPECT_EQ(-5, A->y); 265 EXPECT_EQ(1u, MultiArgConstructor::Destructions); 266 } 267 268 TEST(OptionalTest, InPlaceConstructionMultiArgConstructorTest) { 269 MultiArgConstructor::ResetCounts(); 270 { 271 Optional<MultiArgConstructor> A{in_place, 1, 2}; 272 EXPECT_TRUE(A.has_value()); 273 EXPECT_TRUE(A.has_value()); 274 EXPECT_EQ(1, A->x); 275 EXPECT_EQ(2, A->y); 276 Optional<MultiArgConstructor> B{in_place, 5, false}; 277 EXPECT_TRUE(B.has_value()); 278 EXPECT_TRUE(B.has_value()); 279 EXPECT_EQ(5, B->x); 280 EXPECT_EQ(-5, B->y); 281 EXPECT_EQ(0u, MultiArgConstructor::Destructions); 282 } 283 EXPECT_EQ(2u, MultiArgConstructor::Destructions); 284 } 285 286 TEST(OptionalTest, InPlaceConstructionAndEmplaceEquivalentTest) { 287 MultiArgConstructor::ResetCounts(); 288 { 289 Optional<MultiArgConstructor> A{in_place, 1, 2}; 290 Optional<MultiArgConstructor> B; 291 B.emplace(1, 2); 292 EXPECT_EQ(0u, MultiArgConstructor::Destructions); 293 ASSERT_EQ(A, B); 294 } 295 EXPECT_EQ(2u, MultiArgConstructor::Destructions); 296 } 297 298 struct MoveOnly { 299 static unsigned MoveConstructions; 300 static unsigned Destructions; 301 static unsigned MoveAssignments; 302 int val; 303 explicit MoveOnly(int val) : val(val) { 304 } 305 MoveOnly(MoveOnly&& other) { 306 val = other.val; 307 ++MoveConstructions; 308 } 309 MoveOnly &operator=(MoveOnly&& other) { 310 val = other.val; 311 ++MoveAssignments; 312 return *this; 313 } 314 ~MoveOnly() { 315 ++Destructions; 316 } 317 static void ResetCounts() { 318 MoveConstructions = 0; 319 Destructions = 0; 320 MoveAssignments = 0; 321 } 322 }; 323 324 unsigned MoveOnly::MoveConstructions = 0; 325 unsigned MoveOnly::Destructions = 0; 326 unsigned MoveOnly::MoveAssignments = 0; 327 328 static_assert(!std::is_trivially_copyable<Optional<MoveOnly>>::value, 329 "not trivially copyable"); 330 331 TEST(OptionalTest, MoveOnlyNull) { 332 MoveOnly::ResetCounts(); 333 Optional<MoveOnly> O; 334 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 335 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 336 EXPECT_EQ(0u, MoveOnly::Destructions); 337 } 338 339 TEST(OptionalTest, MoveOnlyConstruction) { 340 MoveOnly::ResetCounts(); 341 Optional<MoveOnly> O(MoveOnly(3)); 342 EXPECT_TRUE((bool)O); 343 EXPECT_EQ(3, O->val); 344 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 345 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 346 EXPECT_EQ(1u, MoveOnly::Destructions); 347 } 348 349 TEST(OptionalTest, MoveOnlyMoveConstruction) { 350 Optional<MoveOnly> A(MoveOnly(3)); 351 MoveOnly::ResetCounts(); 352 Optional<MoveOnly> B(std::move(A)); 353 EXPECT_TRUE((bool)A); 354 EXPECT_TRUE((bool)B); 355 EXPECT_EQ(3, B->val); 356 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 357 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 358 EXPECT_EQ(0u, MoveOnly::Destructions); 359 } 360 361 TEST(OptionalTest, MoveOnlyAssignment) { 362 MoveOnly::ResetCounts(); 363 Optional<MoveOnly> O; 364 O = MoveOnly(3); 365 EXPECT_TRUE((bool)O); 366 EXPECT_EQ(3, O->val); 367 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 368 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 369 EXPECT_EQ(1u, MoveOnly::Destructions); 370 } 371 372 TEST(OptionalTest, MoveOnlyInitializingAssignment) { 373 Optional<MoveOnly> A(MoveOnly(3)); 374 Optional<MoveOnly> B; 375 MoveOnly::ResetCounts(); 376 B = std::move(A); 377 EXPECT_TRUE((bool)A); 378 EXPECT_TRUE((bool)B); 379 EXPECT_EQ(3, B->val); 380 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 381 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 382 EXPECT_EQ(0u, MoveOnly::Destructions); 383 } 384 385 TEST(OptionalTest, MoveOnlyNullingAssignment) { 386 Optional<MoveOnly> A; 387 Optional<MoveOnly> B(MoveOnly(3)); 388 MoveOnly::ResetCounts(); 389 B = std::move(A); 390 EXPECT_FALSE((bool)A); 391 EXPECT_FALSE((bool)B); 392 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 393 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 394 EXPECT_EQ(1u, MoveOnly::Destructions); 395 } 396 397 TEST(OptionalTest, MoveOnlyAssigningAssignment) { 398 Optional<MoveOnly> A(MoveOnly(3)); 399 Optional<MoveOnly> B(MoveOnly(4)); 400 MoveOnly::ResetCounts(); 401 B = std::move(A); 402 EXPECT_TRUE((bool)A); 403 EXPECT_TRUE((bool)B); 404 EXPECT_EQ(3, B->val); 405 EXPECT_EQ(0u, MoveOnly::MoveConstructions); 406 EXPECT_EQ(1u, MoveOnly::MoveAssignments); 407 EXPECT_EQ(0u, MoveOnly::Destructions); 408 } 409 410 struct Immovable { 411 static unsigned Constructions; 412 static unsigned Destructions; 413 int val; 414 explicit Immovable(int val) : val(val) { 415 ++Constructions; 416 } 417 ~Immovable() { 418 ++Destructions; 419 } 420 static void ResetCounts() { 421 Constructions = 0; 422 Destructions = 0; 423 } 424 private: 425 // This should disable all move/copy operations. 426 Immovable(Immovable&& other) = delete; 427 }; 428 429 unsigned Immovable::Constructions = 0; 430 unsigned Immovable::Destructions = 0; 431 432 static_assert(!std::is_trivially_copyable<Optional<Immovable>>::value, 433 "not trivially copyable"); 434 435 TEST(OptionalTest, ImmovableEmplace) { 436 Optional<Immovable> A; 437 Immovable::ResetCounts(); 438 A.emplace(4); 439 EXPECT_TRUE((bool)A); 440 EXPECT_EQ(4, A->val); 441 EXPECT_EQ(1u, Immovable::Constructions); 442 EXPECT_EQ(0u, Immovable::Destructions); 443 } 444 445 TEST(OptionalTest, ImmovableInPlaceConstruction) { 446 Immovable::ResetCounts(); 447 Optional<Immovable> A{in_place, 4}; 448 EXPECT_TRUE((bool)A); 449 EXPECT_EQ(4, A->val); 450 EXPECT_EQ(1u, Immovable::Constructions); 451 EXPECT_EQ(0u, Immovable::Destructions); 452 } 453 454 // Craft a class which is_trivially_copyable, but not 455 // is_trivially_copy_constructible. 456 struct NonTCopy { 457 NonTCopy() = default; 458 459 // Delete the volatile copy constructor to engage the "rule of 3" and delete 460 // any unspecified copy assignment or constructor. 461 NonTCopy(volatile NonTCopy const &) = delete; 462 463 // Leave the non-volatile default copy constructor unspecified (deleted by 464 // rule of 3) 465 466 // This template can serve as the copy constructor, but isn't chosen 467 // by =default in a class with a 'NonTCopy' member. 468 template <typename Self = NonTCopy> 469 NonTCopy(Self const &Other) : Val(Other.Val) {} 470 471 NonTCopy &operator=(NonTCopy const &) = default; 472 473 int Val{0}; 474 }; 475 476 #if defined(_MSC_VER) && _MSC_VER >= 1927 && !defined(__clang__) 477 // Currently only true on recent MSVC releases. 478 static_assert(std::is_trivially_copyable<NonTCopy>::value, 479 "Expect NonTCopy to be trivially copyable"); 480 481 static_assert(!std::is_trivially_copy_constructible<NonTCopy>::value, 482 "Expect NonTCopy not to be trivially copy constructible."); 483 #endif // defined(_MSC_VER) && _MSC_VER >= 1927 484 485 TEST(OptionalTest, DeletedCopyConstructor) { 486 487 // Expect compile to fail if 'trivial' version of 488 // optional_detail::OptionalStorage is chosen. 489 using NonTCopyOptT = Optional<NonTCopy>; 490 NonTCopyOptT NonTCopy1; 491 492 // Check that the Optional can be copy constructed. 493 NonTCopyOptT NonTCopy2{NonTCopy1}; 494 495 // Check that the Optional can be copy assigned. 496 NonTCopy1 = NonTCopy2; 497 } 498 499 // Craft a class which is_trivially_copyable, but not 500 // is_trivially_copy_assignable. 501 class NonTAssign { 502 public: 503 NonTAssign() = default; 504 NonTAssign(NonTAssign const &) = default; 505 506 // Delete the volatile copy assignment to engage the "rule of 3" and delete 507 // any unspecified copy assignment or constructor. 508 NonTAssign &operator=(volatile NonTAssign const &) = delete; 509 510 // Leave the non-volatile default copy assignment unspecified (deleted by rule 511 // of 3). 512 513 // This template can serve as the copy assignment, but isn't chosen 514 // by =default in a class with a 'NonTAssign' member. 515 template <typename Self = NonTAssign> 516 NonTAssign &operator=(Self const &Other) { 517 A = Other.A; 518 return *this; 519 } 520 521 int A{0}; 522 }; 523 524 #if defined(_MSC_VER) && _MSC_VER >= 1927 && !defined(__clang__) 525 // Currently only true on recent MSVC releases. 526 static_assert(std::is_trivially_copyable<NonTAssign>::value, 527 "Expect NonTAssign to be trivially copyable"); 528 529 static_assert(!std::is_trivially_copy_assignable<NonTAssign>::value, 530 "Expect NonTAssign not to be trivially assignable."); 531 #endif // defined(_MSC_VER) && _MSC_VER >= 1927 532 533 TEST(OptionalTest, DeletedCopyAssignment) { 534 535 // Expect compile to fail if 'trivial' version of 536 // optional_detail::OptionalStorage is chosen. 537 using NonTAssignOptT = Optional<NonTAssign>; 538 NonTAssignOptT NonTAssign1; 539 540 // Check that the Optional can be copy constructed. 541 NonTAssignOptT NonTAssign2{NonTAssign1}; 542 543 // Check that the Optional can be copy assigned. 544 NonTAssign1 = NonTAssign2; 545 } 546 547 struct NoTMove { 548 NoTMove() = default; 549 NoTMove(NoTMove const &) = default; 550 NoTMove &operator=(NoTMove const &) = default; 551 552 // Delete move constructor / assignment. Compiler should fall-back to the 553 // trivial copy constructor / assignment in the trivial OptionalStorage 554 // specialization. 555 NoTMove(NoTMove &&) = delete; 556 NoTMove &operator=(NoTMove &&) = delete; 557 558 int Val{0}; 559 }; 560 561 TEST(OptionalTest, DeletedMoveConstructor) { 562 using NoTMoveOptT = Optional<NoTMove>; 563 564 NoTMoveOptT NonTMove1; 565 NoTMoveOptT NonTMove2{std::move(NonTMove1)}; 566 567 NonTMove1 = std::move(NonTMove2); 568 569 static_assert( 570 std::is_trivially_copyable<NoTMoveOptT>::value, 571 "Expect Optional<NoTMove> to still use the trivial specialization " 572 "of OptionalStorage despite the deleted move constructor / assignment."); 573 } 574 575 class NoCopyStringMap { 576 public: 577 NoCopyStringMap() = default; 578 579 private: 580 llvm::StringMap<std::unique_ptr<int>> Map; 581 }; 582 583 TEST(OptionalTest, DeletedCopyStringMap) { 584 // Old versions of gcc (7.3 and prior) instantiate the copy constructor when 585 // std::is_trivially_copyable is instantiated. This test will fail 586 // compilation if std::is_trivially_copyable is used in the OptionalStorage 587 // specialization condition by gcc <= 7.3. 588 Optional<NoCopyStringMap> TestInstantiation; 589 } 590 591 TEST(OptionalTest, MoveValueOr) { 592 Optional<MoveOnly> A; 593 594 MoveOnly::ResetCounts(); 595 EXPECT_EQ(42, std::move(A).value_or(MoveOnly(42)).val); 596 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 597 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 598 EXPECT_EQ(2u, MoveOnly::Destructions); 599 600 A = MoveOnly(5); 601 MoveOnly::ResetCounts(); 602 EXPECT_EQ(5, std::move(A).value_or(MoveOnly(42)).val); 603 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 604 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 605 EXPECT_EQ(2u, MoveOnly::Destructions); 606 } 607 608 TEST(OptionalTest, MoveGetValueOr) { 609 Optional<MoveOnly> A; 610 611 MoveOnly::ResetCounts(); 612 EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); 613 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 614 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 615 EXPECT_EQ(2u, MoveOnly::Destructions); 616 617 A = MoveOnly(5); 618 MoveOnly::ResetCounts(); 619 EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); 620 EXPECT_EQ(1u, MoveOnly::MoveConstructions); 621 EXPECT_EQ(0u, MoveOnly::MoveAssignments); 622 EXPECT_EQ(2u, MoveOnly::Destructions); 623 } 624 625 struct EqualTo { 626 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 627 return X == Y; 628 } 629 }; 630 631 struct NotEqualTo { 632 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 633 return X != Y; 634 } 635 }; 636 637 struct Less { 638 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 639 return X < Y; 640 } 641 }; 642 643 struct Greater { 644 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 645 return X > Y; 646 } 647 }; 648 649 struct LessEqual { 650 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 651 return X <= Y; 652 } 653 }; 654 655 struct GreaterEqual { 656 template <typename T, typename U> static bool apply(const T &X, const U &Y) { 657 return X >= Y; 658 } 659 }; 660 661 template <typename OperatorT, typename T> 662 void CheckRelation(const Optional<T> &Lhs, const Optional<T> &Rhs, 663 bool Expected) { 664 EXPECT_EQ(Expected, OperatorT::apply(Lhs, Rhs)); 665 666 if (Lhs) 667 EXPECT_EQ(Expected, OperatorT::apply(*Lhs, Rhs)); 668 else 669 EXPECT_EQ(Expected, OperatorT::apply(None, Rhs)); 670 671 if (Rhs) 672 EXPECT_EQ(Expected, OperatorT::apply(Lhs, *Rhs)); 673 else 674 EXPECT_EQ(Expected, OperatorT::apply(Lhs, None)); 675 } 676 677 struct EqualityMock {}; 678 const Optional<EqualityMock> NoneEq, EqualityLhs((EqualityMock())), 679 EqualityRhs((EqualityMock())); 680 bool IsEqual; 681 682 bool operator==(const EqualityMock &Lhs, const EqualityMock &Rhs) { 683 EXPECT_EQ(&*EqualityLhs, &Lhs); 684 EXPECT_EQ(&*EqualityRhs, &Rhs); 685 return IsEqual; 686 } 687 688 TEST(OptionalTest, OperatorEqual) { 689 CheckRelation<EqualTo>(NoneEq, NoneEq, true); 690 CheckRelation<EqualTo>(NoneEq, EqualityRhs, false); 691 CheckRelation<EqualTo>(EqualityLhs, NoneEq, false); 692 693 IsEqual = false; 694 CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual); 695 IsEqual = true; 696 CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual); 697 } 698 699 TEST(OptionalTest, OperatorNotEqual) { 700 CheckRelation<NotEqualTo>(NoneEq, NoneEq, false); 701 CheckRelation<NotEqualTo>(NoneEq, EqualityRhs, true); 702 CheckRelation<NotEqualTo>(EqualityLhs, NoneEq, true); 703 704 IsEqual = false; 705 CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual); 706 IsEqual = true; 707 CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual); 708 } 709 710 struct InequalityMock {}; 711 const Optional<InequalityMock> NoneIneq, InequalityLhs((InequalityMock())), 712 InequalityRhs((InequalityMock())); 713 bool IsLess; 714 715 bool operator<(const InequalityMock &Lhs, const InequalityMock &Rhs) { 716 EXPECT_EQ(&*InequalityLhs, &Lhs); 717 EXPECT_EQ(&*InequalityRhs, &Rhs); 718 return IsLess; 719 } 720 721 TEST(OptionalTest, OperatorLess) { 722 CheckRelation<Less>(NoneIneq, NoneIneq, false); 723 CheckRelation<Less>(NoneIneq, InequalityRhs, true); 724 CheckRelation<Less>(InequalityLhs, NoneIneq, false); 725 726 IsLess = false; 727 CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess); 728 IsLess = true; 729 CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess); 730 } 731 732 TEST(OptionalTest, OperatorGreater) { 733 CheckRelation<Greater>(NoneIneq, NoneIneq, false); 734 CheckRelation<Greater>(NoneIneq, InequalityRhs, false); 735 CheckRelation<Greater>(InequalityLhs, NoneIneq, true); 736 737 IsLess = false; 738 CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess); 739 IsLess = true; 740 CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess); 741 } 742 743 TEST(OptionalTest, OperatorLessEqual) { 744 CheckRelation<LessEqual>(NoneIneq, NoneIneq, true); 745 CheckRelation<LessEqual>(NoneIneq, InequalityRhs, true); 746 CheckRelation<LessEqual>(InequalityLhs, NoneIneq, false); 747 748 IsLess = false; 749 CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess); 750 IsLess = true; 751 CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess); 752 } 753 754 TEST(OptionalTest, OperatorGreaterEqual) { 755 CheckRelation<GreaterEqual>(NoneIneq, NoneIneq, true); 756 CheckRelation<GreaterEqual>(NoneIneq, InequalityRhs, false); 757 CheckRelation<GreaterEqual>(InequalityLhs, NoneIneq, true); 758 759 IsLess = false; 760 CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess); 761 IsLess = true; 762 CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess); 763 } 764 765 struct ComparableAndStreamable { 766 friend bool operator==(ComparableAndStreamable, 767 ComparableAndStreamable) LLVM_ATTRIBUTE_USED { 768 return true; 769 } 770 771 friend raw_ostream &operator<<(raw_ostream &OS, ComparableAndStreamable) { 772 return OS << "ComparableAndStreamable"; 773 } 774 775 static Optional<ComparableAndStreamable> get() { 776 return ComparableAndStreamable(); 777 } 778 }; 779 780 TEST(OptionalTest, StreamOperator) { 781 auto to_string = [](Optional<ComparableAndStreamable> O) { 782 SmallString<16> S; 783 raw_svector_ostream OS(S); 784 OS << O; 785 return S; 786 }; 787 EXPECT_EQ("ComparableAndStreamable", 788 to_string(ComparableAndStreamable::get())); 789 EXPECT_EQ("None", to_string(None)); 790 } 791 792 struct Comparable { 793 friend bool operator==(Comparable, Comparable) LLVM_ATTRIBUTE_USED { 794 return true; 795 } 796 static Optional<Comparable> get() { return Comparable(); } 797 }; 798 799 TEST(OptionalTest, UseInUnitTests) { 800 // Test that we invoke the streaming operators when pretty-printing values in 801 // EXPECT macros. 802 EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None, ComparableAndStreamable::get()), 803 "Expected equality of these values:\n" 804 " llvm::None\n" 805 " Which is: None\n" 806 " ComparableAndStreamable::get()\n" 807 " Which is: ComparableAndStreamable"); 808 809 // Test that it is still possible to compare objects which do not have a 810 // custom streaming operator. 811 EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None, Comparable::get()), "object"); 812 } 813 814 TEST(OptionalTest, HashValue) { 815 // Check that None, false, and true all hash differently. 816 Optional<bool> B, B0 = false, B1 = true; 817 EXPECT_NE(hash_value(B0), hash_value(B)); 818 EXPECT_NE(hash_value(B1), hash_value(B)); 819 EXPECT_NE(hash_value(B1), hash_value(B0)); 820 821 // Check that None, 0, and 1 all hash differently. 822 Optional<int> I, I0 = 0, I1 = 1; 823 EXPECT_NE(hash_value(I0), hash_value(I)); 824 EXPECT_NE(hash_value(I1), hash_value(I)); 825 EXPECT_NE(hash_value(I1), hash_value(I0)); 826 827 // Check None hash the same way regardless of type. 828 EXPECT_EQ(hash_value(B), hash_value(I)); 829 } 830 831 struct NotTriviallyCopyable { 832 NotTriviallyCopyable(); // Constructor out-of-line. 833 virtual ~NotTriviallyCopyable() = default; 834 Optional<MoveOnly> MO; 835 }; 836 837 TEST(OptionalTest, GCCIsTriviallyMoveConstructibleCompat) { 838 Optional<NotTriviallyCopyable> V; 839 EXPECT_FALSE(V); 840 } 841 842 } // end anonymous namespace 843