aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <redi@gcc.gnu.org>2014-05-16 12:08:49 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2014-05-16 12:08:49 +0100
commitcd1464dbc692344c2e620ddd111c7bbdbd554b7e (patch)
tree6fd49a2dd73f5c6fe2373f9a8256eb261ee1794a
parent3d840f7d1f4b0172b8179e6e0a41694fc88fde67 (diff)
downloadgcc-cd1464dbc692344c2e620ddd111c7bbdbd554b7e.zip
gcc-cd1464dbc692344c2e620ddd111c7bbdbd554b7e.tar.gz
gcc-cd1464dbc692344c2e620ddd111c7bbdbd554b7e.tar.bz2
parse_numbers.h (__parse_int::_Number_help): Check for overflow.
* include/bits/parse_numbers.h (__parse_int::_Number_help): Check for overflow. * include/std/chrono (chrono_literals::__select_type::_Select_type): Remove. (chrono_literals::_Checked_integral_constant): Define. Simplify UDL operator templates and check for overflow. * testsuite/20_util/duration/literals/range.cc: New. From-SVN: r210513
-rw-r--r--libstdc++-v3/ChangeLog12
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h1
-rw-r--r--libstdc++-v3/include/std/chrono98
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/literals/range.cc31
4 files changed, 73 insertions, 69 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 373b7a7..3df0901 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,4 +1,14 @@
-2014-05-15 Ed Smith-Rowland <3dw4rd@verizon.net>
+2014-05-16 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/parse_numbers.h (__parse_int::_Number_help): Check for
+ overflow.
+ * include/std/chrono (chrono_literals::__select_type::_Select_type):
+ Remove.
+ (chrono_literals::_Checked_integral_constant): Define.
+ Simplify UDL operator templates and check for overflow.
+ * testsuite/20_util/duration/literals/range.cc: New.
+
+2014-05-16 Ed Smith-Rowland <3dw4rd@verizon.net>
Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/61166
diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h
index 0a42381a..a29d127 100644
--- a/libstdc++-v3/include/bits/parse_numbers.h
+++ b/libstdc++-v3/include/bits/parse_numbers.h
@@ -193,6 +193,7 @@ namespace __parse_int
_Pow / (_Base * __valid_digit::value),
_Digs...>;
using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
+ static_assert((type::value / _Pow) == __digit::value, "overflow");
};
template<unsigned _Base, unsigned long long _Pow, char _Dig>
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index b114e02..39ad5e3 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -787,117 +787,79 @@ _GLIBCXX_END_NAMESPACE_VERSION
inline namespace chrono_literals
{
- namespace __select_type
- {
-
- using namespace __parse_int;
-
- template<unsigned long long _Val, typename _Dur>
- struct _Select_type
- : conditional<
- _Val <= static_cast<unsigned long long>
- (numeric_limits<typename _Dur::rep>::max()),
- _Dur, void>
- {
- static constexpr typename _Select_type::type
- value{static_cast<typename _Select_type::type>(_Val)};
- };
-
- template<unsigned long long _Val, typename _Dur>
- constexpr typename _Select_type<_Val, _Dur>::type
- _Select_type<_Val, _Dur>::value;
+ template<typename _Rep, unsigned long long _Val>
+ struct _Checked_integral_constant
+ : integral_constant<_Rep, static_cast<_Rep>(_Val)>
+ {
+ static_assert(_Checked_integral_constant::value > 0
+ && _Checked_integral_constant::value == _Val,
+ "literal value cannot be represented by duration type");
+ };
- } // __select_type
+ template<typename _Dur, char... _Digits>
+ constexpr _Dur __check_overflow()
+ {
+ using _Val = __parse_int::_Parse_int<_Digits...>;
+ using _Rep = typename _Dur::rep;
+ // TODO: should be simply integral_constant<_Rep, _Val::value>
+ // but GCC doesn't reject narrowing conversions to _Rep.
+ using _CheckedVal = _Checked_integral_constant<_Rep, _Val::value>;
+ return _Dur{_CheckedVal::value};
+ }
constexpr chrono::duration<long double, ratio<3600,1>>
operator""h(long double __hours)
{ return chrono::duration<long double, ratio<3600,1>>{__hours}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::hours>::type
+ constexpr chrono::hours
operator""h()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::hours>::value;
- }
+ { return __check_overflow<chrono::hours, _Digits...>(); }
constexpr chrono::duration<long double, ratio<60,1>>
operator""min(long double __mins)
{ return chrono::duration<long double, ratio<60,1>>{__mins}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::minutes>::type
+ constexpr chrono::minutes
operator""min()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::minutes>::value;
- }
+ { return __check_overflow<chrono::minutes, _Digits...>(); }
constexpr chrono::duration<long double>
operator""s(long double __secs)
{ return chrono::duration<long double>{__secs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::seconds>::type
+ constexpr chrono::seconds
operator""s()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::seconds>::value;
- }
+ { return __check_overflow<chrono::seconds, _Digits...>(); }
constexpr chrono::duration<long double, milli>
operator""ms(long double __msecs)
{ return chrono::duration<long double, milli>{__msecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::milliseconds>::type
+ constexpr chrono::milliseconds
operator""ms()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::milliseconds>::value;
- }
+ { return __check_overflow<chrono::milliseconds, _Digits...>(); }
constexpr chrono::duration<long double, micro>
operator""us(long double __usecs)
{ return chrono::duration<long double, micro>{__usecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::microseconds>::type
+ constexpr chrono::microseconds
operator""us()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::microseconds>::value;
- }
+ { return __check_overflow<chrono::microseconds, _Digits...>(); }
constexpr chrono::duration<long double, nano>
operator""ns(long double __nsecs)
{ return chrono::duration<long double, nano>{__nsecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::nanoseconds>::type
+ constexpr chrono::nanoseconds
operator""ns()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::nanoseconds>::value;
- }
+ { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
} // inline namespace chrono_literals
} // inline namespace literals
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
new file mode 100644
index 0000000..c005df6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2014 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/>.
+
+#include <chrono>
+
+void
+test01()
+{
+ using namespace std::literals::chrono_literals;
+
+ // std::numeric_limits<int64_t>::max() == 9223372036854775807;
+ auto h = 9223372036854775808h;
+ // { dg-error "cannot be represented" "" { target *-*-* } 794 }
+}