]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
parse_numbers.h (__parse_int::_Number_help): Check for overflow.
authorJonathan Wakely <redi@gcc.gnu.org>
Fri, 16 May 2014 11:08:49 +0000 (12:08 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 16 May 2014 11:08:49 +0000 (12:08 +0100)
* 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

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/parse_numbers.h
libstdc++-v3/include/std/chrono
libstdc++-v3/testsuite/20_util/duration/literals/range.cc [new file with mode: 0644]

index 373b7a7c9dc777f26f2229247ca2a5e99b728330..3df09012b9a03974b37f2f0371f40a8e2dcaea84 100644 (file)
@@ -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
index 0a42381a09b62f6ba2f5c8fc363d68b43cd9805a..a29d1272255da955b973f5accac1f80190d1da58 100644 (file)
@@ -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>
index b114e02f0c233ccbef09a39e968b1cd149b8b87f..39ad5e3ba83a8ac6dd3e24f6d2de7be2a34740ab 100644 (file)
@@ -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 (file)
index 0000000..c005df6
--- /dev/null
@@ -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 }
+}