1 //===----------------------------------------------------------------------===//
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 // Triggers a Clang assertion: llvm.org/PR45879
10 // UNSUPPORTED: clang-13, clang-14, clang-15
11
12 // <tuple>
13
14 // template <class... Types> class tuple;
15
16 // template <class... UTypes>
17 // tuple& operator=(const tuple<UTypes...>& u);
18
19 // UNSUPPORTED: c++03
20
21 #include <tuple>
22 #include <string>
23 #include <cassert>
24
25 #include "test_macros.h"
26
27 struct B {
28 int id_;
29
BB30 constexpr explicit B(int i = 0) : id_(i) {}
31 };
32
33 struct D : B {
DD34 constexpr explicit D(int i = 0) : B(i) {}
35 };
36
37 struct NonAssignable {
38 NonAssignable& operator=(NonAssignable const&) = delete;
39 NonAssignable& operator=(NonAssignable&&) = delete;
40 };
41
42 struct NothrowCopyAssignable {
43 NothrowCopyAssignable(NothrowCopyAssignable const&) = delete;
operator =NothrowCopyAssignable44 NothrowCopyAssignable& operator=(NothrowCopyAssignable const&) noexcept { return *this; }
45 };
46
47 struct PotentiallyThrowingCopyAssignable {
48 PotentiallyThrowingCopyAssignable(PotentiallyThrowingCopyAssignable const&) = delete;
operator =PotentiallyThrowingCopyAssignable49 PotentiallyThrowingCopyAssignable& operator=(PotentiallyThrowingCopyAssignable const&) { return *this; }
50 };
51
52 TEST_CONSTEXPR_CXX20
test()53 bool test()
54 {
55 {
56 typedef std::tuple<long> T0;
57 typedef std::tuple<long long> T1;
58 T0 t0(2);
59 T1 t1;
60 t1 = t0;
61 assert(std::get<0>(t1) == 2);
62 }
63 {
64 typedef std::tuple<long, char> T0;
65 typedef std::tuple<long long, int> T1;
66 T0 t0(2, 'a');
67 T1 t1;
68 t1 = t0;
69 assert(std::get<0>(t1) == 2);
70 assert(std::get<1>(t1) == int('a'));
71 }
72 {
73 typedef std::tuple<long, char, D> T0;
74 typedef std::tuple<long long, int, B> T1;
75 T0 t0(2, 'a', D(3));
76 T1 t1;
77 t1 = t0;
78 assert(std::get<0>(t1) == 2);
79 assert(std::get<1>(t1) == int('a'));
80 assert(std::get<2>(t1).id_ == 3);
81 }
82 {
83 D d(3);
84 D d2(2);
85 typedef std::tuple<long, char, D&> T0;
86 typedef std::tuple<long long, int, B&> T1;
87 T0 t0(2, 'a', d2);
88 T1 t1(1, 'b', d);
89 t1 = t0;
90 assert(std::get<0>(t1) == 2);
91 assert(std::get<1>(t1) == int('a'));
92 assert(std::get<2>(t1).id_ == 2);
93 }
94 {
95 // Test that tuple evaluates correctly applies an lvalue reference
96 // before evaluating is_assignable (i.e. 'is_assignable<int&, int&>')
97 // instead of evaluating 'is_assignable<int&&, int&>' which is false.
98 int x = 42;
99 int y = 43;
100 std::tuple<int&&> t(std::move(x));
101 std::tuple<int&> t2(y);
102 t = t2;
103 assert(std::get<0>(t) == 43);
104 assert(&std::get<0>(t) == &x);
105 }
106 return true;
107 }
108
main(int,char **)109 int main(int, char**)
110 {
111 test();
112 #if TEST_STD_VER >= 20
113 static_assert(test());
114 #endif
115
116 {
117 using T = std::tuple<int, NonAssignable>;
118 using U = std::tuple<NonAssignable, int>;
119 static_assert(!std::is_assignable<T&, U const&>::value, "");
120 static_assert(!std::is_assignable<U&, T const&>::value, "");
121 }
122 {
123 typedef std::tuple<NothrowCopyAssignable, long> T0;
124 typedef std::tuple<NothrowCopyAssignable, int> T1;
125 static_assert(std::is_nothrow_assignable<T0&, T1 const&>::value, "");
126 }
127 {
128 typedef std::tuple<PotentiallyThrowingCopyAssignable, long> T0;
129 typedef std::tuple<PotentiallyThrowingCopyAssignable, int> T1;
130 static_assert(std::is_assignable<T0&, T1 const&>::value, "");
131 static_assert(!std::is_nothrow_assignable<T0&, T1 const&>::value, "");
132 }
133
134 return 0;
135 }
136