[libcxx-commits] [PATCH] D101770: [libc++] Fix bug with construction of std::tuple involving std::any

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon May 3 10:35:16 PDT 2021


ldionne created this revision.
ldionne requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

In std::tuple, we should try to avoid calling std::is_copy_constructible
if we can avoid doing so to workaround weird interactions with (I think)
compiler builtins. See https://reviews.llvm.org/D96523#2730953 and follow-ups
for more information.

I believe the std::tuple implementation was standards conforming before
this change and that we're working around a compiler bug, but it's
still worth doing so.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101770

Files:
  libcxx/include/tuple
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.with_any.compile.pass.cpp


Index: libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.with_any.compile.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.with_any.compile.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// This test makes sure that we can copy/move a std::tuple containing a type
+// that checks for copy constructibility itself, like std::any.
+//
+// Problem showcased in https://reviews.llvm.org/D96523#2730953.
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+template <class ...Pred>
+struct And : std::true_type { };
+
+template <class P1, class ...Pn>
+struct And<P1, Pn...>
+  : std::conditional<P1::value, And<Pn...>, std::false_type>::type
+{ };
+
+struct any {
+  any();
+  any(any const&) = default;
+
+  template <class ValueType, class Decayed = std::decay_t<ValueType>, class = std::enable_if_t<
+    !std::is_same<Decayed, any>::value &&
+    std::is_copy_constructible<Decayed>::value
+  > >
+  any(ValueType&&);
+};
+
+struct B {
+  B();
+  B(any);
+};
+
+void f() {
+  {
+    std::tuple<B, int> a;
+    std::tuple<B, int> b = a; (void)b;
+  }
+
+  {
+    std::tuple<B, int> a;
+    std::tuple<B, int> b = std::move(a); (void)b;
+  }
+}
Index: libcxx/include/tuple
===================================================================
--- libcxx/include/tuple
+++ libcxx/include/tuple
@@ -675,12 +675,12 @@
     // tuple(const tuple<U...>&) constructors (including allocator_arg_t variants)
     template <class ..._Up>
     struct _EnableCopyFromOtherTuple : _And<
+        _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
         _Or<
             _BoolConstant<sizeof...(_Tp) != 1>,
             // _Tp and _Up are 1-element packs - the pack expansions look
             // weird to avoid tripping up the type traits in degenerate cases
             _Lazy<_And,
-                _Not<is_same<_Tp, _Up> >...,
                 _Not<is_convertible<const tuple<_Up>&, _Tp> >...,
                 _Not<is_constructible<_Tp, const tuple<_Up>&> >...
             >
@@ -741,12 +741,12 @@
     // tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
     template <class ..._Up>
     struct _EnableMoveFromOtherTuple : _And<
+        _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
         _Or<
             _BoolConstant<sizeof...(_Tp) != 1>,
             // _Tp and _Up are 1-element packs - the pack expansions look
             // weird to avoid tripping up the type traits in degenerate cases
             _Lazy<_And,
-                _Not<is_same<_Tp, _Up> >...,
                 _Not<is_convertible<tuple<_Up>, _Tp> >...,
                 _Not<is_constructible<_Tp, tuple<_Up> > >...
             >


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D101770.342456.patch
Type: text/x-patch
Size: 3136 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20210503/f06923a3/attachment-0001.bin>


More information about the libcxx-commits mailing list