[libcxx-commits] [libcxx] 84f0bb6 - [libc++] Fix template instantiation depth issues with std::tuple

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon May 3 11:42:11 PDT 2021


Author: Louis Dionne
Date: 2021-05-03T14:42:07-04:00
New Revision: 84f0bb619507caf7c4809400138dae1da578282a

URL: https://github.com/llvm/llvm-project/commit/84f0bb619507caf7c4809400138dae1da578282a
DIFF: https://github.com/llvm/llvm-project/commit/84f0bb619507caf7c4809400138dae1da578282a.diff

LOG: [libc++] Fix template instantiation depth issues with std::tuple

This fixes the issue by implementing _And using the short-circuiting
SFINAE trick that we previously used only in std::tuple. One thing we
could look into is use the naive recursive implementation for disjunctions
with a small number of arguments, and use that trick with larger numbers
of arguments. It might be the case that the constant overhead for setting
up the SFINAE trick makes it only worth doing for larger packs, but that's
left for further work.

This problem was raised in https://reviews.llvm.org/D96523.

Differential Revision: https://reviews.llvm.org/D101661

Added: 
    libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp

Modified: 
    libcxx/include/type_traits

Removed: 
    


################################################################################
diff  --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 7978f7ba93f3f..fd6f7989dddf6 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -476,8 +476,6 @@ struct _MetaBase<true> {
   using _EnableIfImpl _LIBCPP_NODEBUG_TYPE = _Tp;
   template <class _Result, class _First, class ..._Rest>
   using _OrImpl _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::template _OrImpl<_First, _Rest...>;
-  template <class _Result, class _First, class ..._Rest>
-  using _AndImpl _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_First::value == true && sizeof...(_Rest) != 0>::template _AndImpl<_First, _Rest...>;
 };
 
 template <>
@@ -488,8 +486,6 @@ struct _MetaBase<false> {
   using _SelectApplyImpl _LIBCPP_NODEBUG_TYPE = _SecondFn<_Args...>;
   template <class _Result, class ...>
   using _OrImpl _LIBCPP_NODEBUG_TYPE = _Result;
-  template <class _Result, class ...>
-  using _AndImpl _LIBCPP_NODEBUG_TYPE = _Result;
 };
 template <bool _Cond, class _Ret = void>
 using _EnableIf _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_Cond>::template _EnableIfImpl<_Ret>;
@@ -497,8 +493,6 @@ template <bool _Cond, class _IfRes, class _ElseRes>
 using _If _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
 template <class ..._Rest>
 using _Or _LIBCPP_NODEBUG_TYPE = typename _MetaBase< sizeof...(_Rest) != 0 >::template _OrImpl<false_type, _Rest...>;
-template <class ..._Rest>
-using _And _LIBCPP_NODEBUG_TYPE = typename _MetaBase< sizeof...(_Rest) != 0 >::template _AndImpl<true_type, _Rest...>;
 template <class _Pred>
 struct _Not : _BoolConstant<!_Pred::value> {};
 template <class ..._Args>
@@ -506,6 +500,14 @@ using _FirstType _LIBCPP_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >=
 template <class ..._Args>
 using _SecondType _LIBCPP_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >= 2)>::template _SecondImpl<_Args...>;
 
+template <class ...> using __expand_to_true = true_type;
+template <class ..._Pred>
+__expand_to_true<_EnableIf<_Pred::value>...> __and_helper(int);
+template <class ...>
+false_type __and_helper(...);
+template <class ..._Pred>
+using _And _LIBCPP_NODEBUG_TYPE = decltype(__and_helper<_Pred...>(0));
+
 template <template <class...> class _Func, class ..._Args>
 struct _Lazy : _Func<_Args...> {};
 

diff  --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp
new file mode 100644
index 0000000000000..8ade19bf460c0
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11
+
+// Make sure that we don't blow up the template instantiation recursion depth
+// for tuples of size <= 1024.
+
+#include <tuple>
+#include <cassert>
+#include <utility>
+
+template <size_t... I>
+constexpr void CreateTuple(std::index_sequence<I...>) {
+  std::tuple<decltype(I)...> tuple(I...);
+  assert(std::get<0>(tuple) == 0);
+  assert(std::get<sizeof...(I)-1>(tuple) == sizeof...(I)-1);
+}
+
+constexpr bool test() {
+  CreateTuple(std::make_index_sequence<1024>{});
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test(), "");
+  return 0;
+}


        


More information about the libcxx-commits mailing list