<div dir="ltr">Thanks, Eric.</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 24, 2018 at 3:11 PM, Eric Fiselier <span dir="ltr"><<a href="mailto:eric@efcs.ca" target="_blank">eric@efcs.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Sorry for the breakage. Fixed in r323389.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 24, 2018 at 4:08 PM, Eric Fiselier <span dir="ltr"><<a href="mailto:eric@efcs.ca" target="_blank">eric@efcs.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Looking.</div><div class="m_-4485867114878516831HOEnZb"><div class="m_-4485867114878516831h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 24, 2018 at 3:52 PM, Richard Trieu <span dir="ltr"><<a href="mailto:rtrieu@google.com" target="_blank">rtrieu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Eric,<div><br></div><div>I am getting a build failure after this revision:</div><div><br></div><div><div>llvm/projects/libcxx/include/t<wbr>uple:175:27: error: no return statement in constexpr function</div><div>    static constexpr bool __can_bind_reference() {</div><div>                          ^</div><div>1 error generated.</div><div><br></div><div>It looks like if the #if in __can_bind_reference is false, the function will be empty.  Can you take a look?</div><span class="m_-4485867114878516831m_2537165753472263646HOEnZb"><font color="#888888"><div><br></div><div>Richard</div></font></span><div><div class="m_-4485867114878516831m_2537165753472263646h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 24, 2018 at 2:14 PM, Eric Fiselier via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: ericwf<br>
Date: Wed Jan 24 14:14:01 2018<br>
New Revision: 323380<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=323380&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=323380&view=rev</a><br>
Log:<br>
[libc++] Fix PR20855 -- libc++ incorrectly diagnoses illegal reference binding in std::tuple.<br>
<br>
Summary:<br>
See <a href="https://bugs.llvm.org/show_bug.cgi?id=20855" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_bug<wbr>.cgi?id=20855</a><br>
<br>
Libc++ goes out of it's way to diagnose `std::tuple` constructions which are UB due to lifetime bugs caused by reference creation. For example:<br>
<br>
```<br>
// The 'const std::string&' is created *inside* the tuple constructor, and its lifetime is over before the end of the constructor call.<br>
std::tuple<int, const std::string&> t(std::make_tuple(42, "abc"));<br>
```<br>
<br>
However, we are over-aggressive and we incorrectly diagnose cases such as:<br>
<br>
```<br>
void foo(std::tuple<int const&, int const&> const&);<br>
foo(std::make_tuple(42, 42));<br>
```<br>
<br>
This patch fixes the incorrectly diagnosed cases, as well as converting the diagnostic to use the newly added Clang trait `__reference_binds_to_temporar<wbr>y`. The new trait allows us to diagnose cases we previously couldn't such as:<br>
<br>
```<br>
std::tuple<int, const std::string&> t(42, "abc");<br>
```<br>
<br>
Reviewers: rsmith, mclow.lists<br>
<br>
Reviewed By: rsmith<br>
<br>
Subscribers: cfe-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D41977" rel="noreferrer" target="_blank">https://reviews.llvm.org/D4197<wbr>7</a><br>
<br>
Added:<br>
    libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/tuple.c<wbr>nstr/PR20855_tuple_ref_binding<wbr>_diagnostics.fail.cpp<br>
    libcxx/trunk/test/std/utilitie<wbr>s/tuple/tuple.tuple/tuple.cnst<wbr>r/PR20855_tuple_ref_binding_di<wbr>agnostics.pass.cpp<br>
Removed:<br>
    libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.fail.cpp<br>
    libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.pass.cpp<br>
Modified:<br>
    libcxx/trunk/include/tuple<br>
