aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2016-07-31 17:08:52 +0000
committerJonathan Wakely <jwakely@redhat.com>2016-07-31 17:08:52 +0000
commit4d895214e6b534643f7055b456efcb5fee3b228c (patch)
treecd212317232614b40be7551e82f1bddfa39cf65a
parenta3b90c0fb0b1a93c2d6565bdcef92853a45ceb60 (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/ChangeLog7
-rw-r--r--libstdc++-v3/include/std/array6
-rw-r--r--libstdc++-v3/include/std/functional8
-rw-r--r--libstdc++-v3/include/std/tuple28
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc61
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" }
+}