[libcxx-commits] [libcxx] r357410 - Fix PR41130 - 'operator/ of std::chrono::duration and custom type'. Thanks to Zulan for the report, and Howard for the direction of the fix.

Marshall Clow via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 1 09:38:03 PDT 2019


Author: marshall
Date: Mon Apr  1 09:38:02 2019
New Revision: 357410

URL: http://llvm.org/viewvc/llvm-project?rev=357410&view=rev
Log:
Fix PR41130 - 'operator/ of std::chrono::duration and custom type'. Thanks to Zulan for the report, and Howard for the direction of the fix.

Modified:
    libcxx/trunk/include/chrono
    libcxx/trunk/test/std/utilities/time/rep.h
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_divide=.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=duration.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=rep.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_times=.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_divide_rep.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_mod_rep.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_times_rep.pass.cpp

Modified: libcxx/trunk/include/chrono
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/chrono?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/include/chrono (original)
+++ libcxx/trunk/include/chrono Mon Apr  1 09:38:02 2019
@@ -1262,34 +1262,15 @@ operator*(const _Rep1& __s, const durati
 
 // Duration /
 
-template <class _Duration, class _Rep, bool = __is_duration<_Rep>::value>
-struct __duration_divide_result
-{
-};
-
-template <class _Duration, class _Rep2,
-    bool = is_convertible<_Rep2,
-                          typename common_type<typename _Duration::rep, _Rep2>::type>::value>
-struct __duration_divide_imp
-{
-};
-
-template <class _Rep1, class _Period, class _Rep2>
-struct __duration_divide_imp<duration<_Rep1, _Period>, _Rep2, true>
-{
-    typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period> type;
-};
-
-template <class _Rep1, class _Period, class _Rep2>
-struct __duration_divide_result<duration<_Rep1, _Period>, _Rep2, false>
-    : __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>
-{
-};
-
 template <class _Rep1, class _Period, class _Rep2>
 inline _LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR
-typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
+typename enable_if
+<
+    !__is_duration<_Rep2>::value &&
+      is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
+    duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+>::type
 operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
 {
     typedef typename common_type<_Rep1, _Rep2>::type _Cr;
@@ -1312,7 +1293,12 @@ operator/(const duration<_Rep1, _Period1
 template <class _Rep1, class _Period, class _Rep2>
 inline _LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR
-typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
+typename enable_if
+<
+    !__is_duration<_Rep2>::value &&
+      is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
+    duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+>::type
 operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
 {
     typedef typename common_type<_Rep1, _Rep2>::type _Cr;

Modified: libcxx/trunk/test/std/utilities/time/rep.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/rep.h?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/rep.h (original)
+++ libcxx/trunk/test/std/utilities/time/rep.h Mon Apr  1 09:38:02 2019
@@ -25,4 +25,40 @@ public:
     Rep& operator/=(Rep x) {data_ /= x.data_; return *this;}
 };
 
+// This is PR#41130
+
+struct NotARep {};
+
+// std::chrono:::duration has only '*', '/' and '%' taking a "Rep" parameter
+
+// Multiplication is commutative, division is not.
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>
+operator*(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
+
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>
+operator*(NotARep, std::chrono::duration<Rep, Period> d) { return d; }
+
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>
+operator/(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
+
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>
+operator%(std::chrono::duration<Rep, Period> d, NotARep) { return d; }
+
+// op= is not commutative.
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>&
+operator*=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
+
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>&
+operator/=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
+
+template <class Rep, class Period>
+std::chrono::duration<Rep, Period>&
+operator%=(std::chrono::duration<Rep, Period>& d, NotARep) { return d; }
+
 #endif  // REP_H

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_divide=.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_divide%3D.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_divide=.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_divide=.pass.cpp Mon Apr  1 09:38:02 2019
@@ -16,6 +16,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 #if TEST_STD_VER > 14
 constexpr bool test_constexpr()
@@ -38,5 +39,14 @@ int main(int, char**)
     static_assert(test_constexpr(), "");
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    std::chrono::nanoseconds d(5);
+    NotARep n;
+    d /= n;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=duration.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod%3Dduration.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=duration.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=duration.pass.cpp Mon Apr  1 09:38:02 2019
@@ -16,6 +16,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 #if TEST_STD_VER > 14
 constexpr bool test_constexpr()
@@ -42,5 +43,14 @@ int main(int, char**)
     static_assert(test_constexpr(), "");
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    std::chrono::nanoseconds d(5);
+    NotARep n;
+    d %= n;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=rep.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod%3Drep.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=rep.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_mod=rep.pass.cpp Mon Apr  1 09:38:02 2019
@@ -17,6 +17,11 @@
 
 #include "test_macros.h"
 
+class NotARep {};
+
+typedef std::chrono::seconds Duration;
+Duration operator%=(Duration d, NotARep) { return d; }
+
 #if TEST_STD_VER > 14
 constexpr bool test_constexpr()
 {
@@ -38,5 +43,15 @@ int main(int, char**)
     static_assert(test_constexpr(), "");
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    Duration d(5);
+    NotARep n;
+    d %= n;
+    assert(d.count() == 5);
+    }
+#endif
+
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_times=.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_times%3D.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_times=.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.arithmetic/op_times=.pass.cpp Mon Apr  1 09:38:02 2019
@@ -16,6 +16,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 #if TEST_STD_VER > 14
 constexpr bool test_constexpr()
@@ -38,5 +39,14 @@ int main(int, char**)
     static_assert(test_constexpr(), "");
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    std::chrono::nanoseconds d(5);
+    NotARep n;
+    d *= n;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_divide_rep.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_divide_rep.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_divide_rep.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_divide_rep.pass.cpp Mon Apr  1 09:38:02 2019
@@ -19,11 +19,14 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 int main(int, char**)
 {
     {
-    std::chrono::nanoseconds ns(15);
+    typedef std::chrono::nanoseconds Dur;
+    Dur ns(15);
+    ASSERT_SAME_TYPE(Dur, decltype(ns / 5));
     ns = ns / 5;
     assert(ns.count() == 3);
     }
@@ -35,5 +38,16 @@ int main(int, char**)
     }
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    typedef std::chrono::nanoseconds Duration;
+    Duration d(5);
+    NotARep n;
+    ASSERT_SAME_TYPE(Duration, decltype(d / n));
+    d = d / n;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_mod_rep.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_mod_rep.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_mod_rep.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_mod_rep.pass.cpp Mon Apr  1 09:38:02 2019
@@ -19,11 +19,14 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 int main(int, char**)
 {
     {
-    std::chrono::nanoseconds ns(15);
+    typedef std::chrono::nanoseconds Dur;
+    Dur ns(15);
+    ASSERT_SAME_TYPE(Dur, decltype(ns % 6));
     ns = ns % 6;
     assert(ns.count() == 3);
     }
@@ -35,5 +38,16 @@ int main(int, char**)
     }
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is PR#41130
+    typedef std::chrono::seconds Duration;
+    Duration d(5);
+    NotARep n;
+    ASSERT_SAME_TYPE(Duration, decltype(d % n));
+    d = d % n;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_times_rep.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_times_rep.pass.cpp?rev=357410&r1=357409&r2=357410&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_times_rep.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.duration/time.duration.nonmember/op_times_rep.pass.cpp Mon Apr  1 09:38:02 2019
@@ -24,6 +24,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "../../rep.h"
 
 int main(int, char**)
 {
@@ -34,6 +35,7 @@ int main(int, char**)
     ns = 6 * ns;
     assert(ns.count() == 90);
     }
+
 #if TEST_STD_VER >= 11
     {
     constexpr std::chrono::nanoseconds ns(3);
@@ -44,5 +46,19 @@ int main(int, char**)
     }
 #endif
 
+#if TEST_STD_VER >= 11
+    { // This is related to PR#41130
+    typedef std::chrono::nanoseconds Duration;
+    Duration d(5);
+    NotARep n;
+    ASSERT_SAME_TYPE(Duration, decltype(d * n));
+    ASSERT_SAME_TYPE(Duration, decltype(n * d));
+    d = d * n;
+    assert(d.count() == 5);
+    d = n * d;
+    assert(d.count() == 5);
+    }
+#endif
+
   return 0;
 }




More information about the libcxx-commits mailing list