diff options
author | Jonathan Wakely <redi@gcc.gnu.org> | 2014-05-16 12:08:49 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2014-05-16 12:08:49 +0100 |
commit | cd1464dbc692344c2e620ddd111c7bbdbd554b7e (patch) | |
tree | 6fd49a2dd73f5c6fe2373f9a8256eb261ee1794a | |
parent | 3d840f7d1f4b0172b8179e6e0a41694fc88fde67 (diff) | |
download | gcc-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/ChangeLog | 12 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/parse_numbers.h | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/chrono | 98 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/duration/literals/range.cc | 31 |
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 } +} |