diff options
| author | Marshall Clow <mclow.lists@gmail.com> | 2014-10-15 10:33:02 +0000 |
|---|---|---|
| committer | Marshall Clow <mclow.lists@gmail.com> | 2014-10-15 10:33:02 +0000 |
| commit | 14c5ec51945be51c55c58cc4d2a1e4f1cfb56533 (patch) | |
| tree | cdc19eebb6caa83c76ca46cd352e0cf4c0d0c6c3 | |
| parent | 6373829449e48634ae7548e3a5e9c2869b104d32 (diff) | |
| download | bcm5719-llvm-14c5ec51945be51c55c58cc4d2a1e4f1cfb56533.tar.gz bcm5719-llvm-14c5ec51945be51c55c58cc4d2a1e4f1cfb56533.zip | |
Fixes PR21157 'tuple: non-default constructible tuple hard failure' Thanks to Louis Dionne for the bug report and the patch.
llvm-svn: 219785
4 files changed, 87 insertions, 11 deletions
diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 1463170fe1c..aa7185c86fa 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -376,19 +376,18 @@ template <class ..._Tp> _LIBCPP_INLINE_VISIBILITY void __swallow(_Tp&&...) _NOEXCEPT {} -template <bool ...> struct __all; +template <bool ..._B> +struct __all + : is_same<__all<_B...>, __all<(_B, true)...>> +{ }; -template <> -struct __all<> -{ - static const bool value = true; -}; +template <class _Tp> +struct __all_default_constructible; -template <bool _B0, bool ... _Bp> -struct __all<_B0, _Bp...> -{ - static const bool value = _B0 && __all<_Bp...>::value; -}; +template <class ..._Tp> +struct __all_default_constructible<__tuple_types<_Tp...>> + : __all<is_default_constructible<_Tp>::value...> +{ }; // __tuple_impl @@ -512,6 +511,9 @@ class _LIBCPP_TYPE_VIS_ONLY tuple typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT; public: + template <bool _Dummy = true, class _Up = typename enable_if< + __all<(_Dummy && is_default_constructible<_Tp>::value)...>::value + >::type> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR tuple() _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {} @@ -547,6 +549,12 @@ public: sizeof...(_Up) < sizeof...(_Tp) ? sizeof...(_Up) : sizeof...(_Tp)>::type + >::value && + __all_default_constructible< + typename __make_tuple_types<tuple, sizeof...(_Tp), + sizeof...(_Up) < sizeof...(_Tp) ? + sizeof...(_Up) : + sizeof...(_Tp)>::type >::value, bool >::type = false @@ -587,6 +595,12 @@ public: sizeof...(_Up) < sizeof...(_Tp) ? sizeof...(_Up) : sizeof...(_Tp)>::type + >::value && + __all_default_constructible< + typename __make_tuple_types<tuple, sizeof...(_Tp), + sizeof...(_Up) < sizeof...(_Tp) ? + sizeof...(_Up) : + sizeof...(_Tp)>::type >::value, bool >::type =false @@ -620,6 +634,12 @@ public: sizeof...(_Up) < sizeof...(_Tp) ? sizeof...(_Up) : sizeof...(_Tp)>::type + >::value && + __all_default_constructible< + typename __make_tuple_types<tuple, sizeof...(_Tp), + sizeof...(_Up) < sizeof...(_Tp) ? + sizeof...(_Up) : + sizeof...(_Tp)>::type >::value >::type > diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp index d6fbdae835a..7359d77c054 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp @@ -16,6 +16,7 @@ #include <tuple> #include <cassert> +#include <type_traits> #include "../MoveOnly.h" @@ -30,6 +31,8 @@ struct A #endif +struct NoDefault { NoDefault() = delete; }; + int main() { { @@ -63,6 +66,14 @@ int main() assert(std::get<1>(t) == MoveOnly()); assert(std::get<2>(t) == MoveOnly()); } + { + // Make sure the _Up... constructor SFINAEs out when the types that + // are not explicitly initialized are not all default constructible. + // Otherwise, std::is_constructible would return true but instantiating + // the constructor would fail. + static_assert(!std::is_constructible<std::tuple<MoveOnly, NoDefault>, MoveOnly>(), ""); + static_assert(!std::is_constructible<std::tuple<MoveOnly, MoveOnly, NoDefault>, MoveOnly, MoveOnly>(), ""); + } #if _LIBCPP_STD_VER > 11 { constexpr std::tuple<Empty> t0{Empty()}; diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp index 667c4dd803c..97469869dff 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_UTypes.pass.cpp @@ -22,6 +22,8 @@ #include "../alloc_first.h" #include "../alloc_last.h" +struct NoDefault { NoDefault() = delete; }; + int main() { { @@ -68,4 +70,19 @@ int main() assert(std::get<1>(t) == MoveOnly()); assert(std::get<2>(t) == MoveOnly()); } + { + // Make sure the _Up... constructor SFINAEs out when the types that + // are not explicitly initialized are not all default constructible. + // Otherwise, std::is_constructible would return true but instantiating + // the constructor would fail. + static_assert(!std::is_constructible< + std::tuple<MoveOnly, NoDefault>, + std::allocator_arg_t, A1<int>, MoveOnly + >::value, ""); + + static_assert(!std::is_constructible< + std::tuple<MoveOnly, MoveOnly, NoDefault>, + std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly + >::value, ""); + } } diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp index b72b77ee97c..9cde90da3f5 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/default.pass.cpp @@ -16,9 +16,23 @@ #include <tuple> #include <string> #include <cassert> +#include <type_traits> #include "DefaultOnly.h" +struct NoDefault { + NoDefault() = delete; + explicit NoDefault(int) { } +}; + +struct NoExceptDefault { + NoExceptDefault() noexcept = default; +}; + +struct ThrowingDefault { + ThrowingDefault() { } +}; + int main() { { @@ -46,6 +60,20 @@ int main() assert(std::get<2>(t) == ""); assert(std::get<3>(t) == DefaultOnly()); } + { + // See bug #21157. + static_assert(!std::is_default_constructible<std::tuple<NoDefault>>(), ""); + static_assert(!std::is_default_constructible<std::tuple<DefaultOnly, NoDefault>>(), ""); + static_assert(!std::is_default_constructible<std::tuple<NoDefault, DefaultOnly, NoDefault>>(), ""); + } + { + static_assert(noexcept(std::tuple<NoExceptDefault>()), ""); + static_assert(noexcept(std::tuple<NoExceptDefault, NoExceptDefault>()), ""); + + static_assert(!noexcept(std::tuple<ThrowingDefault, NoExceptDefault>()), ""); + static_assert(!noexcept(std::tuple<NoExceptDefault, ThrowingDefault>()), ""); + static_assert(!noexcept(std::tuple<ThrowingDefault, ThrowingDefault>()), ""); + } #ifndef _LIBCPP_HAS_NO_CONSTEXPR { constexpr std::tuple<> t; |

