From: Ed Smith-Rowland <3dw4rd@verizon.net>
To: gcc-patches <gcc-patches@gcc.gnu.org>,
"libstdc++@gcc.gnu.org" <libstdc++@gcc.gnu.org>
Subject: [PATCH, libstdc++/61166] overflow when parse number in std::duration operator""
Date: Wed, 14 May 2014 13:39:00 -0000 [thread overview]
Message-ID: <537371EF.9080901@verizon.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 189 bytes --]
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?
[-- Attachment #2: CL_pr61166 --]
[-- Type: text/plain, Size: 253 bytes --]
2014-05-14 Ed Smith-Rowland <3dw4rd@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.
[-- Attachment #3: patch_pr61166 --]
[-- Type: text/plain, Size: 13921 bytes --]
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();
+}
next reply other threads:[~2014-05-14 13:39 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-14 13:39 Ed Smith-Rowland [this message]
2014-05-14 13:59 ` Daniel Krügler
2014-05-14 14:13 ` Jonathan Wakely
2014-05-14 14:26 ` Ed Smith-Rowland
2014-05-14 14:36 ` Jonathan Wakely
2014-05-14 14:41 ` Jonathan Wakely
2014-05-14 15:36 ` Jonathan Wakely
2014-05-15 19:03 ` Jonathan Wakely
2014-05-16 2:54 ` Ed Smith-Rowland
2014-05-16 11:09 ` Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=537371EF.9080901@verizon.net \
--to=3dw4rd@verizon.net \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).