diff options
author | Eric Fiselier <eric@efcs.ca> | 2014-10-28 06:31:22 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2014-10-28 06:31:22 +0000 |
commit | 522aaf67ea4dbda95504fb2940655c5df8e353ee (patch) | |
tree | 575c47aaa7582fe7a70dcdb57647c2fc14a9920e /include/__tuple | |
parent | cf85245c088c3b887bfb3b95663e15a8eaae9f41 (diff) | |
download | external_libcxx-522aaf67ea4dbda95504fb2940655c5df8e353ee.tar.gz external_libcxx-522aaf67ea4dbda95504fb2940655c5df8e353ee.tar.bz2 external_libcxx-522aaf67ea4dbda95504fb2940655c5df8e353ee.zip |
[libcxx] Delay evaluation of __make_tuple_types to prevent blowing the max template instantiation depth. Fixes Bug #18345
Summary:
http://llvm.org/bugs/show_bug.cgi?id=18345
Tuple's constructor and assignment operators for "tuple-like" types evaluates __make_tuple_types unnecessarily. In the case of a large array this can blow the template instantiation depth.
Ex:
```
#include <array>
#include <tuple>
#include <memory>
typedef std::array<int, 1256> array_t;
typedef std::tuple<array_t> tuple_t;
int main() {
array_t a;
tuple_t t(a); // broken
t = a; // broken
// make_shared uses tuple behind the scenes. This bug breaks this code.
std::make_shared<array_t>(a);
}
```
To prevent this from happening we delay the instantiation of `__make_tuple_types` until after we perform the length check. Currently `__make_tuple_types` is instantiated at the same time that the length check .
Test Plan: Two tests have been added. One for the "tuple-like" constructors and another for the "tuple-like" assignment operator.
Reviewers: mclow.lists, EricWF
Reviewed By: EricWF
Subscribers: K-ballo, cfe-commits
Differential Revision: http://reviews.llvm.org/D4467
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@220769 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/__tuple')
-rw-r--r-- | include/__tuple | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/include/__tuple b/include/__tuple index ee5b916fa..bffb95cb7 100644 --- a/include/__tuple +++ b/include/__tuple @@ -245,19 +245,30 @@ struct __make_tuple_types // __tuple_convertible -template <bool, class _Tp, class _Up> +template <class, class> struct __tuple_convertible_imp : public false_type {}; template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> -struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > +struct __tuple_convertible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > : public integral_constant<bool, is_convertible<_Tp0, _Up0>::value && - __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; + __tuple_convertible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; template <> -struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<> > +struct __tuple_convertible_imp<__tuple_types<>, __tuple_types<> > : public true_type {}; +template <bool, class, class> +struct __tuple_convertible_apply : public false_type {}; + +template <class _Tp, class _Up> +struct __tuple_convertible_apply<true, _Tp, _Up> + : public __tuple_convertible_imp< + typename __make_tuple_types<_Tp>::type + , typename __make_tuple_types<_Up>::type + > +{}; + template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, bool = __tuple_like<_Up>::value> struct __tuple_convertible @@ -265,26 +276,36 @@ struct __tuple_convertible template <class _Tp, class _Up> struct __tuple_convertible<_Tp, _Up, true, true> - : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value == - tuple_size<_Up>::value, - typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> + : public __tuple_convertible_apply<tuple_size<typename remove_reference<_Tp>::type>::value == + tuple_size<_Up>::value, _Tp, _Up> {}; // __tuple_constructible -template <bool, class _Tp, class _Up> +template <class, class> struct __tuple_constructible_imp : public false_type {}; template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> -struct __tuple_constructible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > +struct __tuple_constructible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > : public integral_constant<bool, is_constructible<_Up0, _Tp0>::value && - __tuple_constructible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; + __tuple_constructible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; template <> -struct __tuple_constructible_imp<true, __tuple_types<>, __tuple_types<> > +struct __tuple_constructible_imp<__tuple_types<>, __tuple_types<> > : public true_type {}; +template <bool _SameSize, class, class> +struct __tuple_constructible_apply : public false_type {}; + +template <class _Tp, class _Up> +struct __tuple_constructible_apply<true, _Tp, _Up> + : public __tuple_constructible_imp< + typename __make_tuple_types<_Tp>::type + , typename __make_tuple_types<_Up>::type + > +{}; + template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, bool = __tuple_like<_Up>::value> struct __tuple_constructible @@ -292,26 +313,36 @@ struct __tuple_constructible template <class _Tp, class _Up> struct __tuple_constructible<_Tp, _Up, true, true> - : public __tuple_constructible_imp<tuple_size<typename remove_reference<_Tp>::type>::value == - tuple_size<_Up>::value, - typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> + : public __tuple_constructible_apply<tuple_size<typename remove_reference<_Tp>::type>::value == + tuple_size<_Up>::value, _Tp, _Up> {}; // __tuple_assignable -template <bool, class _Tp, class _Up> +template <class, class> struct __tuple_assignable_imp : public false_type {}; template <class _Tp0, class ..._Tp, class _Up0, class ..._Up> -struct __tuple_assignable_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > +struct __tuple_assignable_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> > : public integral_constant<bool, is_assignable<_Up0&, _Tp0>::value && - __tuple_assignable_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; + __tuple_assignable_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {}; template <> -struct __tuple_assignable_imp<true, __tuple_types<>, __tuple_types<> > +struct __tuple_assignable_imp<__tuple_types<>, __tuple_types<> > : public true_type {}; +template <bool, class, class> +struct __tuple_assignable_apply : public false_type {}; + +template <class _Tp, class _Up> +struct __tuple_assignable_apply<true, _Tp, _Up> + : __tuple_assignable_imp< + typename __make_tuple_types<_Tp>::type + , typename __make_tuple_types<_Up>::type + > +{}; + template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value, bool = __tuple_like<_Up>::value> struct __tuple_assignable @@ -319,9 +350,8 @@ struct __tuple_assignable template <class _Tp, class _Up> struct __tuple_assignable<_Tp, _Up, true, true> - : public __tuple_assignable_imp<tuple_size<typename remove_reference<_Tp>::type>::value == - tuple_size<_Up>::value, - typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> + : public __tuple_assignable_apply<tuple_size<typename remove_reference<_Tp>::type>::value == + tuple_size<_Up>::value, _Tp, _Up> {}; _LIBCPP_END_NAMESPACE_STD |