Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -5612,7 +5612,11 @@ namespace chrono {
return true;
case 'Q':
if constexpr (_Is_specialization_v<_Ty, duration>) {
_Os << _STD abs(_Val.count());
if constexpr (is_unsigned_v<typename _Ty::rep>) {
_Os << _Val.count();
} else {
_Os << _STD abs(_Val.count());
}
} else {
_STL_INTERNAL_CHECK(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <timezone_data.hpp>

// Extended to test LWG-4257 "Stream insertion for chrono::local_time should be constrained"
// Extended to test GH-5945 "<chrono>: cannot format unsigned durations"

using namespace std;
using namespace chrono;
Expand Down Expand Up @@ -286,6 +287,11 @@ void test_duration_formatter() {
assert(format(STR("{:%T %j}"), duration<float, days::period>{1.55f}) == STR("37:11:59 1"));
assert(format(STR("{:%T %j}"), duration<float, days::period>{-1.55f}) == STR("-37:11:59 1"));

// GH-5945 "<chrono>: cannot format unsigned durations"
assert(format(STR("{:%T %j %q %Q}"), duration<unsigned long long, days::period>{4} + 30min)
== STR("96:30:00 4 min 5790"));
assert(format(STR("{:%T %j}"), duration<unsigned long long, days::period>{4} + 23h + 30min) == STR("119:30:00 4"));

// GH-4247: <chrono>: format() should accept %X and %EX for duration and hh_mm_ss
assert(format(STR("{:%X}"), 9h + 7min + 5s) == STR("09:07:05"));
assert(format(STR("{:%EX}"), 9h + 7min + 5s) == STR("09:07:05"));
Expand Down Expand Up @@ -1102,8 +1108,29 @@ void check_stream_insertion_operator() {
check_stream_insertion_operator_for_duration<bad_dur>();
}

// Test introduced for GH-5945 "<chrono>: cannot format unsigned durations"
void test_format_duration_with_unsigned_rep() {
// operator<<(ostream&, duration _Dur) only prints _Dur.count() (does not use abs)
{
ostringstream oss;
oss << duration<unsigned long, nano>{3};
assert(oss.str() == "3ns");
}
{
ostringstream oss;
oss << duration<long, nano>{-3};
assert(oss.str() == "-3ns");
}

// format calls abs under the hood when needed, this would be rejected before fix.
assert(format("{}", duration<long, nano>{-3}) == "-3ns");
assert(format("{}", duration<unsigned long, nano>{3}) == "3ns");
assert(format("{:%Q}", duration<unsigned long, nano>{3}) == "3");
}

void test() {
test_unsigned_sys_time_format_after_LWG_4274();
test_format_duration_with_unsigned_rep();

check_stream_insertion_operator();

Expand Down