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 <tuple>
16 #include <string>
17 
18 #include "test_macros.h"
19 
20 template <class Tp>
21 struct ConvertsTo {
22   using RawTp = typename std::remove_cv< typename std::remove_reference<Tp>::type>::type;
23 
operator TpConvertsTo24   operator Tp() const {
25     return static_cast<Tp>(value);
26   }
27 
28   mutable RawTp value;
29 };
30 
31 struct Base {};
32 struct Derived : Base {};
33 
34 template <class T> struct CannotDeduce {
35  using type = T;
36 };
37 
38 template <class ...Args>
F(typename CannotDeduce<std::tuple<Args...>>::type const &)39 void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {}
40 
41 
f()42 void f() {
43 #if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary)
44   // Test that we emit our diagnostic from the library.
45   // expected-error@tuple:* 8 {{Attempted construction of reference element binds to a temporary whose lifetime has ended}}
46 
47   // Good news everybody! Clang now diagnoses this for us!
48   // expected-error@tuple:* 0+ {{reference member '__value_' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
49 
50   {
51     F<int, const std::string&>(std::make_tuple(1, "abc")); // expected-note 1 {{requested here}}
52   }
53   {
54     std::tuple<int, const std::string&> t(1, "a"); // expected-note 1 {{requested here}}
55   }
56   {
57     F<int, const std::string&>(std::tuple<int, const std::string&>(1, "abc")); // expected-note 1 {{requested here}}
58   }
59   {
60     ConvertsTo<int&> ct;
61     std::tuple<const long&, int> t(ct, 42); // expected-note {{requested here}}
62   }
63   {
64     ConvertsTo<int> ct;
65     std::tuple<int const&, void*> t(ct, nullptr); // expected-note {{requested here}}
66   }
67   {
68     ConvertsTo<Derived> ct;
69     std::tuple<Base const&, int> t(ct, 42); // expected-note {{requested here}}
70   }
71   {
72     std::allocator<int> alloc;
73     std::tuple<std::string &&> t2("hello"); // expected-note {{requested here}}
74     std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}}
75   }
76 #else
77 #error force failure
78 // expected-error@-1 {{force failure}}
79 #endif
80 }
81