[libcxx] r189722 - SFINAE out duration converting constructor if the constructor would otherwise cause a ratio compile-time overflow. This fixes LWG 2094.

Howard Hinnant hhinnant at apple.com
Sat Aug 31 09:51:56 PDT 2013


Author: hhinnant
Date: Sat Aug 31 11:51:56 2013
New Revision: 189722

URL: http://llvm.org/viewvc/llvm-project?rev=189722&view=rev
Log:
SFINAE out duration converting constructor if the constructor would otherwise cause a ratio compile-time overflow.  This fixes LWG 2094.

Modified:
    libcxx/trunk/include/chrono
    libcxx/trunk/test/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp
    libcxx/trunk/www/cxx1y_status.html

Modified: libcxx/trunk/include/chrono
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/chrono?rev=189722&r1=189721&r2=189722&view=diff
==============================================================================
--- libcxx/trunk/include/chrono (original)
+++ libcxx/trunk/include/chrono Sat Aug 31 11:51:56 2013
@@ -409,6 +409,37 @@ class _LIBCPP_TYPE_VIS_ONLY duration
     static_assert(!__is_duration<_Rep>::value, "A duration representation can not be a duration");
     static_assert(__is_ratio<_Period>::value, "Second template parameter of duration must be a std::ratio");
     static_assert(_Period::num > 0, "duration period must be positive");
+
+    template <class _R1, class _R2>
+    struct __no_overflow
+    {
+    private:
+        static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
+        static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
+        static const intmax_t __n1 = _R1::num / __gcd_n1_n2;
+        static const intmax_t __d1 = _R1::den / __gcd_d1_d2;
+        static const intmax_t __n2 = _R2::num / __gcd_n1_n2;
+        static const intmax_t __d2 = _R2::den / __gcd_d1_d2;
+        static const intmax_t max = -((intmax_t(1) << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1);
+
+        template <intmax_t _Xp, intmax_t _Yp, bool __overflow>
+        struct __mul    // __overflow == false
+        {
+            static const intmax_t value = _Xp * _Yp;
+        };
+
+        template <intmax_t _Xp, intmax_t _Yp>
+        struct __mul<_Xp, _Yp, true>
+        {
+            static const intmax_t value = 1;
+        };
+
+    public:
+        static const bool value = (__n1 <= max / __d2) && (__n2 <= max / __d1);
+        typedef ratio<__mul<__n1, __d2, !value>::value,
+                      __mul<__n2, __d1, !value>::value> type;
+    };
+    
 public:
     typedef _Rep rep;
     typedef _Period period;
@@ -440,9 +471,10 @@ public:
         duration(const duration<_Rep2, _Period2>& __d,
             typename enable_if
             <
+                __no_overflow<_Period2, period>::value && (
                 treat_as_floating_point<rep>::value ||
-                (ratio_divide<_Period2, period>::type::den == 1 &&
-                 !treat_as_floating_point<_Rep2>::value)
+                (__no_overflow<_Period2, period>::type::den == 1 &&
+                 !treat_as_floating_point<_Rep2>::value))
             >::type* = 0)
                 : __rep_(_VSTD::chrono::duration_cast<duration>(__d).count()) {}
 

Modified: libcxx/trunk/test/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp?rev=189722&r1=189721&r2=189722&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp (original)
+++ libcxx/trunk/test/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp Sat Aug 31 11:51:56 2013
@@ -35,6 +35,8 @@ test(const FromDuration& df, const ToDur
     }
 }
 
+#if _LIBCPP_STD_VER > 11
+
 template<class FromDuration, long long From, class ToDuration, long long To>
 void test_constexpr ()
 {
@@ -49,6 +51,8 @@ void test_constexpr ()
 
 }
 
+#endif
+
 int main()
 {
     test(std::chrono::milliseconds(7265000), std::chrono::hours(2));

Modified: libcxx/trunk/www/cxx1y_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1y_status.html?rev=189722&r1=189721&r2=189722&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1y_status.html (original)
+++ libcxx/trunk/www/cxx1y_status.html Sat Aug 31 11:51:56 2013
@@ -140,7 +140,7 @@
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2091">2091</a></td><td>Misplaced effect in m.try_lock_for()</td><td>Bristol</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2092">2092</a></td><td>Vague Wording for condition_variable_any</td><td>Bristol</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2093">2093</a></td><td>Throws clause of condition_variable::wait with predicate</td><td>Bristol</td><td>Complete</td></tr>
-	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2094">2094</a></td><td>duration conversion overflow shouldn't participate in overload resolution</td><td>Bristol</td><td></td></tr>
+	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2094">2094</a></td><td>duration conversion overflow shouldn't participate in overload resolution</td><td>Bristol</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2122">2122</a></td><td>merge() stability for lists versus forward lists</td><td>Bristol</td><td></td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2128">2128</a></td><td>Absence of global functions cbegin/cend</td><td>Bristol</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2145">2145</a></td><td>error_category default constructor</td><td>Bristol</td><td>Complete</td></tr>





More information about the cfe-commits mailing list