diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-07-31 17:08:52 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2016-07-31 17:08:52 +0000 |
commit | 4d895214e6b534643f7055b456efcb5fee3b228c (patch) | |
tree | cd212317232614b40be7551e82f1bddfa39cf65a | |
parent | a3b90c0fb0b1a93c2d6565bdcef92853a45ceb60 (diff) |
libstdc++/72745 add static assertion for invalid tuple access
PR libstdc++/72745
* include/std/array (get): Use positive message for static assertions.
* include/std/functional (_Safe_tuple_element_t): Fix indentation.
* include/std/tuple (tuple_element<I, tuple<>>): Add partial
specialization for invalid indices, with static assertion.
* testsuite/20_util/tuple/element_access/get_neg.cc: New test.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@238924 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/include/std/array | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/functional | 8 | ||||
-rw-r--r-- | libstdc++-v3/include/std/tuple | 28 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc | 61 |
5 files changed, 94 insertions, 16 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a50066eef11..b79a4053afd 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2016-07-31 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/72745 + * include/std/array (get): Use positive message for static assertions. + * include/std/functional (_Safe_tuple_element_t): Fix indentation. + * include/std/tuple (tuple_element<I, tuple<>>): Add partial + specialization for invalid indices, with static assertion. + * testsuite/20_util/tuple/element_access/get_neg.cc: New test. + * testsuite/20_util/duration/requirements/typedefs_neg3.cc: Move dg-error to relevant line. * testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc: diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 73d26698f72..73a6fbce4f3 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -292,7 +292,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER constexpr _Tp& get(array<_Tp, _Nm>& __arr) noexcept { - static_assert(_Int < _Nm, "index is out of bounds"); + static_assert(_Int < _Nm, "array index is within bounds"); return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: _S_ref(__arr._M_elems, _Int); } @@ -301,7 +301,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER constexpr _Tp&& get(array<_Tp, _Nm>&& __arr) noexcept { - static_assert(_Int < _Nm, "index is out of bounds"); + static_assert(_Int < _Nm, "array index is within bounds"); return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); } @@ -309,7 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER constexpr const _Tp& get(const array<_Tp, _Nm>& __arr) noexcept { - static_assert(_Int < _Nm, "index is out of bounds"); + static_assert(_Int < _Nm, "array index is within bounds"); return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: _S_ref(__arr._M_elems, _Int); } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 97745aeb33b..700505e8f24 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -758,10 +758,10 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) // Like tuple_element_t but SFINAE-friendly. - template<std::size_t __i, typename _Tuple> - using _Safe_tuple_element_t - = typename enable_if<(__i < tuple_size<_Tuple>::value), - tuple_element<__i, _Tuple>>::type::type; + template<std::size_t __i, typename _Tuple> + using _Safe_tuple_element_t + = typename enable_if<(__i < tuple_size<_Tuple>::value), + tuple_element<__i, _Tuple>>::type::type; /** * Maps an argument to bind() into an actual argument to the bound diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index c1c924c1212..484cb4822f2 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -1243,6 +1243,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; + /// class tuple_size + template<typename... _Elements> + struct tuple_size<tuple<_Elements...>> + : public integral_constant<std::size_t, sizeof...(_Elements)> { }; + +#if __cplusplus > 201402L + template <typename _Tp> + constexpr size_t tuple_size_v = tuple_size<_Tp>::value; +#endif + /** * Recursive case for tuple_element: strip off the first element in * the tuple and retrieve the (i-1)th element of the remaining tuple. @@ -1260,15 +1270,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Head type; }; - /// class tuple_size - template<typename... _Elements> - struct tuple_size<tuple<_Elements...>> - : public integral_constant<std::size_t, sizeof...(_Elements)> { }; - -#if __cplusplus > 201402L - template <typename _Tp> - constexpr size_t tuple_size_v = tuple_size<_Tp>::value; -#endif + /** + * Error case for tuple_element: invalid index. + */ + template<size_t __i> + struct tuple_element<__i, tuple<>> + { + static_assert(__i < tuple_size<tuple<>>::value, + "tuple index is in range"); + }; template<std::size_t __i, typename _Head, typename... _Tail> constexpr _Head& diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc new file mode 100644 index 00000000000..95ff697ae7a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-fno-show-column" } +// { dg-do compile { target c++14 } } +// { dg-error "in range" "" { target *-*-* } 1279 } + +#include <tuple> + +void +test01() +{ + using test_type = std::tuple<>; + test_type t; + std::get<0>(t); // { dg-error "no match" } + std::get<0>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<0>(static_cast<test_type&&>(t)); // { dg-error "no match" } + std::get<5>(t); // { dg-error "no match" } + std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" } +} + +void +test02() +{ + using test_type = std::tuple<int>; + test_type t; + std::get<1>(t); // { dg-error "no match" } + std::get<1>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<1>(static_cast<test_type&&>(t)); // { dg-error "no match" } + std::get<5>(t); // { dg-error "no match" } + std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" } +} + +void +test03() +{ + using test_type = std::tuple<int, int, int, int>; + test_type t; + std::get<5>(t); // { dg-error "no match" } + std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" } + std::get<6>(t); // { dg-error "no match" } + std::get<6>(const_cast<const test_type&>(t)); // { dg-error "no match" } + std::get<6>(static_cast<test_type&&>(t)); // { dg-error "no match" } +} |