• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 // UNSUPPORTED: c++98, c++03, c++11, c++14
12 
13 // XFAIL: availability=macosx10.13
14 // XFAIL: availability=macosx10.12
15 // XFAIL: availability=macosx10.11
16 // XFAIL: availability=macosx10.10
17 // XFAIL: availability=macosx10.9
18 // XFAIL: availability=macosx10.8
19 // XFAIL: availability=macosx10.7
20 
21 // <variant>
22 
23 // template <class ...Types> class variant;
24 
25 // template <class T>
26 // variant& operator=(T&&) noexcept(see below);
27 
28 #include <cassert>
29 #include <string>
30 #include <type_traits>
31 #include <variant>
32 
33 #include "test_macros.h"
34 #include "variant_test_helpers.hpp"
35 
36 namespace MetaHelpers {
37 
38 struct Dummy {
39   Dummy() = default;
40 };
41 
42 struct ThrowsCtorT {
ThrowsCtorTMetaHelpers::ThrowsCtorT43   ThrowsCtorT(int) noexcept(false) {}
operator =MetaHelpers::ThrowsCtorT44   ThrowsCtorT &operator=(int) noexcept { return *this; }
45 };
46 
47 struct ThrowsAssignT {
ThrowsAssignTMetaHelpers::ThrowsAssignT48   ThrowsAssignT(int) noexcept {}
operator =MetaHelpers::ThrowsAssignT49   ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
50 };
51 
52 struct NoThrowT {
NoThrowTMetaHelpers::NoThrowT53   NoThrowT(int) noexcept {}
operator =MetaHelpers::NoThrowT54   NoThrowT &operator=(int) noexcept { return *this; }
55 };
56 
57 } // namespace MetaHelpers
58 
59 namespace RuntimeHelpers {
60 #ifndef TEST_HAS_NO_EXCEPTIONS
61 
62 struct ThrowsCtorT {
63   int value;
ThrowsCtorTRuntimeHelpers::ThrowsCtorT64   ThrowsCtorT() : value(0) {}
ThrowsCtorTRuntimeHelpers::ThrowsCtorT65   ThrowsCtorT(int) noexcept(false) { throw 42; }
operator =RuntimeHelpers::ThrowsCtorT66   ThrowsCtorT &operator=(int v) noexcept {
67     value = v;
68     return *this;
69   }
70 };
71 
72 struct MoveCrashes {
73   int value;
MoveCrashesRuntimeHelpers::MoveCrashes74   MoveCrashes(int v = 0) noexcept : value{v} {}
MoveCrashesRuntimeHelpers::MoveCrashes75   MoveCrashes(MoveCrashes &&) noexcept { assert(false); }
operator =RuntimeHelpers::MoveCrashes76   MoveCrashes &operator=(MoveCrashes &&) noexcept { assert(false); return *this; }
operator =RuntimeHelpers::MoveCrashes77   MoveCrashes &operator=(int v) noexcept {
78     value = v;
79     return *this;
80   }
81 };
82 
83 struct ThrowsCtorTandMove {
84   int value;
ThrowsCtorTandMoveRuntimeHelpers::ThrowsCtorTandMove85   ThrowsCtorTandMove() : value(0) {}
ThrowsCtorTandMoveRuntimeHelpers::ThrowsCtorTandMove86   ThrowsCtorTandMove(int) noexcept(false) { throw 42; }
ThrowsCtorTandMoveRuntimeHelpers::ThrowsCtorTandMove87   ThrowsCtorTandMove(ThrowsCtorTandMove &&) noexcept(false) { assert(false); }
operator =RuntimeHelpers::ThrowsCtorTandMove88   ThrowsCtorTandMove &operator=(int v) noexcept {
89     value = v;
90     return *this;
91   }
92 };
93 
94 struct ThrowsAssignT {
95   int value;
ThrowsAssignTRuntimeHelpers::ThrowsAssignT96   ThrowsAssignT() : value(0) {}
ThrowsAssignTRuntimeHelpers::ThrowsAssignT97   ThrowsAssignT(int v) noexcept : value(v) {}
operator =RuntimeHelpers::ThrowsAssignT98   ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
99 };
100 
101 struct NoThrowT {
102   int value;
NoThrowTRuntimeHelpers::NoThrowT103   NoThrowT() : value(0) {}
NoThrowTRuntimeHelpers::NoThrowT104   NoThrowT(int v) noexcept : value(v) {}
operator =RuntimeHelpers::NoThrowT105   NoThrowT &operator=(int v) noexcept {
106     value = v;
107     return *this;
108   }
109 };
110 
111 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
112 } // namespace RuntimeHelpers
113 
test_T_assignment_noexcept()114 void test_T_assignment_noexcept() {
115   using namespace MetaHelpers;
116   {
117     using V = std::variant<Dummy, NoThrowT>;
118     static_assert(std::is_nothrow_assignable<V, int>::value, "");
119   }
120   {
121     using V = std::variant<Dummy, ThrowsCtorT>;
122     static_assert(!std::is_nothrow_assignable<V, int>::value, "");
123   }
124   {
125     using V = std::variant<Dummy, ThrowsAssignT>;
126     static_assert(!std::is_nothrow_assignable<V, int>::value, "");
127   }
128 }
129 
test_T_assignment_sfinae()130 void test_T_assignment_sfinae() {
131   {
132     using V = std::variant<long, unsigned>;
133     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
134   }
135   {
136     using V = std::variant<std::string, std::string>;
137     static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
138   }
139   {
140     using V = std::variant<std::string, void *>;
141     static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
142   }
143 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
144   {
145     using V = std::variant<int, int &&>;
146     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
147   }
148   {
149     using V = std::variant<int, const int &>;
150     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
151   }
152 #endif // TEST_VARIANT_HAS_NO_REFERENCES
153 }
154 
test_T_assignment_basic()155 void test_T_assignment_basic() {
156   {
157     std::variant<int> v(43);
158     v = 42;
159     assert(v.index() == 0);
160     assert(std::get<0>(v) == 42);
161   }
162   {
163     std::variant<int, long> v(43l);
164     v = 42;
165     assert(v.index() == 0);
166     assert(std::get<0>(v) == 42);
167     v = 43l;
168     assert(v.index() == 1);
169     assert(std::get<1>(v) == 43);
170   }
171 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
172   {
173     using V = std::variant<int &, int &&, long>;
174     int x = 42;
175     V v(43l);
176     v = x;
177     assert(v.index() == 0);
178     assert(&std::get<0>(v) == &x);
179     v = std::move(x);
180     assert(v.index() == 1);
181     assert(&std::get<1>(v) == &x);
182     // 'long' is selected by FUN(const int &) since 'const int &' cannot bind
183     // to 'int&'.
184     const int &cx = x;
185     v = cx;
186     assert(v.index() == 2);
187     assert(std::get<2>(v) == 42);
188   }
189 #endif // TEST_VARIANT_HAS_NO_REFERENCES
190 }
191 
test_T_assignment_performs_construction()192 void test_T_assignment_performs_construction() {
193   using namespace RuntimeHelpers;
194 #ifndef TEST_HAS_NO_EXCEPTIONS
195   {
196     using V = std::variant<std::string, ThrowsCtorT>;
197     V v(std::in_place_type<std::string>, "hello");
198     try {
199       v = 42;
200       assert(false);
201     } catch (...) { /* ... */
202     }
203     assert(v.index() == 0);
204     assert(std::get<0>(v) == "hello");
205   }
206   {
207     using V = std::variant<ThrowsAssignT, std::string>;
208     V v(std::in_place_type<std::string>, "hello");
209     v = 42;
210     assert(v.index() == 0);
211     assert(std::get<0>(v).value == 42);
212   }
213 #endif // TEST_HAS_NO_EXCEPTIONS
214 }
215 
test_T_assignment_performs_assignment()216 void test_T_assignment_performs_assignment() {
217   using namespace RuntimeHelpers;
218 #ifndef TEST_HAS_NO_EXCEPTIONS
219   {
220     using V = std::variant<ThrowsCtorT>;
221     V v;
222     v = 42;
223     assert(v.index() == 0);
224     assert(std::get<0>(v).value == 42);
225   }
226   {
227     using V = std::variant<ThrowsCtorT, std::string>;
228     V v;
229     v = 42;
230     assert(v.index() == 0);
231     assert(std::get<0>(v).value == 42);
232   }
233   {
234     using V = std::variant<ThrowsAssignT>;
235     V v(100);
236     try {
237       v = 42;
238       assert(false);
239     } catch (...) { /* ... */
240     }
241     assert(v.index() == 0);
242     assert(std::get<0>(v).value == 100);
243   }
244   {
245     using V = std::variant<std::string, ThrowsAssignT>;
246     V v(100);
247     try {
248       v = 42;
249       assert(false);
250     } catch (...) { /* ... */
251     }
252     assert(v.index() == 1);
253     assert(std::get<1>(v).value == 100);
254   }
255 #endif // TEST_HAS_NO_EXCEPTIONS
256 }
257 
main()258 int main() {
259   test_T_assignment_basic();
260   test_T_assignment_performs_construction();
261   test_T_assignment_performs_assignment();
262   test_T_assignment_noexcept();
263   test_T_assignment_sfinae();
264 }
265