llvm.org GIT mirror llvm / a28eda7
Allow llvm::Optional to work with types without default constructors. This generalizes Optional to require less from the T type by using aligned storage for backing & placement new/deleting the T into it when necessary. Also includes unit tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175580 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 6 years ago
3 changed file(s) with 221 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
1616 #define LLVM_ADT_OPTIONAL_H
1717
1818 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/AlignOf.h"
1920 #include
2021
2122 #if LLVM_HAS_RVALUE_REFERENCES
2627
2728 template
2829 class Optional {
29 T x;
30 AlignedCharArrayUnion storage;
3031 bool hasVal;
3132 public:
32 explicit Optional() : x(), hasVal(false) {}
33 Optional(const T &y) : x(y), hasVal(true) {}
33 explicit Optional() : hasVal(false) {}
34 Optional(const T &y) : hasVal(true) {
35 new (storage.buffer) T(y);
36 }
37 Optional(const Optional &O) : hasVal(O.hasVal) {
38 if (hasVal)
39 new (storage.buffer) T(*O);
40 }
3441
3542 #if LLVM_HAS_RVALUE_REFERENCES
36 Optional(T &&y) : x(std::forward(y)), hasVal(true) {}
43 Optional(T &&y) : hasVal(true) {
44 new (storage.buffer) T(std::forward(y));
45 }
3746 #endif
3847
3948 static inline Optional create(const T* y) {
4150 }
4251
4352 Optional &operator=(const T &y) {
44 x = y;
45 hasVal = true;
53 if (hasVal)
54 **this = y;
55 else {
56 new (storage.buffer) T(y);
57 hasVal = true;
58 }
4659 return *this;
4760 }
61
62 Optional &operator=(const Optional &O) {
63 if (!O)
64 Reset();
65 else
66 *this = *O;
67 return *this;
68 }
69
70 void Reset() {
71 if (hasVal) {
72 (*this)->~T();
73 hasVal = false;
74 }
75 }
76
77 ~Optional() {
78 Reset();
79 }
4880
49 const T* getPointer() const { assert(hasVal); return &x; }
50 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; }
81 const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); }
82 T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); }
83 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
84 T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
5185
5286 operator bool() const { return hasVal; }
5387 bool hasValue() const { return hasVal; }
5488 const T* operator->() const { return getPointer(); }
55 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; }
89 T* operator->() { return getPointer(); }
90 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
91 T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
5692
5793 #if LLVM_HAS_RVALUE_REFERENCE_THIS
58 T&& getValue() && { assert(hasVal); return std::move(x); }
59 T&& operator*() && { assert(hasVal); return std::move(x); }
94 T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
95 T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
6096 #endif
6197 };
6298
1818 IntervalMapTest.cpp
1919 IntrusiveRefCntPtrTest.cpp
2020 MapVectorTest.cpp
21 OptionalTest.cpp
2122 PackedVectorTest.cpp
2223 SCCIteratorTest.cpp
2324 SmallPtrSetTest.cpp
0 //===- llvm/unittest/ADT/OptionalTest.cpp - Optional unit tests -----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "gtest/gtest.h"
10 #include "llvm/ADT/Optional.h"
11 using namespace llvm;
12
13 namespace {
14
15 struct NonDefaultConstructible {
16 static unsigned CopyConstructions;
17 static unsigned Destructions;
18 static unsigned CopyAssignments;
19 explicit NonDefaultConstructible(int) {
20 }
21 NonDefaultConstructible(const NonDefaultConstructible&) {
22 ++CopyConstructions;
23 }
24 NonDefaultConstructible &operator=(const NonDefaultConstructible&) {
25 ++CopyAssignments;
26 return *this;
27 }
28 ~NonDefaultConstructible() {
29 ++Destructions;
30 }
31 static void ResetCounts() {
32 CopyConstructions = 0;
33 Destructions = 0;
34 CopyAssignments = 0;
35 }
36 };
37
38 unsigned NonDefaultConstructible::CopyConstructions = 0;
39 unsigned NonDefaultConstructible::Destructions = 0;
40 unsigned NonDefaultConstructible::CopyAssignments = 0;
41
42 // Test fixture
43 class OptionalTest : public testing::Test {
44 };
45
46 TEST_F(OptionalTest, NonDefaultConstructibleTest) {
47 Optional O;
48 EXPECT_FALSE(O);
49 }
50
51 TEST_F(OptionalTest, ResetTest) {
52 NonDefaultConstructible::ResetCounts();
53 Optional O(NonDefaultConstructible(3));
54 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
55 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
56 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
57 NonDefaultConstructible::ResetCounts();
58 O.Reset();
59 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
60 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
61 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
62 }
63
64 TEST_F(OptionalTest, InitializationLeakTest) {
65 NonDefaultConstructible::ResetCounts();
66 Optional(NonDefaultConstructible(3));
67 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
68 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
69 EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
70 }
71
72 TEST_F(OptionalTest, CopyConstructionTest) {
73 NonDefaultConstructible::ResetCounts();
74 {
75 Optional A(NonDefaultConstructible(3));
76 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
77 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
78 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
79 NonDefaultConstructible::ResetCounts();
80 Optional B(A);
81 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
82 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
83 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
84 NonDefaultConstructible::ResetCounts();
85 }
86 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
87 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
88 EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
89 }
90
91 TEST_F(OptionalTest, ConstructingCopyAssignmentTest) {
92 NonDefaultConstructible::ResetCounts();
93 {
94 Optional A(NonDefaultConstructible(3));
95 Optional B;
96 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
97 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
98 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
99 NonDefaultConstructible::ResetCounts();
100 B = A;
101 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
102 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
103 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
104 NonDefaultConstructible::ResetCounts();
105 }
106 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
107 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
108 EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
109 }
110
111 TEST_F(OptionalTest, CopyingCopyAssignmentTest) {
112 NonDefaultConstructible::ResetCounts();
113 {
114 Optional A(NonDefaultConstructible(3));
115 Optional B(NonDefaultConstructible(4));
116 EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions);
117 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
118 EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
119 NonDefaultConstructible::ResetCounts();
120 B = A;
121 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
122 EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments);
123 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
124 NonDefaultConstructible::ResetCounts();
125 }
126 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
127 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
128 EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
129 }
130
131 TEST_F(OptionalTest, DeletingCopyAssignmentTest) {
132 NonDefaultConstructible::ResetCounts();
133 {
134 Optional A;
135 Optional B(NonDefaultConstructible(3));
136 EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
137 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
138 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
139 NonDefaultConstructible::ResetCounts();
140 B = A;
141 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
142 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
143 EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
144 NonDefaultConstructible::ResetCounts();
145 }
146 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
147 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
148 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
149 }
150
151 TEST_F(OptionalTest, NullCopyConstructionTest) {
152 NonDefaultConstructible::ResetCounts();
153 {
154 Optional A;
155 Optional B;
156 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
157 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
158 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
159 NonDefaultConstructible::ResetCounts();
160 B = A;
161 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
162 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
163 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
164 NonDefaultConstructible::ResetCounts();
165 }
166 EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
167 EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
168 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
169 }
170
171 } // end anonymous namespace
172