[libc++][chrono] Implements formatter year.

Partially implements:
- P1361 Integration of chrono with text formatting

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D133663
This commit is contained in:
Mark de Wever 2022-03-20 13:40:02 +01:00
parent d7c85d7e34
commit 3eb4f16b44
12 changed files with 517 additions and 5 deletions

View File

@ -10,7 +10,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local-time-format-t<Duration>``",A ``<chrono>`` implementation,Not assigned,,,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::day``",,Mark de Wever,|Complete|, Clang 16
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::month``",,Mark de Wever,|In Progress|,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::year``",,Mark de Wever,|In Progress|,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::year``",,Mark de Wever,|Complete|, Clang 16
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::weekday``",,Mark de Wever,|In Progress|,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::weekday_indexed``",,Mark de Wever,|In Progress|,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::weekday_last``",,Mark de Wever,|In Progress|,

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -11,6 +11,7 @@
#define _LIBCPP___CHRONO_CONVERT_TO_TM_H
#include <__chrono/day.h>
#include <__chrono/year.h>
#include <__concepts/same_as.h>
#include <__config>
@ -33,6 +34,8 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoCalendarTimePoint& __valu
if constexpr (same_as<_ChronoCalendarTimePoint, chrono::day>)
__result.tm_mday = static_cast<unsigned>(__value);
else if constexpr (same_as<_ChronoCalendarTimePoint, chrono::year>)
__result.tm_year = static_cast<int>(__value) - 1900;
else
static_assert(sizeof(_ChronoCalendarTimePoint) == 0, "Add the missing type specialization");

View File

@ -13,12 +13,17 @@
#include <__chrono/convert_to_tm.h>
#include <__chrono/day.h>
#include <__chrono/parser_std_format_spec.h>
#include <__chrono/statically_widen.h>
#include <__chrono/year.h>
#include <__config>
#include <__format/concepts.h>
#include <__format/format_functions.h>
#include <__format/format_parse_context.h>
#include <__format/formatter.h>
#include <__format/formatter_output.h>
#include <__format/parser_std_format_spec.h>
#include <__memory/addressof.h>
#include <cmath>
#include <ctime>
#include <sstream>
#include <string>
@ -52,6 +57,34 @@ namespace __formatter {
///
/// When no chrono-specs are provided it uses the stream formatter.
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& __sstr) {
if (__year < 0) {
__sstr << _CharT('-');
__year = -__year;
}
// TODO FMT Write an issue
// If the result has less than four digits it is zero-padded with 0 to two digits.
// is less -> has less
// left-padded -> zero-padded, otherwise the proper value would be 000-0.
// Note according to the wording it should be left padded, which is odd.
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:04}"), __year);
}
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_CharT>& __sstr) {
// TODO FMT Write an issue
// [tab:time.format.spec]
// %C The year divided by 100 using floored division. If the result is a
// single decimal digit, it is prefixed with 0.
bool __negative = __year < 0;
int __century = (__year - (99 * __negative)) / 100; // floored division
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __century);
}
template <class _CharT, class _Tp>
_LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) {
@ -74,7 +107,59 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
__sstr << *__it;
break;
case _CharT('C'): {
// strftime's output is only defined in the range [00, 99].
int __year = __t.tm_year + 1900;
if (__year < 1000 || __year > 9999)
__formatter::__format_century(__year, __sstr);
else
__facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
} break;
// Unlike time_put and strftime the formatting library requires %Y
//
// [tab:time.format.spec]
// The year as a decimal number. If the result is less than four digits
// it is left-padded with 0 to four digits.
//
// This means years in the range (-1000, 1000) need manual formatting.
// It's unclear whether %EY needs the same treatment. For example the
// Japanese EY contains the era name and year. This is zero-padded to 2
// digits in time_put (note that older glibc versions didn't do
// padding.) However most eras won't reach 100 years, let alone 1000.
// So padding to 4 digits seems unwanted for Japanese.
//
// The same applies to %Ex since that too depends on the era.
//
// %x the locale's date representation is currently doesn't handle the
// zero-padding too.
//
// The 4 digits can be implemented better at a later time. On POSIX
// systems the required information can be extracted by nl_langinfo
// https://man7.org/linux/man-pages/man3/nl_langinfo.3.html
//
// Note since year < -1000 is expected to be rare it uses the more
// expensive year routine.
//
// TODO FMT evaluate the comment above.
# if defined(__GLIBC__) || defined(_AIX)
case _CharT('y'):
// Glibc fails for negative values, AIX for positive values too.
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100);
break;
# endif // defined(__GLIBC__) || defined(_AIX)
case _CharT('Y'): {
int __year = __t.tm_year + 1900;
if (__year < 1000)
__formatter::__format_year(__year, __sstr);
else
__facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
} break;
case _CharT('O'):
case _CharT('E'):
++__it;
[[fallthrough]];
default:
@ -146,7 +231,19 @@ public:
}
};
#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year, _CharT>
: public __formatter_chrono<_CharT> {
public:
using _Base = __formatter_chrono<_CharT>;
_LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
-> decltype(__parse_ctx.begin()) {
return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year);
}
};
#endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
_LIBCPP_END_NAMESPACE_STD

