diff options
author | Ed Smith-Rowland <3dw4rd@verizon.net> | 2014-05-16 09:30:57 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2014-05-16 10:30:57 +0100 |
commit | a2f4bd2ae1b6f66290315e145be759e4a8abd7ac (patch) | |
tree | 639f73432e0f2001642b6e4cfaf5c93c436b124b /libstdc++-v3 | |
parent | 88d4fbcf507b3a19905f87310a241d8bc6523836 (diff) | |
download | gcc-a2f4bd2ae1b6f66290315e145be759e4a8abd7ac.zip gcc-a2f4bd2ae1b6f66290315e145be759e4a8abd7ac.tar.gz gcc-a2f4bd2ae1b6f66290315e145be759e4a8abd7ac.tar.bz2 |
re PR libstdc++/61166 (overflow when parse number in std::duration operator"")
2014-05-15 Ed Smith-Rowland <3dw4rd@verizon.net>
Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/61166
* include/bits/parse_numbers.h: Use integral_constant to remove
duplication and simplify.
* testsuite/20_util/duration/literals/61166.cc: New.
Co-Authored-By: Jonathan Wakely <jwakely@redhat.com>
From-SVN: r210511
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 8 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/parse_numbers.h | 338 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/duration/literals/61166.cc | 39 |
3 files changed, 151 insertions, 234 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 85e2465..373b7a7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2014-05-15 Ed Smith-Rowland <3dw4rd@verizon.net> + Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/61166 + * include/bits/parse_numbers.h: Use integral_constant to remove + duplication and simplify. + * testsuite/20_util/duration/literals/61166.cc: New. + 2014-05-15 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/60326 diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h index 91a127c..0a42381a 100644 --- a/libstdc++-v3/include/bits/parse_numbers.h +++ b/libstdc++-v3/include/bits/parse_numbers.h @@ -27,8 +27,8 @@ * Do not attempt to use it directly. @headername{chrono} */ -#ifndef _PARSE_NUMBERS_H -#define _PARSE_NUMBERS_H 1 +#ifndef _GLIBCXX_PARSE_NUMBERS_H +#define _GLIBCXX_PARSE_NUMBERS_H 1 #pragma GCC system_header @@ -36,289 +36,181 @@ #if __cplusplus > 201103L +#include <limits> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace __parse_int { - +namespace __parse_int +{ template<unsigned _Base, char _Dig> struct _Digit; template<unsigned _Base> - struct _Digit<_Base, '0'> + struct _Digit<_Base, '0'> : integral_constant<unsigned, 0> { - static constexpr bool valid{true}; - static constexpr unsigned value{0}; + using __valid = true_type; }; template<unsigned _Base> - struct _Digit<_Base, '1'> + struct _Digit<_Base, '1'> : integral_constant<unsigned, 1> { - static constexpr bool valid{true}; - static constexpr unsigned value{1}; + using __valid = true_type; }; - template<unsigned _Base> - struct _Digit<_Base, '2'> + template<unsigned _Base, unsigned _Val> + struct _Digit_impl : integral_constant<unsigned, _Val> { - static_assert(_Base > 2, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{2}; + static_assert(_Base > _Val, "invalid digit"); + using __valid = true_type; }; template<unsigned _Base> - struct _Digit<_Base, '3'> - { - static_assert(_Base > 3, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{3}; - }; + struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2> + { }; template<unsigned _Base> - struct _Digit<_Base, '4'> - { - static_assert(_Base > 4, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{4}; - }; + struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3> + { }; template<unsigned _Base> - struct _Digit<_Base, '5'> - { - static_assert(_Base > 5, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{5}; - }; + struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4> + { }; template<unsigned _Base> - struct _Digit<_Base, '6'> - { - static_assert(_Base > 6, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{6}; - }; + struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5> + { }; template<unsigned _Base> - struct _Digit<_Base, '7'> - { - static_assert(_Base > 7, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{7}; - }; + struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6> + { }; template<unsigned _Base> - struct _Digit<_Base, '8'> - { - static_assert(_Base > 8, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{8}; - }; + struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7> + { }; template<unsigned _Base> - struct _Digit<_Base, '9'> - { - static_assert(_Base > 9, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{9}; - }; + struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8> + { }; template<unsigned _Base> - struct _Digit<_Base, 'a'> - { - static_assert(_Base > 0xa, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xa}; - }; + struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9> + { }; template<unsigned _Base> - struct _Digit<_Base, 'A'> - { - static_assert(_Base > 0xa, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xa}; - }; + struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa> + { }; template<unsigned _Base> - struct _Digit<_Base, 'b'> - { - static_assert(_Base > 0xb, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xb}; - }; + struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa> + { }; template<unsigned _Base> - struct _Digit<_Base, 'B'> - { - static_assert(_Base > 0xb, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xb}; - }; + struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb> + { }; template<unsigned _Base> - struct _Digit<_Base, 'c'> - { - static_assert(_Base > 0xc, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xc}; - }; + struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb> + { }; template<unsigned _Base> - struct _Digit<_Base, 'C'> - { - static_assert(_Base > 0xc, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xc}; - }; + struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc> + { }; template<unsigned _Base> - struct _Digit<_Base, 'd'> - { - static_assert(_Base > 0xd, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xd}; - }; + struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc> + { }; template<unsigned _Base> - struct _Digit<_Base, 'D'> - { - static_assert(_Base > 0xd, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xd}; - }; + struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd> + { }; template<unsigned _Base> - struct _Digit<_Base, 'e'> - { - static_assert(_Base > 0xe, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xe}; - }; + struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd> + { }; template<unsigned _Base> - struct _Digit<_Base, 'E'> - { - static_assert(_Base > 0xe, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xe}; - }; + struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe> + { }; template<unsigned _Base> - struct _Digit<_Base, 'f'> - { - static_assert(_Base > 0xf, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xf}; - }; + struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe> + { }; template<unsigned _Base> - struct _Digit<_Base, 'F'> - { - static_assert(_Base > 0xf, "invalid digit"); - static constexpr bool valid{true}; - static constexpr unsigned value{0xf}; - }; + struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf> + { }; - // Digit separator template<unsigned _Base> - struct _Digit<_Base, '\''> - { - static constexpr bool valid{false}; - static constexpr unsigned value{0}; - }; - - -//------------------------------------------------------------------------------ - - template<unsigned _Base, char _Dig, char... _Digs> - struct _Digits_help - { - static constexpr unsigned - value{_Digit<_Base, _Dig>::valid ? - 1U + _Digits_help<_Base, _Digs...>::value : - _Digits_help<_Base, _Digs...>::value}; - }; - - template<unsigned _Base, char _Dig> - struct _Digits_help<_Base, _Dig> - { - static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; - }; - - template<unsigned _Base, char... _Digs> - struct _Digits - { - static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value}; - }; + struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf> + { }; + // Digit separator template<unsigned _Base> - struct _Digits<_Base> + struct _Digit<_Base, '\''> : integral_constant<unsigned, 0> { - static constexpr unsigned value{0U}; + using __valid = false_type; }; //------------------------------------------------------------------------------ + template<unsigned long long _Val> + using __ull_constant = integral_constant<unsigned long long, _Val>; + template<unsigned _Base, char _Dig, char... _Digs> struct _Power_help { - static constexpr unsigned - value{_Digit<_Base, _Dig>::valid ? - _Base * _Power_help<_Base, _Digs...>::value : - _Power_help<_Base, _Digs...>::value}; + using __next = typename _Power_help<_Base, _Digs...>::type; + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type + = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>; }; template<unsigned _Base, char _Dig> struct _Power_help<_Base, _Dig> { - static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type = __ull_constant<__valid_digit::value>; }; template<unsigned _Base, char... _Digs> - struct _Power - { - static constexpr unsigned value{_Power_help<_Base, _Digs...>::value}; - }; + struct _Power : _Power_help<_Base, _Digs...>::type + { }; template<unsigned _Base> - struct _Power<_Base> - { - static constexpr unsigned value{0U}; - }; + struct _Power<_Base> : __ull_constant<0> + { }; //------------------------------------------------------------------------------ - template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs> + template<unsigned _Base, unsigned long long _Pow, char _Dig, char... _Digs> struct _Number_help { - static constexpr unsigned - value{_Digit<_Base, _Dig>::valid ? - _Pow * _Digit<_Base, _Dig>::value - + _Number_help<_Base, _Pow / _Base, _Digs...>::value : - _Number_help<_Base, _Pow, _Digs...>::value}; + using __digit = _Digit<_Base, _Dig>; + using __valid_digit = typename __digit::__valid; + using __next = _Number_help<_Base, + _Pow / (_Base * __valid_digit::value), + _Digs...>; + using type = __ull_constant<_Pow * __digit::value + __next::type::value>; }; - template<unsigned _Base, unsigned _Pow, char _Dig> + template<unsigned _Base, unsigned long long _Pow, char _Dig> struct _Number_help<_Base, _Pow, _Dig> { //static_assert(_Pow == 1U, "power should be one"); - static constexpr unsigned - value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U}; + using type = __ull_constant<_Digit<_Base, _Dig>::value>; }; template<unsigned _Base, char... _Digs> struct _Number - { - static constexpr unsigned - value{_Number_help<_Base, _Power<_Base, _Digs...>::value, - _Digs...>::value}; - }; + : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type + { }; template<unsigned _Base> struct _Number<_Base> - { - static constexpr unsigned value{0U}; - }; + : __ull_constant<0> + { }; //------------------------------------------------------------------------------ // This _Parse_int is the same 'level' as the old _Base_dispatch. @@ -328,84 +220,62 @@ namespace __parse_int { template<char... _Digs> struct _Parse_int<'0', 'b', _Digs...> - { - static constexpr unsigned long long - value{_Number<2U, _Digs...>::value}; - }; + : _Number<2U, _Digs...>::type + { }; template<char... _Digs> struct _Parse_int<'0', 'B', _Digs...> - { - static constexpr unsigned long long - value{_Number<2U, _Digs...>::value}; - }; + : _Number<2U, _Digs...>::type + { }; template<char... _Digs> struct _Parse_int<'0', 'x', _Digs...> - { - static constexpr unsigned long long - value{_Number<16U, _Digs...>::value}; - }; + : _Number<16U, _Digs...>::type + { }; template<char... _Digs> struct _Parse_int<'0', 'X', _Digs...> - { - static constexpr unsigned long long - value{_Number<16U, _Digs...>::value}; - }; + : _Number<16U, _Digs...>::type + { }; template<char... _Digs> struct _Parse_int<'0', _Digs...> - { - static constexpr unsigned long long - value{_Number<8U, _Digs...>::value}; - }; + : _Number<8U, _Digs...>::type + { }; template<char... _Digs> struct _Parse_int - { - static constexpr unsigned long long - value{_Number<10U, _Digs...>::value}; - }; + : _Number<10U, _Digs...>::type + { }; } // namespace __parse_int -namespace __select_int { - +namespace __select_int +{ template<unsigned long long _Val, typename... _Ints> struct _Select_int_base; template<unsigned long long _Val, typename _IntType, typename... _Ints> struct _Select_int_base<_Val, _IntType, _Ints...> - : integral_constant - < - typename conditional - < - _Val <= static_cast<unsigned long long> - (std::numeric_limits<_IntType>::max()), - _IntType, - typename _Select_int_base<_Val, _Ints...>::value_type - >::type, - _Val - > + : conditional_t<(_Val <= std::numeric_limits<_IntType>::max()), + integral_constant<_IntType, _Val>, + _Select_int_base<_Val, _Ints...>> { }; template<unsigned long long _Val> - struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val> + struct _Select_int_base<_Val> { }; template<char... _Digs> - struct _Select_int - : _Select_int_base< + using _Select_int = typename _Select_int_base< __parse_int::_Parse_int<_Digs...>::value, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long - > - { }; + >::type; } // namespace __select_int @@ -414,4 +284,4 @@ _GLIBCXX_END_NAMESPACE_VERSION #endif // __cplusplus > 201103L -#endif // _PARSE_NUMBERS_H +#endif // _GLIBCXX_PARSE_NUMBERS_H diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc b/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc new file mode 100644 index 0000000..e06adf8 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc @@ -0,0 +1,39 @@ +// { dg-do run } +// { 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/>. + +// libstdc++/61166 + +#include <chrono> +#include <testsuite_hooks.h> + +void +test01() +{ + using namespace std::literals::chrono_literals; + + // std::numeric_limits<unsigned>::max() == 4294967295 + VERIFY( (429496729510h).count() == 429496729510 ); +} + +int +main() +{ + test01(); +} |