Make the machinery in bits/parse_number.h unsigned long long.
I had actually noticed this a while back but we were in stage 4. Then I
forgot.. :-/
Built and tested on x84_64-linux.
OK?
2014-05-14 Ed Smith-Rowland <3dw...@verizon.net>
libstdc++/61166 overflow when parse number in std::duration operator""
* include/bits/parse_numbers.h: Make the machinery unsigned long long.
* testsuite/20_util/duration/literals/pr61166.cc: New.
Index: include/bits/parse_numbers.h
===================================================================
--- include/bits/parse_numbers.h (revision 210315)
+++ include/bits/parse_numbers.h (working copy)
@@ -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,262 +36,278 @@
#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>
+ template<unsigned long long _Base, char _Dig>
struct _Digit;
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '0'>
{
static constexpr bool valid{true};
- static constexpr unsigned value{0};
+ static constexpr unsigned long long value{0};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '1'>
{
static constexpr bool valid{true};
- static constexpr unsigned value{1};
+ static constexpr unsigned long long value{1};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '2'>
{
static_assert(_Base > 2, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{2};
+ static constexpr unsigned long long value{2};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '3'>
{
static_assert(_Base > 3, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{3};
+ static constexpr unsigned long long value{3};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '4'>
{
static_assert(_Base > 4, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{4};
+ static constexpr unsigned long long value{4};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '5'>
{
static_assert(_Base > 5, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{5};
+ static constexpr unsigned long long value{5};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '6'>
{
static_assert(_Base > 6, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{6};
+ static constexpr unsigned long long value{6};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '7'>
{
static_assert(_Base > 7, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{7};
+ static constexpr unsigned long long value{7};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '8'>
{
static_assert(_Base > 8, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{8};
+ static constexpr unsigned long long value{8};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '9'>
{
static_assert(_Base > 9, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{9};
+ static constexpr unsigned long long value{9};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'a'>
{
static_assert(_Base > 0xa, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xa};
+ static constexpr unsigned long long value{0xa};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'A'>
{
static_assert(_Base > 0xa, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xa};
+ static constexpr unsigned long long value{0xa};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'b'>
{
static_assert(_Base > 0xb, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xb};
+ static constexpr unsigned long long value{0xb};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'B'>
{
static_assert(_Base > 0xb, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xb};
+ static constexpr unsigned long long value{0xb};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'c'>
{
static_assert(_Base > 0xc, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xc};
+ static constexpr unsigned long long value{0xc};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'C'>
{
static_assert(_Base > 0xc, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xc};
+ static constexpr unsigned long long value{0xc};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'd'>
{
static_assert(_Base > 0xd, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xd};
+ static constexpr unsigned long long value{0xd};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'D'>
{
static_assert(_Base > 0xd, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xd};
+ static constexpr unsigned long long value{0xd};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'e'>
{
static_assert(_Base > 0xe, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xe};
+ static constexpr unsigned long long value{0xe};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'E'>
{
static_assert(_Base > 0xe, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xe};
+ static constexpr unsigned long long value{0xe};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'f'>
{
static_assert(_Base > 0xf, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xf};
+ static constexpr unsigned long long value{0xf};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, 'F'>
{
static_assert(_Base > 0xf, "invalid digit");
static constexpr bool valid{true};
- static constexpr unsigned value{0xf};
+ static constexpr unsigned long long value{0xf};
};
+ // Radix
+ template<unsigned long long _Base>
+ struct _Digit<_Base, '.'>
+ {
+ static constexpr bool valid{false};
+ static constexpr unsigned long long value{0};
+ };
+
// Digit separator
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digit<_Base, '\''>
{
static constexpr bool valid{false};
- static constexpr unsigned value{0};
+ static constexpr unsigned long long value{0};
};
//------------------------------------------------------------------------------
- template<unsigned _Base, char _Dig, char... _Digs>
+ template<unsigned long long _Base, char _Dig, char... _Digs>
struct _Digits_help
{
- static constexpr unsigned
+ static constexpr unsigned long long
value{_Digit<_Base, _Dig>::valid ?
1U + _Digits_help<_Base, _Digs...>::value :
_Digits_help<_Base, _Digs...>::value};
};
- template<unsigned _Base, char _Dig>
+ template<unsigned long long _Base, char _Dig>
struct _Digits_help<_Base, _Dig>
{
- static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+ static constexpr unsigned long long
+ value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
};
- template<unsigned _Base, char... _Digs>
+ template<unsigned long long _Base, char... _Digs>
struct _Digits
{
- static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value};
+ static constexpr unsigned long long
+ value{_Digits_help<_Base, _Digs...>::value};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Digits<_Base>
{
- static constexpr unsigned value{0U};
+ static constexpr unsigned long long value{0U};
};
//------------------------------------------------------------------------------
- template<unsigned _Base, char _Dig, char... _Digs>
+ template<unsigned long long _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};
+ static constexpr unsigned long long
+ value{_Digit<_Base, _Dig>::valid
+ ? _Base * _Power_help<_Base, _Digs...>::value
+ : _Power_help<_Base, _Digs...>::value};
};
- template<unsigned _Base, char _Dig>
+ template<unsigned long long _Base, char _Dig>
struct _Power_help<_Base, _Dig>
{
- static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+ static constexpr unsigned long long
+ value{_Digit<_Base, _Dig>::valid ? 1ULL : 0ULL};
};
- template<unsigned _Base, char... _Digs>
+ template<unsigned long long _Base, char... _Digs>
struct _Power
{
- static constexpr unsigned value{_Power_help<_Base, _Digs...>::value};
+ static constexpr unsigned long long
+ value{_Power_help<_Base, _Digs...>::value};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Power<_Base>
{
- static constexpr unsigned value{0U};
+ static constexpr unsigned long long value{0ULL};
};
//------------------------------------------------------------------------------
- template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs>
+ template<unsigned long long _Base, unsigned long long _Pow,
+ char _Dig, char... _Digs>
struct _Number_help
{
- static constexpr unsigned
+ static constexpr unsigned long long
value{_Digit<_Base, _Dig>::valid ?
_Pow * _Digit<_Base, _Dig>::value
+ _Number_help<_Base, _Pow / _Base, _Digs...>::value :
@@ -298,26 +314,26 @@
_Number_help<_Base, _Pow, _Digs...>::value};
};
- template<unsigned _Base, unsigned _Pow, char _Dig>
+ template<unsigned long long _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};
+ //static_assert(_Pow == 1ULL, "power should be one");
+ static constexpr unsigned long long
+ value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0ULL};
};
- template<unsigned _Base, char... _Digs>
+ template<unsigned long long _Base, char... _Digs>
struct _Number
{
- static constexpr unsigned
+ static constexpr unsigned long long
value{_Number_help<_Base, _Power<_Base, _Digs...>::value,
_Digs...>::value};
};
- template<unsigned _Base>
+ template<unsigned long long _Base>
struct _Number<_Base>
{
- static constexpr unsigned value{0U};
+ static constexpr unsigned long long value{0ULL};
};
//------------------------------------------------------------------------------
@@ -371,7 +387,8 @@
} // namespace __parse_int
-namespace __select_int {
+namespace __select_int
+{
template<unsigned long long _Val, typename... _Ints>
struct _Select_int_base;
@@ -414,4 +431,4 @@
#endif // __cplusplus > 201103L
-#endif // _PARSE_NUMBERS_H
+#endif // _GLIBCXX_PARSE_NUMBERS_H
Index: testsuite/20_util/duration/literals/pr61166.cc
===================================================================
--- testsuite/20_util/duration/literals/pr61166.cc (revision 0)
+++ testsuite/20_util/duration/literals/pr61166.cc (working copy)
@@ -0,0 +1,37 @@
+// { 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/>.
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+void
+test03()
+{
+ using namespace std::literals::chrono_literals;
+
+ // std::numeric_limits<unsigned>::max() == 4294967295
+ VERIFY( (429496729510h).count() == 429496729510 );
+}
+
+int
+main()
+{
+ test03();
+}