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