<br>
Modified: libcxx/trunk/include/tuple<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=323380&r1=323379&r2=323380&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/libcxx/trunk/include/tup<wbr>le?rev=323380&r1=323379&r2=323<wbr>380&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/tuple (original)<br>
+++ libcxx/trunk/include/tuple Wed Jan 24 14:14:01 2018<br>
@@ -173,16 +173,9 @@ class __tuple_leaf<br>
<br>
     template <class _Tp><br>
     static constexpr bool __can_bind_reference() {<br>
-        using _RawTp = typename remove_reference<_Tp>::type;<br>
-        using _RawHp = typename remove_reference<_Hp>::type;<br>
-        using _CheckLValueArg = integral_constant<bool,<br>
-            is_lvalue_reference<_Tp>::valu<wbr>e<br>
-        ||  is_same<_RawTp, reference_wrapper<_RawHp>>::va<wbr>lue<br>
-        ||  is_same<_RawTp, reference_wrapper<typename remove_const<_RawHp>::type>>::<wbr>value<br>
-        >;<br>
-        return  !is_reference<_Hp>::value<br>
-            || (is_lvalue_reference<_Hp>::val<wbr>ue && _CheckLValueArg::value)<br>
-            || (is_rvalue_reference<_Hp>::val<wbr>ue && !is_lvalue_reference<_Tp>::val<wbr>ue);<br>
+#if __has_keyword(__reference_bind<wbr>s_to_temporary)<br>
+      return !__reference_binds_to_temporar<wbr>y(_Hp, _Tp);<br>
+#endif<br>
     }<br>
<br>
     __tuple_leaf& operator=(const __tuple_leaf&);<br>
@@ -224,15 +217,15 @@ public:<br>
         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11<br>
         explicit __tuple_leaf(_Tp&& __t) _NOEXCEPT_((is_nothrow_constru<wbr>ctible<_Hp, _Tp>::value))<br>
             : __value_(_VSTD::forward<_Tp>(_<wbr>_t))<br>
-        {static_assert(__can_bind_refe<wbr>rence<_Tp>(),<br>
-       "Attempted to construct a reference element in a tuple with an rvalue");}<br>
+        {static_assert(__can_bind_refe<wbr>rence<_Tp&&>(),<br>
+       "Attempted construction of reference element binds to a temporary whose lifetime has ended");}<br>
<br>
     template <class _Tp, class _Alloc><br>
         _LIBCPP_INLINE_VISIBILITY<br>
         explicit __tuple_leaf(integral_constant<wbr><int, 0>, const _Alloc&, _Tp&& __t)<br>
             : __value_(_VSTD::forward<_Tp>(_<wbr>_t))<br>
-        {static_assert(__can_bind_refe<wbr>rence<_Tp>(),<br>
-       "Attempted to construct a reference element in a tuple with an rvalue");}<br>
+        {static_assert(__can_bind_refe<wbr>rence<_Tp&&>(),<br>
+       "Attempted construction of reference element binds to a temporary whose lifetime has ended");}<br>
<br>
     template <class _Tp, class _Alloc><br>
         _LIBCPP_INLINE_VISIBILITY<br>
