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 // UNSUPPORTED: c++03
10
11 // <tuple>
12
13 // See https://llvm.org/PR20855.
14
15 #include <functional>
16 #include <tuple>
17 #include <string>
18 #include <cassert>
19 #include "test_macros.h"
20
21 #if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary)
22 # define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "")
23 # define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "")
24 #else
25 # define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
26 # define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
27 #endif
28
29 template <class Tp>
30 struct ConvertsTo {
31 using RawTp = typename std::remove_cv< typename std::remove_reference<Tp>::type>::type;
32
operator TpConvertsTo33 operator Tp() const {
34 return static_cast<Tp>(value);
35 }
36
37 mutable RawTp value;
38 };
39
40 struct Base {};
41 struct Derived : Base {};
42
43
44 static_assert(std::is_same<decltype("abc"), decltype(("abc"))>::value, "");
45 ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype("abc"));
46 ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype(("abc")));
47 ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, const char*&&);
48
49 ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(int&, const ConvertsTo<int&>&);
50 ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(const int&, ConvertsTo<int&>&);
51 ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(Base&, Derived&);
52
53
54 static_assert(std::is_constructible<int&, std::reference_wrapper<int>>::value, "");
55 static_assert(std::is_constructible<int const&, std::reference_wrapper<int>>::value, "");
56
57 template <class T> struct CannotDeduce {
58 using type = T;
59 };
60
61 template <class ...Args>
F(typename CannotDeduce<std::tuple<Args...>>::type const &)62 void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {}
63
compile_tests()64 void compile_tests() {
65 {
66 F<int, int const&>(std::make_tuple(42, 42));
67 }
68 {
69 F<int, int const&>(std::make_tuple<const int&, const int&>(42, 42));
70 std::tuple<int, int const&> t(std::make_tuple<const int&, const int&>(42, 42));
71 }
72 {
73 auto fn = &F<int, std::string const&>;
74 fn(std::tuple<int, std::string const&>(42, std::string("a")));
75 fn(std::make_tuple(42, std::string("a")));
76 }
77 {
78 Derived d;
79 std::tuple<Base&, Base const&> t(d, d);
80 }
81 {
82 ConvertsTo<int&> ct;
83 std::tuple<int, int&> t(42, ct);
84 }
85 }
86
allocator_tests()87 void allocator_tests() {
88 std::allocator<int> alloc;
89 int x = 42;
90 {
91 std::tuple<int&> t(std::ref(x));
92 assert(&std::get<0>(t) == &x);
93 std::tuple<int&> t1(std::allocator_arg, alloc, std::ref(x));
94 assert(&std::get<0>(t1) == &x);
95 }
96 {
97 auto r = std::ref(x);
98 auto const& cr = r;
99 std::tuple<int&> t(r);
100 assert(&std::get<0>(t) == &x);
101 std::tuple<int&> t1(cr);
102 assert(&std::get<0>(t1) == &x);
103 std::tuple<int&> t2(std::allocator_arg, alloc, r);
104 assert(&std::get<0>(t2) == &x);
105 std::tuple<int&> t3(std::allocator_arg, alloc, cr);
106 assert(&std::get<0>(t3) == &x);
107 }
108 {
109 std::tuple<int const&> t(std::ref(x));
110 assert(&std::get<0>(t) == &x);
111 std::tuple<int const&> t2(std::cref(x));
112 assert(&std::get<0>(t2) == &x);
113 std::tuple<int const&> t3(std::allocator_arg, alloc, std::ref(x));
114 assert(&std::get<0>(t3) == &x);
115 std::tuple<int const&> t4(std::allocator_arg, alloc, std::cref(x));
116 assert(&std::get<0>(t4) == &x);
117 }
118 {
119 auto r = std::ref(x);
120 auto cr = std::cref(x);
121 std::tuple<int const&> t(r);
122 assert(&std::get<0>(t) == &x);
123 std::tuple<int const&> t2(cr);
124 assert(&std::get<0>(t2) == &x);
125 std::tuple<int const&> t3(std::allocator_arg, alloc, r);
126 assert(&std::get<0>(t3) == &x);
127 std::tuple<int const&> t4(std::allocator_arg, alloc, cr);
128 assert(&std::get<0>(t4) == &x);
129 }
130 }
131
132
main(int,char **)133 int main(int, char**) {
134 compile_tests();
135 allocator_tests();
136
137 return 0;
138 }
139