View File

@ -12,6 +12,7 @@
#include <__chrono/day.h>
#include <__chrono/statically_widen.h>
#include <__chrono/year.h>
#include <__config>
#include <__format/format_functions.h>
#include <ostream>
@ -40,6 +41,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) {
: std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast<unsigned>(__d)));
}
template <class _CharT, class _Traits>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) {
return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y)
: std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y));
}
} // namespace chrono
#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)

View File

@ -355,6 +355,9 @@ constexpr year operator+(const year& x, const years& y) noexcept;
constexpr year operator+(const years& x, const year& y) noexcept;
constexpr year operator-(const year& x, const years& y) noexcept;
constexpr years operator-(const year& x, const year& y) noexcept;
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const year& y);
// 25.8.6, class weekday // C++20
class weekday;
@ -620,6 +623,7 @@ bool operator>=(const time_zone& x, const time_zone& y) noexcept;
namespace std {
template<class charT> struct formatter<chrono::day, charT>; // C++20
template<class charT> struct formatter<chrono::year, charT>; // C++20
} // namespace std
namespace chrono {

View File

@ -106,6 +106,7 @@ charconv type_traits
chrono array
chrono bit
chrono charconv
chrono cmath
chrono compare
chrono concepts
chrono cstddef

1 algorithm atomic
106 chrono array
107 chrono bit
108 chrono charconv
109 chrono cmath
110 chrono compare
111 chrono concepts
112 chrono cstddef

View File

@ -86,6 +86,7 @@ charconv type_traits
chrono array
chrono bit
chrono charconv
chrono cmath
chrono compare
chrono concepts
chrono cstddef

1 algorithm bit
86 chrono array
87 chrono bit
88 chrono charconv
89 chrono cmath
90 chrono compare
91 chrono concepts
92 chrono cstddef

View File

@ -143,7 +143,7 @@ void test_P1361() {
assert_is_formattable<std::chrono::day, CharT>();
assert_is_not_formattable<std::chrono::month, CharT>();
assert_is_not_formattable<std::chrono::year, CharT>();
assert_is_formattable<std::chrono::year, CharT>();
assert_is_not_formattable<std::chrono::weekday, CharT>();
assert_is_not_formattable<std::chrono::weekday_indexed, CharT>();

View File

@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Investigate Windows issues.
// UNSUPPORTED: msvc, target={{.+}}-windows-gnu
// REQUIRES: locale.fr_FR.UTF-8
// REQUIRES: locale.ja_JP.UTF-8
// <chrono>
// class year;
// template<class charT, class traits>
// basic_ostream<charT, traits>&
// operator<<(basic_ostream<charT, traits>& os, const year& year);
#include <chrono>
#include <cassert>
#include <sstream>
#include "make_string.h"
#include "platform_support.h" // locale name macros
#include "test_macros.h"
#define SV(S) MAKE_STRING_VIEW(CharT, S)
template <class CharT>
static std::basic_string<CharT> stream_c_locale(std::chrono::year year) {
std::basic_stringstream<CharT> sstr;
sstr << year;
return sstr.str();
}
template <class CharT>
static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::year year) {
std::basic_stringstream<CharT> sstr;
const std::locale locale(LOCALE_fr_FR_UTF_8);
sstr.imbue(locale);
sstr << year;
return sstr.str();
}
template <class CharT>
static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::year year) {
std::basic_stringstream<CharT> sstr;
const std::locale locale(LOCALE_ja_JP_UTF_8);
sstr.imbue(locale);
sstr << year;
return sstr.str();
}
template <class CharT>
static void test() {
assert(stream_c_locale<CharT>(std::chrono::year{-32'768}) == SV("-32768 is not a valid year"));
assert(stream_c_locale<CharT>(std::chrono::year{-32'767}) == SV("-32767"));
assert(stream_c_locale<CharT>(std::chrono::year{0}) == SV("0000"));
assert(stream_c_locale<CharT>(std::chrono::year{1970}) == SV("1970"));
assert(stream_c_locale<CharT>(std::chrono::year{32'767}) == SV("32767"));
assert(stream_fr_FR_locale<CharT>(std::chrono::year{-32'768}) == SV("-32768 is not a valid year"));
assert(stream_fr_FR_locale<CharT>(std::chrono::year{-32'767}) == SV("-32767"));
assert(stream_fr_FR_locale<CharT>(std::chrono::year{0}) == SV("0000"));
assert(stream_fr_FR_locale<CharT>(std::chrono::year{1970}) == SV("1970"));
assert(stream_fr_FR_locale<CharT>(std::chrono::year{32'767}) == SV("32767"));
assert(stream_ja_JP_locale<CharT>(std::chrono::year{-32'768}) == SV("-32768 is not a valid year"));
assert(stream_ja_JP_locale<CharT>(std::chrono::year{-32'767}) == SV("-32767"));
assert(stream_ja_JP_locale<CharT>(std::chrono::year{0}) == SV("0000"));
assert(stream_ja_JP_locale<CharT>(std::chrono::year{1970}) == SV("1970"));
assert(stream_ja_JP_locale<CharT>(std::chrono::year{32'767}) == SV("32767"));
}
int main(int, char**) {
test<char>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
#endif
return 0;
}

View File

@ -0,0 +1,308 @@
//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Investigate Windows issues.
// UNSUPPORTED: msvc, target={{.+}}-windows-gnu
// REQUIRES: locale.fr_FR.UTF-8
// REQUIRES: locale.ja_JP.UTF-8
// <chrono>
// template<class charT> struct formatter<chrono::year, charT>;
#include <chrono>
#include <format>
#include <cassert>
#include <concepts>
#include <locale>
#include <iostream>
#include <type_traits>
#include "formatter_tests.h"
#include "make_string.h"
#include "platform_support.h" // locale name macros
#include "string_literal.h"
#include "test_macros.h"
template <class CharT>
static void test_no_chrono_specs() {
check(SV("-32767"), SV("{}"), std::chrono::year{-32'767});
check(SV("-1000"), SV("{}"), std::chrono::year{-1000});
check(SV("-0100"), SV("{}"), std::chrono::year{-100});
check(SV("-0010"), SV("{}"), std::chrono::year{-10});
check(SV("-0001"), SV("{}"), std::chrono::year{-1});
check(SV("0000"), SV("{}"), std::chrono::year{0});
check(SV("0001"), SV("{}"), std::chrono::year{1});
check(SV("0010"), SV("{}"), std::chrono::year{10});
check(SV("0100"), SV("{}"), std::chrono::year{100});
check(SV("1000"), SV("{}"), std::chrono::year{1000});
check(SV("32727"), SV("{}"), std::chrono::year{32'727});
// Invalid year
check(SV("-32768 is not a valid year"), SV("{}"), std::chrono::year{-32'768});
check(SV("-32768 is not a valid year"), SV("{}"), std::chrono::year{32'768});
}
template <class CharT>
static void test_valid_values() {
constexpr std::basic_string_view<CharT> fmt = SV(
"{:"
"%%C='%C'%t"
"%%EC='%EC'%t"
"%%y='%y'%t"
"%%Ey='%Ey'%t"
"%%Oy='%Oy'%t"
"%%Y='%Y'%t"
"%%EY='%EY'%t"
"%n}");
constexpr std::basic_string_view<CharT> lfmt = SV(
"{:L"
"%%C='%C'%t"
"%%EC='%EC'%t"
"%%y='%y'%t"
"%%Ey='%Ey'%t"
"%%Oy='%Oy'%t"
"%%Y='%Y'%t"
"%%EY='%EY'%t"
"%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%C='00'\t"
#if defined(__APPLE__)
"%EC='00'\t"
#else
"%EC='0'\t"
#endif
"%y='00'\t"
"%Ey='00'\t"
"%Oy='00'\t"
"%Y='0000'\t"
#if defined(__APPLE__)
"%EY='0000'\t"
#elif defined(_AIX)
"%EY=''\t"
#else
"%EY='0'\t"
#endif
"\n"),
fmt,
std::chrono::year{0});
check(SV("%C='19'\t"
"%EC='19'\t"
"%y='70'\t"
"%Ey='70'\t"
"%Oy='70'\t"
"%Y='1970'\t"
"%EY='1970'\t"
"\n"),
fmt,
std::chrono::year{1970});
check(SV("%C='20'\t"
"%EC='20'\t"
"%y='38'\t"
"%Ey='38'\t"
"%Oy='38'\t"
"%Y='2038'\t"
"%EY='2038'\t"
"\n"),
fmt,
std::chrono::year{2038});
// Use the global locale (fr_FR)
check(SV("%C='00'\t"
#if defined(__APPLE__)
"%EC='00'\t"
#else
"%EC='0'\t"
#endif
"%y='00'\t"
"%Ey='00'\t"
"%Oy='00'\t"
"%Y='0000'\t"
#if defined(__APPLE__)
"%EY='0000'\t"
#elif defined(_AIX)
"%EY=''\t"
#else
"%EY='0'\t"
#endif
"\n"),
lfmt,
std::chrono::year{0});
check(SV("%C='19'\t"
"%EC='19'\t"
"%y='70'\t"
"%Ey='70'\t"
"%Oy='70'\t"
"%Y='1970'\t"
"%EY='1970'\t"
"\n"),
lfmt,
std::chrono::year{1970});
check(SV("%C='20'\t"
"%EC='20'\t"
"%y='38'\t"
"%Ey='38'\t"
"%Oy='38'\t"
"%Y='2038'\t"
"%EY='2038'\t"
"\n"),
lfmt,
std::chrono::year{2038});
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(__APPLE__) || defined(_AIX)
check(SV("%C='00'\t"
# if defined(__APPLE__)
"%EC='00'\t"
# else
"%EC='0'\t"
# endif
"%y='00'\t"
"%Ey='00'\t"
"%Oy='00'\t"
"%Y='0000'\t"
# if defined(_AIX)
"%EY=''\t"
# else
"%EY='0000'\t"
# endif
"\n"),
lfmt,
std::chrono::year{0});
check(SV("%C='19'\t"
"%EC='19'\t"
"%y='70'\t"
"%Ey='70'\t"
"%Oy='70'\t"
"%Y='1970'\t"
"%EY='1970'\t"
"\n"),
lfmt,
std::chrono::year{1970});
check(SV("%C='20'\t"
"%EC='20'\t"
"%y='38'\t"
"%Ey='38'\t"
"%Oy='38'\t"
"%Y='2038'\t"
"%EY='2038'\t"
"\n"),
lfmt,
std::chrono::year{2038});
#else // defined(__APPLE__) || defined(_AIX)
check(loc,
SV("%C='00'\t"
"%EC='紀元前'\t"
"%y='00'\t"
// https://sourceware.org/bugzilla/show_bug.cgi?id=23758
# if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
"%Ey='1'\t"
# else
"%Ey='01'\t"
# endif
"%Oy=''\t"
"%Y='0000'\t"
// https://sourceware.org/bugzilla/show_bug.cgi?id=23758
# if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
"%EY='紀元前1年'\t"
# else
"%EY='紀元前01年'\t"
# endif
"\n"),
lfmt,
std::chrono::year{0});
check(loc,
SV("%C='19'\t"
"%EC='昭和'\t"
"%y='70'\t"
"%Ey='45'\t"
"%Oy='七十'\t"
"%Y='1970'\t"
"%EY='昭和45年'\t"
"\n"),
lfmt,
std::chrono::year{1970});
// Note this test will fail if the Reiwa era ends before 2038.
check(loc,
SV("%C='20'\t"
"%EC='令和'\t"
"%y='38'\t"
"%Ey='20'\t"
"%Oy='三十八'\t"
"%Y='2038'\t"
"%EY='令和20年'\t"
"\n"),
lfmt,
std::chrono::year{2038});
#endif // defined(__APPLE__) || defined(_AIX)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_padding() {
constexpr std::basic_string_view<CharT> fmt = SV("{:%%C='%C'%t%%y='%y'%t%%Y='%Y'%t%n}");
check(SV("%C='-100'\t%y='99'\t%Y='-9999'\t\n"), fmt, std::chrono::year{-9'999});
check(SV("%C='-10'\t%y='99'\t%Y='-0999'\t\n"), fmt, std::chrono::year{-999});
check(SV("%C='-1'\t%y='99'\t%Y='-0099'\t\n"), fmt, std::chrono::year{-99});
check(SV("%C='-1'\t%y='09'\t%Y='-0009'\t\n"), fmt, std::chrono::year{-9});
check(SV("%C='00'\t%y='00'\t%Y='0000'\t\n"), fmt, std::chrono::year{0});
check(SV("%C='00'\t%y='09'\t%Y='0009'\t\n"), fmt, std::chrono::year{9});
check(SV("%C='00'\t%y='99'\t%Y='0099'\t\n"), fmt, std::chrono::year{99});
check(SV("%C='09'\t%y='99'\t%Y='0999'\t\n"), fmt, std::chrono::year{999});
check(SV("%C='99'\t%y='99'\t%Y='9999'\t\n"), fmt, std::chrono::year{9'999});
check(SV("%C='100'\t%y='00'\t%Y='10000'\t\n"), fmt, std::chrono::year{10'000});
}
template <class CharT>
static void test() {
test_no_chrono_specs<CharT>();
test_valid_values<CharT>();
test_padding<CharT>();
check_invalid_types<CharT>(
{SV("C"), SV("y"), SV("Y"), SV("EC"), SV("Ey"), SV("EY"), SV("Oy")}, std::chrono::year{1970});
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:A"), std::chrono::year{1970});
check_exception("The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::year{1970});
check_exception("End of input while parsing the modifier chrono conversion-spec", SV("{:%"), std::chrono::year{1970});
check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::year{1970});
check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::year{1970});
// Precision not allowed
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:.3}"), std::chrono::year{1970});
}
int main(int, char**) {
test<char>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
#endif
return 0;
}

View File

@ -185,7 +185,7 @@ void test_P1361() {
assert_formatter_is_enabled<std::chrono::day, CharT>();
assert_formatter_is_disabled<std::chrono::month, CharT>();
assert_formatter_is_disabled<std::chrono::year, CharT>();
assert_formatter_is_enabled<std::chrono::year, CharT>();
assert_formatter_is_disabled<std::chrono::weekday, CharT>();
assert_formatter_is_disabled<std::chrono::weekday_indexed, CharT>();

View File

@ -190,7 +190,7 @@ check-generated-output)
! grep -rn '[^ -~]' libcxx/include libcxx/src libcxx/test libcxx/benchmarks \
--exclude '*.dat' \
--exclude 'format_tests.h' \
--exclude 'formatter.day.pass.cpp' \
--exclude 'formatter.*.pass.cpp' \
--exclude 'grep.pass.cpp' \
--exclude 'locale-specific_form.pass.cpp' \
--exclude 'std_format_spec_string_unicode.bench.cpp' \