Re: [PATCH] PR libstdc++/81468 constrain std::chrono::time_point constructor

2017-09-18 Thread Jonathan Wakely

On 13/09/17 21:30 -0400, Tim Song wrote:

On Wed, Sep 13, 2017 at 10:55 AM, Jonathan Wakely  wrote:


+// DR 1177
+static_assert(is_constructible{},
+"can convert duration with one floating point rep to another");
+static_assert(is_constructible{},
+"can convert duration with integral rep to one with floating point rep");
+static_assert(!is_constructible{},
+"cannot convert duration with floating point rep to one with integral 
rep");
+static_assert(is_constructible{},
+"can convert duration with one integral rep to another");
+
+static_assert(!is_constructible>>{},
+"cannot convert duration to one with different period");
+static_assert(is_constructible>>{},
+"unless it has a floating-point representation");


"it" is a little ambiguous here unless you read the next message's
mention of "the original"...


+static_assert(is_constructible>>{},
+"or a period that is an integral multiple of the original");


This is backwards: duration is convertible to duration iff P1 is an integral multiple of P2, i.e., if the original's
period is an integral multiple of "its" period.

The static assert only passed because duration was used as the
destination type (presumably because of a copy/paste error).

Tim


Good catch, thanks.

I've committed this patch.


commit 5c021e19e0758e5ad7e47feadbd0632b15f85785
Author: Jonathan Wakely 
Date:   Mon Sep 18 19:04:25 2017 +0100

PR libstdc++/81468 fix test for duration conversions

PR libstdc++/81468
* testsuite/20_util/duration/cons/dr1177.cc: Fix incorrect test and
improve static assertion messages.

diff --git a/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc b/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc
index 28c881ccc79..d90cd27f482 100644
--- a/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc
@@ -36,6 +36,6 @@ static_assert(is_constructible{},
 static_assert(!is_constructible>>{},
 "cannot convert duration to one with different period");
 static_assert(is_constructible>>{},
-"unless it has a floating-point representation");
-static_assert(is_constructible>>{},
-"or a period that is an integral multiple of the original");
+"... unless the result type has a floating-point representation");
+static_assert(is_constructible>, duration>{},
+"... or the original's period is a multiple of the result's period");


Re: [PATCH] PR libstdc++/81468 constrain std::chrono::time_point constructor

2017-09-13 Thread Tim Song
On Wed, Sep 13, 2017 at 10:55 AM, Jonathan Wakely  wrote:
>
> +// DR 1177
> +static_assert(is_constructible{},
> +"can convert duration with one floating point rep to another");
> +static_assert(is_constructible{},
> +"can convert duration with integral rep to one with floating point rep");
> +static_assert(!is_constructible{},
> +"cannot convert duration with floating point rep to one with integral 
> rep");
> +static_assert(is_constructible{},
> +"can convert duration with one integral rep to another");
> +
> +static_assert(!is_constructible>>{},
> +"cannot convert duration to one with different period");
> +static_assert(is_constructible>>{},
> +"unless it has a floating-point representation");

"it" is a little ambiguous here unless you read the next message's
mention of "the original"...

> +static_assert(is_constructible>>{},
> +"or a period that is an integral multiple of the original");

This is backwards: duration is convertible to duration iff P1 is an integral multiple of P2, i.e., if the original's
period is an integral multiple of "its" period.

The static assert only passed because duration was used as the
destination type (presumably because of a copy/paste error).

Tim


Re: [PATCH] PR libstdc++/81468 constrain std::chrono::time_point constructor

2017-09-13 Thread Jonathan Wakely

On 13/09/17 15:09 +0100, Jonathan Wakely wrote:

Howard reported this bug, caused by a missing SFINAE constraint on a
std::chrono::time_point constructor.

I've also done a bit of simplification using alias templates.


Here's the backport for the branches, which just adds the constraint
(and tests) without the new alias templates.


commit 4a6c846f3203dd0ceb13b7130e686833a4150d96
Author: Jonathan Wakely 
Date:   Wed Sep 13 15:16:31 2017 +0100

PR libstdc++/81468 constrain std::chrono::time_point constructor

PR libstdc++/81468
* include/std/chrono (time_point(const time_point<_Dur2>&)): Add
missing constraint from LWG DR 1177.
* testsuite/20_util/duration/cons/dr1177.cc: New.
* testsuite/20_util/time_point/cons/81468.cc: New.
* testsuite/20_util/duration/literals/range.cc: Update dg-error line.

diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index c3a6ba8f873..cc63d44657b 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -622,7 +622,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
 	{ }
 
 	// conversions
-	template
+	template>>
 	  constexpr time_point(const time_point& __t)
 	  : __d(__t.time_since_epoch())
 	  { }
diff --git a/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc b/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc
new file mode 100644
index 000..28c881ccc79
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/cons/dr1177.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 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
+// .
+
+// { dg-do compile { target c++11 } }
+
+#include 
+#include 
+
+using namespace std;
+using namespace std::chrono;
+
+// DR 1177
+static_assert(is_constructible{},
+"can convert duration with one floating point rep to another");
+static_assert(is_constructible{},
+"can convert duration with integral rep to one with floating point rep");
+static_assert(!is_constructible{},
+"cannot convert duration with floating point rep to one with integral rep");
+static_assert(is_constructible{},
+"can convert duration with one integral rep to another");
+
+static_assert(!is_constructible>>{},
+"cannot convert duration to one with different period");
+static_assert(is_constructible>>{},
+"unless it has a floating-point representation");
+static_assert(is_constructible>>{},
+"or a period that is an integral multiple of the original");
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
index c0d1a6e5885..531b53c42ec 100644
--- a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
@@ -26,6 +26,6 @@ test01()
 
   // std::numeric_limits::max() == 9223372036854775807;
   auto h = 9223372036854775808h;
-  // { dg-error "cannot be represented" "" { target *-*-* } 892 }
+  // { dg-error "cannot be represented" "" { target *-*-* } 893 }
 }
 // { dg-prune-output "in constexpr expansion" } // needed for -O0
diff --git a/libstdc++-v3/testsuite/20_util/time_point/cons/81468.cc b/libstdc++-v3/testsuite/20_util/time_point/cons/81468.cc
new file mode 100644
index 000..30d1c4a5ac7
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/time_point/cons/81468.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 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 

[PATCH] PR libstdc++/81468 constrain std::chrono::time_point constructor

2017-09-13 Thread Jonathan Wakely

Howard reported this bug, caused by a missing SFINAE constraint on a
std::chrono::time_point constructor.

I've also done a bit of simplification using alias templates.

PR libstdc++/81468
* include/std/chrono (__enable_if_is_duration)
(__disable_if_is_duration): New alias templates to simplify SFINAE.
(duration_cast, floor, ceil): Use __enable_if_is_duration.
(duration::__is_float, duration::__is_harmonic): New alias templates
to simplify SFINAE.
(duration::duration(const _Rep2&)): Use _Require, __is_float and
__is_harmonic.
(duration::duration(const duration<_Rep2, _Period2>&)): Likewise.
(__common_rep_type): Remove, replace with ...
(__common_rep_t): New alias template.
(operator*, operator/, operator%): Use __common_rep_t and
__disable_if_is_duration.
(time_point::time_point(const time_point&)): Add missing
constraint from LWG DR 1177.
* testsuite/20_util/duration/cons/dr1177.cc: New.
* testsuite/20_util/duration/literals/range.cc: Update dg-error line.
* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Likewise.
* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.
* testsuite/20_util/time_point/cons/81468.cc: New.

Tested on powerp64le-linux, committed to trunk.


commit e06db0fa47676eeb386bfd1a582a005d341fb678
Author: Jonathan Wakely 
Date:   Wed Sep 13 13:00:50 2017 +0100

PR libstdc++/81468 constrain std::chrono::time_point constructor

PR libstdc++/81468
* include/std/chrono (__enable_if_is_duration)
(__disable_if_is_duration): New alias templates to simplify SFINAE.
(duration_cast, floor, ceil): Use __enable_if_is_duration.
(duration::__is_float, duration::__is_harmonic): New alias templates
to simplify SFINAE.
(duration::duration(const _Rep2&)): Use _Require, __is_float and
__is_harmonic.
(duration::duration(const duration<_Rep2, _Period2>&)): Likewise.
(__common_rep_type): Remove, replace with ...
(__common_rep_t): New alias template.
(operator*, operator/, operator%): Use __common_rep_t and
__disable_if_is_duration.
(time_point::time_point(const time_point&)): Add 
missing
constraint from LWG DR 1177.
* testsuite/20_util/duration/cons/dr1177.cc: New.
* testsuite/20_util/duration/literals/range.cc: Update dg-error 
line.
* testsuite/20_util/duration/requirements/typedefs_neg1.cc: 
Likewise.
* testsuite/20_util/duration/requirements/typedefs_neg2.cc: 
Likewise.
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: 
Likewise.
* testsuite/20_util/time_point/cons/81468.cc: New.

diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 1bcbf524a7b..fc058fcd8d8 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -179,10 +179,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   : std::true_type
   { };
 
+template
+  using __enable_if_is_duration
+   = typename enable_if<__is_duration<_Tp>::value, _Tp>::type;
+
+template
+  using __disable_if_is_duration
+   = typename enable_if::value, _Tp>::type;
+
 /// duration_cast
 template
-  constexpr typename enable_if<__is_duration<_ToDur>::value,
-  _ToDur>::type
+  constexpr __enable_if_is_duration<_ToDur>
   duration_cast(const duration<_Rep, _Period>& __d)
   {
typedef typename _ToDur::period __to_period;
@@ -211,7 +218,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define __cpp_lib_chrono 201510
 
 template
-  constexpr enable_if_t<__is_duration<_ToDur>::value, _ToDur>
+  constexpr __enable_if_is_duration<_ToDur>
   floor(const duration<_Rep, _Period>& __d)
   {
auto __to = chrono::duration_cast<_ToDur>(__d);
@@ -221,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 
 template
-  constexpr enable_if_t<__is_duration<_ToDur>::value, _ToDur>
+  constexpr __enable_if_is_duration<_ToDur>
   ceil(const duration<_Rep, _Period>& __d)
   {
auto __to = chrono::duration_cast<_ToDur>(__d);
@@ -294,6 +301,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 template
   struct duration
   {
+  private:
+   template
+ using __is_float = treat_as_floating_point<_Rep2>;
+
+   // _Period2 is an exact multiple of _Period
+   template
+ using __is_harmonic
+   = __bool_constant::den == 1>;
+
+  public:
+
typedef _Reprep;
typedef _Period