<br>
Removed: libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.fail.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.fail.cpp?rev=323379&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/libcxx/trunk/test/libcxx<wbr>/utilities/tuple/tuple.tuple/d<wbr>iagnose_reference_binding.fail<wbr>.cpp?rev=323379&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.fail.cpp (original)<br>
+++ libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.fail.cpp (removed)<br>
@@ -1,40 +0,0 @@<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is dual licensed under the MIT and the University of Illinois Open<br>
-// Source Licenses. See LICENSE.TXT for details.<br>
-//<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-<br>
-// UNSUPPORTED: c++98, c++03<br>
-<br>
-// <tuple><br>
-<br>
-// Test the diagnostics libc++ generates for invalid reference binding.<br>
-// Libc++ attempts to diagnose the following cases:<br>
-//  * Constructing an lvalue reference from an rvalue.<br>
-//  * Constructing an rvalue reference from an lvalue.<br>
-<br>
-#include <tuple><br>
-#include <string><br>
-<br>
-int main() {<br>
-    std::allocator<void> alloc;<br>
-<br>
-    // expected-error-re@tuple:* 4 {{static_assert failed{{.*}} "Attempted to construct a reference element in a tuple with an rvalue"}}<br>
-<br>
-    // bind lvalue to rvalue<br>
-    std::tuple<int const&> t(42); // expected-note {{requested here}}<br>
-    std::tuple<int const&> t1(std::allocator_arg, alloc, 42); // expected-note {{requested here}}<br>
-    // bind rvalue to constructed non-rvalue<br>
-    std::tuple<std::string &&> t2("hello"); // expected-note {{requested here}}<br>
-    std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}}<br>
-<br>
-    // FIXME: The below warnings may get emitted as an error, a warning, or not emitted at all<br>
-    // depending on the flags used to compile this test.<br>
-  {<br>
-    // expected-warning@tuple:* 0+ {{binding reference member '__value_' to a temporary value}}<br>
-    // expected-error@tuple:* 0+ {{binding reference member '__value_' to a temporary value}}<br>
-  }<br>
-}<br>
<br>
Removed: libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.pass.cpp?rev=323379&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/libcxx/trunk/test/libcxx<wbr>/utilities/tuple/tuple.tuple/d<wbr>iagnose_reference_binding.pass<wbr>.cpp?rev=323379&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.pass.cpp (original)<br>
+++ libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/diagnos<wbr>e_reference_binding.pass.cpp (removed)<br>
@@ -1,71 +0,0 @@<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is dual licensed under the MIT and the University of Illinois Open<br>
-// Source Licenses. See LICENSE.TXT for details.<br>
-//<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-<br>
-// UNSUPPORTED: c++98, c++03<br>
-<br>
-// <tuple><br>
-<br>
-// Test the diagnostics libc++ generates for invalid reference binding.<br>
-// Libc++ attempts to diagnose the following cases:<br>
-//  * Constructing an lvalue reference from an rvalue.<br>
-//  * Constructing an rvalue reference from an lvalue.<br>
-<br>
-#include <tuple><br>
-#include <string><br>
-#include <functional><br>
-#include <cassert><br>
-<br>
-static_assert(std::is_constru<wbr>ctible<int&, std::reference_wrapper<int>>::<wbr>value, "");<br>
-static_assert(std::is_constru<wbr>ctible<int const&, std::reference_wrapper<int>>::<wbr>value, "");<br>
-<br>
-<br>
-int main() {<br>
-    std::allocator<void> alloc;<br>
-    int x = 42;<br>
-    {<br>
-        std::tuple<int&> t(std::ref(x));<br>
-        assert(&std::get<0>(t) == &x);<br>
-        std::tuple<int&> t1(std::allocator_arg, alloc, std::ref(x));<br>
-        assert(&std::get<0>(t1) == &x);<br>
-    }<br>
-    {<br>
-        auto r = std::ref(x);<br>
-        auto const& cr = r;<br>
-        std::tuple<int&> t(r);<br>
-        assert(&std::get<0>(t) == &x);<br>
-        std::tuple<int&> t1(cr);<br>
-        assert(&std::get<0>(t1) == &x);<br>
-        std::tuple<int&> t2(std::allocator_arg, alloc, r);<br>
-        assert(&std::get<0>(t2) == &x);<br>
-        std::tuple<int&> t3(std::allocator_arg, alloc, cr);<br>
-        assert(&std::get<0>(t3) == &x);<br>
-    }<br>
-    {<br>
-        std::tuple<int const&> t(std::ref(x));<br>
-        assert(&std::get<0>(t) == &x);<br>
-        std::tuple<int const&> t2(std::cref(x));<br>
-        assert(&std::get<0>(t2) == &x);<br>
-        std::tuple<int const&> t3(std::allocator_arg, alloc, std::ref(x));<br>
-        assert(&std::get<0>(t3) == &x);<br>
-        std::tuple<int const&> t4(std::allocator_arg, alloc, std::cref(x));<br>
-        assert(&std::get<0>(t4) == &x);<br>
-    }<br>
-    {<br>
-        auto r = std::ref(x);<br>
-        auto cr = std::cref(x);<br>
-        std::tuple<int const&> t(r);<br>
-        assert(&std::get<0>(t) == &x);<br>
-        std::tuple<int const&> t2(cr);<br>
-        assert(&std::get<0>(t2) == &x);<br>
-        std::tuple<int const&> t3(std::allocator_arg, alloc, r);<br>
-        assert(&std::get<0>(t3) == &x);<br>
-        std::tuple<int const&> t4(std::allocator_arg, alloc, cr);<br>
-        assert(&std::get<0>(t4) == &x);<br>
-    }<br>
-}<br>
<br>
Added: libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/tuple.c<wbr>nstr/PR20855_tuple_ref_binding<wbr>_diagnostics.fail.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.fail.cpp?rev=323380&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/libcxx/trunk/test/libcxx<wbr>/utilities/tuple/tuple.tuple/t<wbr>uple.cnstr/PR20855_tuple_ref_b<wbr>inding_diagnostics.fail.cpp?re<wbr>v=323380&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/tuple.c<wbr>nstr/PR20855_tuple_ref_binding<wbr>_diagnostics.fail.cpp (added)<br>
+++ libcxx/trunk/test/libcxx/utili<wbr>ties/tuple/tuple.tuple/tuple.c<wbr>nstr/PR20855_tuple_ref_binding<wbr>_diagnostics.fail.cpp Wed Jan 24 14:14:01 2018<br>
@@ -0,0 +1,80 @@<br>
+// -*- C++ -*-<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03<br>
+<br>
+// <tuple><br>
+<br>
+// See <a href="http://llvm.org/PR20855" rel="noreferrer" target="_blank">llvm.org/PR20855</a><br>
+<br>
+#ifdef __clang__<br>
+#pragma clang diagnostic ignored "-Wdangling-field"<br>
+#endif<br>
+<br>
+#include <tuple><br>
+#include <string><br>
+#include "test_macros.h"<br>
+<br>
+template <class Tp><br>
+struct ConvertsTo {<br>
+  using RawTp = typename std::remove_cv< typename std::remove_reference<Tp>::typ<wbr>e>::type;<br>
+<br>
+  operator Tp() const {<br>
+    return static_cast<Tp>(value);<br>
+  }<br>
+<br>
+  mutable RawTp value;<br>
+};<br>
+<br>
+struct Base {};<br>
+struct Derived : Base {};<br>
+<br>
+template <class T> struct CannotDeduce {<br>
+ using type = T;<br>
+};<br>
+<br>
+template <class ...Args><br>
+void F(typename CannotDeduce<std::tuple<Args..<wbr>.>>::type const&) {}<br>
+<br>
+<br>
+int main() {<br>
+#if TEST_HAS_BUILTIN_IDENTIFIER(__<wbr>reference_binds_to_temporary)<br>
+  // expected-error@tuple:* 8 {{"Attempted construction of reference element binds to a temporary whose lifetime has ended"}}<br>
+  {<br>
+    F<int, const std::string&>(std::make_tuple(<wbr>1, "abc")); // expected-note 1 {{requested here}}<br>
+  }<br>
+  {<br>
+    std::tuple<int, const std::string&> t(1, "a"); // expected-note 1 {{requested here}}<br>
+  }<br>
+  {<br>
+    F<int, const std::string&>(std::tuple<int, const std::string&>(1, "abc")); // expected-note 1 {{requested here}}<br>
+  }<br>
+  {<br>
+    ConvertsTo<int&> ct;<br>
+    std::tuple<const long&, int> t(ct, 42); // expected-note {{requested here}}<br>
+  }<br>
+  {<br>
+    ConvertsTo<int> ct;<br>
+    std::tuple<int const&, void*> t(ct, nullptr); // expected-note {{requested here}}<br>
+  }<br>
+  {<br>
+    ConvertsTo<Derived> ct;<br>
+    std::tuple<Base const&, int> t(ct, 42); // expected-note {{requested here}}<br>
+  }<br>
+  {<br>
+    std::allocator<void> alloc;<br>
+    std::tuple<std::string &&> t2("hello"); // expected-note {{requested here}}<br>
+    std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}}<br>
+  }<br>
+#else<br>
+#error force failure<br>
+// expected-error@-1 {{force failure}}<br>
+#endif<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/utilitie<wbr>s/tuple/tuple.tuple/tuple.cnst<wbr>r/PR20855_tuple_ref_binding_di<wbr>agnostics.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp?rev=323380&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/libcxx/trunk/test/std/ut<wbr>ilities/tuple/tuple.tuple/tupl<wbr>e.cnstr/PR20855_tuple_ref_bind<wbr>ing_diagnostics.pass.cpp?rev=3<wbr>23380&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/utilitie<wbr>s/tuple/tuple.tuple/tuple.cnst<wbr>r/PR20855_tuple_ref_binding_di<wbr>agnostics.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/utilitie<wbr>s/tuple/tuple.tuple/tuple.cnst<wbr>r/PR20855_tuple_ref_binding_di<wbr>agnostics.pass.cpp Wed Jan 24 14:14:01 2018<br>
@@ -0,0 +1,136 @@<br>
+// -*- C++ -*-<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03<br>
+<br>
+// <tuple><br>
+<br>
+// See <a href="http://llvm.org/PR20855" rel="noreferrer" target="_blank">llvm.org/PR20855</a><br>
+<br>
+#include <tuple><br>
+#include <string><br>
+#include "test_macros.h"<br>
+<br>
+#if TEST_HAS_BUILTIN_IDENTIFIER(__<wbr>reference_binds_to_temporary)<br>
+# define ASSERT_REFERENCE_BINDS_TEMPORA<wbr>RY(...) static_assert(__reference_bind<wbr>s_to_temporary(__VA_ARGS__), "")<br>
+# define ASSERT_NOT_REFERENCE_BINDS_TEM<wbr>PORARY(...) static_assert(!__reference_bin<wbr>ds_to_temporary(__VA_ARGS__), "")<br>
+#else<br>
+# define ASSERT_REFERENCE_BINDS_TEMPORA<wbr>RY(...) static_assert(true, "")<br>
+# define ASSERT_NOT_REFERENCE_BINDS_TEM<wbr>PORARY(...) static_assert(true, "")<br>
+#endif<br>
+<br>
+template <class Tp><br>
+struct ConvertsTo {<br>
+  using RawTp = typename std::remove_cv< typename std::remove_reference<Tp>::typ<wbr>e>::type;<br>
+<br>
+  operator Tp() const {<br>
+    return static_cast<Tp>(value);<br>
+  }<br>
+<br>
+  mutable RawTp value;<br>
+};<br>
+<br>
+struct Base {};<br>
+struct Derived : Base {};<br>
+<br>
+<br>
+static_assert(std::is_same<de<wbr>cltype("abc"), decltype(("abc"))>::value, "");<br>
+ASSERT_REFERENCE_BINDS_TEMPOR<wbr>ARY(std::string const&, decltype("abc"));<br>
+ASSERT_REFERENCE_BINDS_TEMPOR<wbr>ARY(std::string const&, decltype(("abc")));<br>
+ASSERT_REFERENCE_BINDS_TEMPOR<wbr>ARY(std::string const&, const char*&&);<br>
+<br>
+ASSERT_NOT_REFERENCE_BINDS_TE<wbr>MPORARY(int&, const ConvertsTo<int&>&);<br>
+ASSERT_NOT_REFERENCE_BINDS_TE<wbr>MPORARY(const int&, ConvertsTo<int&>&);<br>
+ASSERT_NOT_REFERENCE_BINDS_TE<wbr>MPORARY(Base&, Derived&);<br>
+<br>
+<br>
+static_assert(std::is_constru<wbr>ctible<int&, std::reference_wrapper<int>>::<wbr>value, "");<br>
+static_assert(std::is_constru<wbr>ctible<int const&, std::reference_wrapper<int>>::<wbr>value, "");<br>
+<br>
+template <class T> struct CannotDeduce {<br>
+ using type = T;<br>
+};<br>
+<br>
+template <class ...Args><br>
+void F(typename CannotDeduce<std::tuple<Args..<wbr>.>>::type const&) {}<br>
+<br>
+void compile_tests() {<br>
+  {<br>
+    F<int, int const&>(std::make_tuple(42, 42));<br>
+  }<br>
+  {<br>
+    F<int, int const&>(std::make_tuple<const int&, const int&>(42, 42));<br>
+    std::tuple<int, int const&> t(std::make_tuple<const int&, const int&>(42, 42));<br>
+  }<br>
+  {<br>
+    auto fn = &F<int, std::string const&>;<br>
+    fn(std::tuple<int, std::string const&>(42, std::string("a")));<br>
+    fn(std::make_tuple(42, std::string("a")));<br>
+  }<br>
+  {<br>
+    Derived d;<br>
+    std::tuple<Base&, Base const&> t(d, d);<br>
+  }<br>
+  {<br>
+    ConvertsTo<int&> ct;<br>
+    std::tuple<int, int&> t(42, ct);<br>
+  }<br>
+}<br>
+<br>
+void allocator_tests() {<br>
+    std::allocator<void> alloc;<br>
+    int x = 42;<br>
+    {<br>
+        std::tuple<int&> t(std::ref(x));<br>
+        assert(&std::get<0>(t) == &x);<br>
+        std::tuple<int&> t1(std::allocator_arg, alloc, std::ref(x));<br>
+        assert(&std::get<0>(t1) == &x);<br>
+    }<br>
+    {<br>
+        auto r = std::ref(x);<br>
+        auto const& cr = r;<br>
+        std::tuple<int&> t(r);<br>
+        assert(&std::get<0>(t) == &x);<br>
+        std::tuple<int&> t1(cr);<br>
+        assert(&std::get<0>(t1) == &x);<br>
+        std::tuple<int&> t2(std::allocator_arg, alloc, r);<br>
+        assert(&std::get<0>(t2) == &x);<br>
+        std::tuple<int&> t3(std::allocator_arg, alloc, cr);<br>
+        assert(&std::get<0>(t3) == &x);<br>
+    }<br>
+    {<br>
+        std::tuple<int const&> t(std::ref(x));<br>
+        assert(&std::get<0>(t) == &x);<br>
+        std::tuple<int const&> t2(std::cref(x));<br>
+        assert(&std::get<0>(t2) == &x);<br>
+        std::tuple<int const&> t3(std::allocator_arg, alloc, std::ref(x));<br>
+        assert(&std::get<0>(t3) == &x);<br>
+        std::tuple<int const&> t4(std::allocator_arg, alloc, std::cref(x));<br>
+        assert(&std::get<0>(t4) == &x);<br>
+    }<br>
+    {<br>
+        auto r = std::ref(x);<br>
+        auto cr = std::cref(x);<br>
+        std::tuple<int const&> t(r);<br>
+        assert(&std::get<0>(t) == &x);<br>
+        std::tuple<int const&> t2(cr);<br>
+        assert(&std::get<0>(t2) == &x);<br>
+        std::tuple<int const&> t3(std::allocator_arg, alloc, r);<br>
+        assert(&std::get<0>(t3) == &x);<br>
+        std::tuple<int const&> t4(std::allocator_arg, alloc, cr);<br>
+        assert(&std::get<0>(t4) == &x);<br>
+    }<br>
+}<br>
+<br>
+<br>
+int main() {<br>
+  compile_tests();<br>
+  allocator_tests();<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>