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