mirror of git://gcc.gnu.org/git/gcc.git
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. From-SVN: r238924
This commit is contained in:
parent
f245e3a0ee
commit
3c040fa4a2
|
|
@ -1,5 +1,12 @@
|
||||||
2016-07-31 Jonathan Wakely <jwakely@redhat.com>
|
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
|
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Move
|
||||||
dg-error to relevant line.
|
dg-error to relevant line.
|
||||||
* testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc:
|
* testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc:
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
constexpr _Tp&
|
constexpr _Tp&
|
||||||
get(array<_Tp, _Nm>& __arr) noexcept
|
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>::
|
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
|
||||||
_S_ref(__arr._M_elems, _Int);
|
_S_ref(__arr._M_elems, _Int);
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
constexpr _Tp&&
|
constexpr _Tp&&
|
||||||
get(array<_Tp, _Nm>&& __arr) noexcept
|
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));
|
return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
constexpr const _Tp&
|
constexpr const _Tp&
|
||||||
get(const array<_Tp, _Nm>& __arr) noexcept
|
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>::
|
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
|
||||||
_S_ref(__arr._M_elems, _Int);
|
_S_ref(__arr._M_elems, _Int);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -758,10 +758,10 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
|
||||||
|
|
||||||
|
|
||||||
// Like tuple_element_t but SFINAE-friendly.
|
// Like tuple_element_t but SFINAE-friendly.
|
||||||
template<std::size_t __i, typename _Tuple>
|
template<std::size_t __i, typename _Tuple>
|
||||||
using _Safe_tuple_element_t
|
using _Safe_tuple_element_t
|
||||||
= typename enable_if<(__i < tuple_size<_Tuple>::value),
|
= typename enable_if<(__i < tuple_size<_Tuple>::value),
|
||||||
tuple_element<__i, _Tuple>>::type::type;
|
tuple_element<__i, _Tuple>>::type::type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps an argument to bind() into an actual argument to the bound
|
* Maps an argument to bind() into an actual argument to the bound
|
||||||
|
|
|
||||||
|
|
@ -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
|
* Recursive case for tuple_element: strip off the first element in
|
||||||
* the tuple and retrieve the (i-1)th element of the remaining tuple.
|
* the tuple and retrieve the (i-1)th element of the remaining tuple.
|
||||||
|
|
@ -1260,15 +1270,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typedef _Head type;
|
typedef _Head type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// class tuple_size
|
/**
|
||||||
template<typename... _Elements>
|
* Error case for tuple_element: invalid index.
|
||||||
struct tuple_size<tuple<_Elements...>>
|
*/
|
||||||
: public integral_constant<std::size_t, sizeof...(_Elements)> { };
|
template<size_t __i>
|
||||||
|
struct tuple_element<__i, tuple<>>
|
||||||
#if __cplusplus > 201402L
|
{
|
||||||
template <typename _Tp>
|
static_assert(__i < tuple_size<tuple<>>::value,
|
||||||
constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
|
"tuple index is in range");
|
||||||
#endif
|
};
|
||||||
|
|
||||||
template<std::size_t __i, typename _Head, typename... _Tail>
|
template<std::size_t __i, typename _Head, typename... _Tail>
|
||||||
constexpr _Head&
|
constexpr _Head&
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue