From 817069bab77415e2609114211a1228b3a9c0a797 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 15:56:48 -0700 Subject: [PATCH 01/45] Code review: Adjust newlines. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index fe47c696b0d..fce9d67960e 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -366,9 +366,11 @@ _NODISCARD constexpr const _CharT* _Parse_nonnegative_integer( _Value = _Value * 10 + static_cast(*_Begin - '0'); ++_Begin; } while (_Begin != _End && '0' <= *_Begin && *_Begin <= '9'); + if (_Value > _Max_int) { throw format_error("Number is too big"); } + return _Begin; } @@ -404,12 +406,14 @@ _NODISCARD constexpr const _CharT* _Parse_arg_id( } else { ++_Begin; } + // The format string shouldn't end right after the index number. // The only things permitted after the index are the end of the replacement field ('}') // or the beginning of the format spec (':'). if (_Begin == _End || (*_Begin != '}' && *_Begin != ':')) { throw format_error("Invalid format string."); } + _Callbacks._On_manual_id(_Index); return _Begin; } @@ -474,7 +478,6 @@ _NODISCARD inline int _Code_units_in_next_character(const wchar_t* _First, const // Returns a count of the number of code units that compose the first encoded character in // [_First, _Last), or -1 if [_First, _Last) doesn't contain an entire encoded character or // *_First is an unpaired surrogate. - _STL_INTERNAL_CHECK(_First < _Last); if (*_First < 0xD800u || *_First >= 0xE000u) { @@ -503,9 +506,11 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, throw format_error("Invalid format string."); } auto _Align_pt = _Begin + _Units; + if (_Align_pt == _End) { _Align_pt = _Begin; } + for (;;) { switch (*_Align_pt) { case '<': @@ -518,6 +523,7 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, _Parsed_align = _Align::_Center; break; } + if (_Parsed_align != _Align::_None) { if (_Align_pt != _Begin) { if (*_Begin == '{') { @@ -535,6 +541,7 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, } _Align_pt = _Begin; } + return _Begin; } @@ -603,6 +610,7 @@ _NODISCARD constexpr const _CharT* _Parse_width( if (_Begin != _End) { _Begin = _Parse_arg_id(_Begin, _End, _Width_adapter<_CharT, _Callbacks_type>{_Callbacks}); } + if (_Begin == _End || *_Begin != '}') { throw format_error("Invalid format string."); } @@ -636,6 +644,7 @@ _NODISCARD constexpr const _CharT* _Parse_precision( } else { throw format_error("Missing precision specifier."); } + return _Begin; } @@ -709,6 +718,7 @@ _NODISCARD constexpr const _CharT* _Parse_format_specs( if (*_Begin != '}') { _Callbacks._On_type(*_Begin++); } + return _Begin; } @@ -733,6 +743,7 @@ _NODISCARD constexpr const _CharT* _Parse_replacement_field( if (_Begin != _End) { _Ch = *_Begin; } + if (_Ch == '}') { _Handler._On_replacement_field(_Adapter._Arg_id, _Begin); } else if (_Ch == ':') { @@ -744,6 +755,7 @@ _NODISCARD constexpr const _CharT* _Parse_replacement_field( throw format_error("Missing '}' in format string."); } } + return _Begin + 1; } @@ -900,6 +912,7 @@ _NODISCARD constexpr basic_format_arg<_Context> _Get_arg(const _Context& _Ctx, s if (!_Arg) { throw format_error("Argument not found."); } + return _Arg; } @@ -951,6 +964,7 @@ _NODISCARD constexpr int _Get_dynamic_specs(const _FormatArg _Arg) { if (_Val > (numeric_limits::max)()) { throw format_error("Number is too big."); } + return static_cast(_Val); } @@ -1023,6 +1037,7 @@ private: if (_Idx > static_cast((numeric_limits::max)())) { throw format_error("Dynamic width or precision index too large."); } + return static_cast(_Idx); } }; @@ -1522,9 +1537,11 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _CharT* _Value) { if (!_Value) { throw format_error("String pointer is null."); } + while (*_Value) { *_Out++ = *_Value++; } + return _Out; } @@ -2160,6 +2177,7 @@ _NODISCARD constexpr int _Unicode_width_estimate(const char32_t _Ch) noexcept { } _Result ^= 1; } + return 1; } @@ -2365,6 +2383,7 @@ struct _Format_handler { _Arg._Custom_state.format(_Parse_context, _Ctx); return _Parse_context.begin()._Unwrapped(); } + _Basic_format_specs<_CharT> _Specs; _Specs_checker<_Specs_handler, _Context>> _Handler( _Specs_handler, _Context>(_Specs, _Parse_context, _Ctx), @@ -2373,6 +2392,7 @@ struct _Format_handler { if (_Begin == _End || *_Begin != '}') { throw format_error("Missing '}' in format string."); } + _Ctx.advance_to(_STD visit_format_arg( _Arg_formatter<_OutputIt, _CharT>{._Ctx = _STD addressof(_Ctx), ._Specs = _STD addressof(_Specs)}, _Arg)); return _Begin; @@ -2407,10 +2427,12 @@ struct _Formatter_base { _Specs._Width = _Get_dynamic_specs<_Width_checker>(_FormatCtx.arg(static_cast(_Specs._Dynamic_width_index))); } + if (_Specs._Dynamic_precision_index >= 0) { _Specs._Precision = _Get_dynamic_specs<_Precision_checker>( _FormatCtx.arg(static_cast(_Specs._Dynamic_precision_index))); } + return _STD visit_format_arg( _Arg_formatter{ ._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Specs)}, From 4dc999c477696a744c92ab6ffb9c36d4880aef23 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 15:58:18 -0700 Subject: [PATCH 02/45] Code review: Add const. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index fce9d67960e..cfaf8b73b78 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -174,7 +174,8 @@ public: using const_iterator = typename basic_string_view<_CharT>::const_iterator; using iterator = const_iterator; - constexpr explicit basic_format_parse_context(basic_string_view<_CharT> _Fmt, size_t _Num_args_ = 0) noexcept + constexpr explicit basic_format_parse_context( + const basic_string_view<_CharT> _Fmt, const size_t _Num_args_ = 0) noexcept : _Format_string(_Fmt), _Num_args(_Num_args_) {} basic_format_parse_context(const basic_format_parse_context&) = delete; @@ -556,7 +557,7 @@ struct _Width_adapter { constexpr void _On_auto_id() { _Callbacks._On_dynamic_width(_Auto_id_tag{}); } - constexpr void _On_manual_id(size_t _Id) { + constexpr void _On_manual_id(const size_t _Id) { _Callbacks._On_dynamic_width(_Id); } }; @@ -572,7 +573,7 @@ struct _Precision_adapter { constexpr void _On_auto_id() { _Callbacks._On_dynamic_precision(_Auto_id_tag{}); } - constexpr void _On_manual_id(size_t _Id) { + constexpr void _On_manual_id(const size_t _Id) { _Callbacks._On_dynamic_precision(_Id); } }; @@ -590,7 +591,7 @@ struct _Id_adapter { _Arg_id = _Parse_context.next_arg_id(); _STL_INTERNAL_CHECK(_Arg_id != static_cast(-1)); } - constexpr void _On_manual_id(size_t _Id) { + constexpr void _On_manual_id(const size_t _Id) { _Parse_context.check_arg_id(_Id); _Arg_id = _Id; _STL_INTERNAL_CHECK(_Arg_id != static_cast(-1)); @@ -852,11 +853,11 @@ class _Specs_setter { public: explicit constexpr _Specs_setter(_Basic_format_specs<_CharT>& _Specs_) : _Specs(_Specs_) {} - constexpr void _On_align(_Align _Aln) { + constexpr void _On_align(const _Align _Aln) { _Specs._Alignment = _Aln; } - constexpr void _On_fill(basic_string_view<_CharT> _Sv) { + constexpr void _On_fill(const basic_string_view<_CharT> _Sv) { if (_Sv.size() > _STD size(_Specs._Fill)) { throw format_error("Invalid fill (too long)."); } @@ -866,7 +867,7 @@ public: _Specs._Fill_length = static_cast(_Sv.size()); } - constexpr void _On_sign(_Sign _Sgn) { + constexpr void _On_sign(const _Sign _Sgn) { _Specs._Sgn = _Sgn; } @@ -878,11 +879,11 @@ public: _Specs._Leading_zero = true; } - constexpr void _On_width(int _Width) { + constexpr void _On_width(const int _Width) { _Specs._Width = _Width; } - constexpr void _On_precision(int _Precision) { + constexpr void _On_precision(const int _Precision) { _Specs._Precision = _Precision; } @@ -890,7 +891,7 @@ public: _Specs._Localized = true; } - constexpr void _On_type(_CharT _Type) { + constexpr void _On_type(const _CharT _Type) { // performance note: this could be optimized to one comparison by // first casting to unsigned int (the negative values will be 128-255) if (_Type < 0 || _Type > (numeric_limits::max)()) { @@ -904,7 +905,7 @@ protected: }; template -_NODISCARD constexpr basic_format_arg<_Context> _Get_arg(const _Context& _Ctx, size_t _Arg_id) { +_NODISCARD constexpr basic_format_arg<_Context> _Get_arg(const _Context& _Ctx, const size_t _Arg_id) { // note: while this is parameterized on the _Arg_id type in libfmt we don't // need to do that in std::format because it's only called with either an integer // id or a named id (which we do not support in std::format) @@ -921,7 +922,7 @@ _NODISCARD constexpr basic_format_arg<_Context> _Get_arg(const _Context& _Ctx, s class _Width_checker { public: template - _NODISCARD constexpr unsigned long long operator()(_Ty _Value) { + _NODISCARD constexpr unsigned long long operator()(const _Ty _Value) const { if constexpr (is_integral_v<_Ty>) { if constexpr (is_signed_v<_Ty>) { if (_Value < 0) { @@ -940,7 +941,7 @@ public: class _Precision_checker { public: template - _NODISCARD constexpr unsigned long long operator()(_Ty _Value) { + _NODISCARD constexpr unsigned long long operator()(const _Ty _Value) const { if constexpr (is_integral_v<_Ty>) { if constexpr (is_signed_v<_Ty>) { if (_Value < 0) { @@ -1081,7 +1082,7 @@ private: _Numeric_specs_checker _Numeric_checker; public: - constexpr explicit _Specs_checker(const _Handler& _Handler_inst, _Basic_format_arg_type _Arg_type_) + constexpr explicit _Specs_checker(const _Handler& _Handler_inst, const _Basic_format_arg_type _Arg_type_) : _Handler(_Handler_inst), _Numeric_checker(_Arg_type_) {} // _On_align has no checking, since we don't implement numeric alignments. @@ -2370,13 +2371,13 @@ struct _Format_handler { _Ctx.advance_to(_RANGES _Copy_unchecked(_Begin, _End, _Ctx.out()).out); } - void _On_replacement_field(size_t _Id, const _CharT*) { + void _On_replacement_field(const size_t _Id, const _CharT*) { auto _Arg = _Ctx.arg(_Id); _Ctx.advance_to(_STD visit_format_arg( _Default_arg_formatter<_OutputIt, _CharT>{_Ctx.out(), _Ctx._Get_args(), _Ctx.locale()}, _Arg)); } - const _CharT* _On_format_specs(size_t _Id, const _CharT* _Begin, const _CharT* _End) { + const _CharT* _On_format_specs(const size_t _Id, const _CharT* _Begin, const _CharT* _End) { _Parse_context.advance_to(_Parse_context.begin() + (_Begin - &*_Parse_context.begin())); auto _Arg = _Ctx.arg(_Id); if (_Arg._Active_state == _Basic_format_arg_type::_Custom_type) { From b68c1b466db3abd64ca10f439d5039999ed510dd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 15:58:57 -0700 Subject: [PATCH 03/45] Code review: Add noexcept. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index cfaf8b73b78..9833f13995c 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1116,7 +1116,7 @@ concept _Has_formatter = requires(const _Ty& _Val, _Context& _Ctx) { // clang-format on template -_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type); +_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) noexcept; // See N4878 [format.arg]/5 // clang-format off @@ -1414,13 +1414,13 @@ public: _OutputIt = _STD move(_It); } - _NODISCARD const basic_format_args& _Get_args() const { + _NODISCARD const basic_format_args& _Get_args() const noexcept { return _Args; } }; template -_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) { +_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) noexcept { switch (_Type) { case _Basic_format_arg_type::_Int_type: return sizeof(int); @@ -1595,7 +1595,7 @@ _NODISCARD _OutputIt _Write_aligned(_OutputIt _Out, const int _Width, const _Bas } template -_NODISCARD constexpr string_view _Get_integral_prefix(const char _Type, const _Integral _Value) { +_NODISCARD constexpr string_view _Get_integral_prefix(const char _Type, const _Integral _Value) noexcept { switch (_Type) { case 'b': return "0b"sv; From ca581bd62a9746497fc6d081301febbbd87f715c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 16:03:19 -0700 Subject: [PATCH 04/45] Code review: Fix comment typo. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 9833f13995c..63a65a5fad0 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1097,7 +1097,7 @@ public: constexpr void _On_zero() { // Note 0 is again not valid for CharT or bool unless a numeric - // presentation type is uesd. + // presentation type is used. _Numeric_checker._Require_numeric_argument(); _Handler::_On_zero(); } From 7a8095831fcb6f34b234026dd9b064840f1c7cdc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 16:08:18 -0700 Subject: [PATCH 05/45] Code review: Shrink "clang-format off" region. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 63a65a5fad0..7e017151e92 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -153,6 +153,7 @@ concept _Parse_spec_callbacks = _Parse_align_callbacks<_Ty, _CharT> { _At._On_localized() } -> same_as; { _At._On_type(_CharT{}) } -> same_as; }; +// clang-format on template concept _CharT_or_bool = same_as<_Ty, _CharT> || same_as<_Ty, bool>; @@ -160,8 +161,6 @@ concept _CharT_or_bool = same_as<_Ty, _CharT> || same_as<_Ty, bool>; template concept _Format_supported_charT = _Is_any_of_v<_CharT, char, wchar_t>; -// clang-format on - template struct formatter; From 4c2e42e44d2dd02f76335c74c0f5e04741414241 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 16:15:48 -0700 Subject: [PATCH 06/45] Code review: Refactor postincrement. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 7e017151e92..36a58765495 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -716,7 +716,8 @@ _NODISCARD constexpr const _CharT* _Parse_format_specs( // If there's anything remaining we assume it's a type. if (*_Begin != '}') { - _Callbacks._On_type(*_Begin++); + _Callbacks._On_type(*_Begin); + ++_Begin; } return _Begin; From 8953f9c67a0e9946c0ce31a981f35e686b2206e2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 16:56:18 -0700 Subject: [PATCH 07/45] Code review: Avoid negated condition. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 36a58765495..e04e36bd895 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -401,10 +401,10 @@ _NODISCARD constexpr const _CharT* _Parse_arg_id( // equal to zero (but not '00'). So if _Ch is zero we skip the parsing, leave // _Index set to zero and let the validity checks below ensure that the arg_id // wasn't something like "00", or "023". - if (_Ch != '0') { - _Begin = _Parse_nonnegative_integer(_Begin, _End, _Index); - } else { + if (_Ch == '0') { ++_Begin; + } else { + _Begin = _Parse_nonnegative_integer(_Begin, _End, _Index); } // The format string shouldn't end right after the index number. From 6d414571befb54748f9aad755dc52bfe30d8fe28 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:09:25 -0700 Subject: [PATCH 08/45] Code review: Early return in _Count_separators(). Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index e04e36bd895..bb0a17516f6 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1655,18 +1655,21 @@ _NODISCARD constexpr bool _In_bounds(const _Ty _Value) { } _NODISCARD inline int _Count_separators(size_t _Digits, const string_view _Groups) { + if (_Groups.empty()) { + return 0; + } + + // Calculate the amount of separators that are going to be inserted based on the groupings of the locale. int _Separators = 0; - if (!_Groups.empty()) { - // Calculate the amount of separators that are going to be inserted based on the groupings of the locale. - auto _Group_it = _Groups.begin(); - while (_Digits > static_cast(*_Group_it)) { - _Digits -= static_cast(*_Group_it); - ++_Separators; - if (_Group_it + 1 != _Groups.end()) { - ++_Group_it; - } + auto _Group_it = _Groups.begin(); + while (_Digits > static_cast(*_Group_it)) { + _Digits -= static_cast(*_Group_it); + ++_Separators; + if (_Group_it + 1 != _Groups.end()) { + ++_Group_it; } } + return _Separators; } From ff0ea8d91055f3cf685a55ff65fa5e51f53ef5b8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:18:20 -0700 Subject: [PATCH 09/45] Code review: Rearrange constexpr variables, use auto. This also uses 10u for clarity. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index bb0a17516f6..6d65ad1da94 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -354,9 +354,11 @@ template _NODISCARD constexpr const _CharT* _Parse_nonnegative_integer( const _CharT* _Begin, const _CharT* _End, unsigned int& _Value) { _STL_INTERNAL_CHECK(_Begin != _End && '0' <= *_Begin && *_Begin <= '9'); - _Value = 0; - constexpr unsigned int _Max_int = static_cast((numeric_limits::max)()); - constexpr unsigned int _Big_int = _Max_int / 10; + + constexpr auto _Max_int = static_cast((numeric_limits::max)()); + constexpr auto _Big_int = _Max_int / 10u; + + _Value = 0; do { if (_Value > _Big_int) { From 97b3e6f5db6383159b50052cac7165264db17584 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:21:24 -0700 Subject: [PATCH 10/45] Code review: Move comment. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 6d65ad1da94..157dba0a97e 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -499,8 +499,8 @@ _NODISCARD inline int _Code_units_in_next_character(const wchar_t* _First, const template _Callbacks_type> _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, _Callbacks_type&& _Callbacks) { - _STL_INTERNAL_CHECK(_Begin != _End && *_Begin != '}'); // align and fill + _STL_INTERNAL_CHECK(_Begin != _End && *_Begin != '}'); auto _Parsed_align = _Align::_None; const int _Units = _Code_units_in_next_character(_Begin, _End, _Getcvt()); From f4fa25f6268d34f83dae17e3efd9768f466e36c4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:29:16 -0700 Subject: [PATCH 11/45] Code review: Remove perf note, compilers optimize this. --- stl/inc/format | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 157dba0a97e..6a8a5f16c7f 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -894,8 +894,6 @@ public: } constexpr void _On_type(const _CharT _Type) { - // performance note: this could be optimized to one comparison by - // first casting to unsigned int (the negative values will be 128-255) if (_Type < 0 || _Type > (numeric_limits::max)()) { throw format_error("Invalid type specification."); } From 6ddd77da135c327028c375ca95c11a3aa81e90af Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:35:18 -0700 Subject: [PATCH 12/45] Code review: Explicitly cast from int to unsigned long long. Co-authored-by: Michael Schellenberger Costa --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 6a8a5f16c7f..30d5dbb38a9 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -962,7 +962,7 @@ template _NODISCARD constexpr int _Get_dynamic_specs(const _FormatArg _Arg) { _STL_INTERNAL_STATIC_ASSERT(_Is_any_of_v<_Handler, _Width_checker, _Precision_checker>); const unsigned long long _Val = _STD visit_format_arg(_Handler(), _Arg); - if (_Val > (numeric_limits::max)()) { + if (_Val > static_cast((numeric_limits::max)())) { throw format_error("Number is too big."); } From 176c603051f36795a52d43b411b78359917146bd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 17:47:04 -0700 Subject: [PATCH 13/45] Code review: Move _Get_format_arg_type_storage_size's definition. --- stl/inc/format | 71 ++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 30d5dbb38a9..165f22187cc 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1116,7 +1116,40 @@ concept _Has_formatter = requires(const _Ty& _Val, _Context& _Ctx) { // clang-format on template -_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) noexcept; +_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) noexcept { + switch (_Type) { + case _Basic_format_arg_type::_Int_type: + return sizeof(int); + case _Basic_format_arg_type::_UInt_type: + return sizeof(unsigned int); + case _Basic_format_arg_type::_Long_long_type: + return sizeof(long long); + case _Basic_format_arg_type::_ULong_long_type: + return sizeof(unsigned long long); + case _Basic_format_arg_type::_Bool_type: + return sizeof(bool); + case _Basic_format_arg_type::_Char_type: + return sizeof(_CharT); + case _Basic_format_arg_type::_Float_type: + return sizeof(float); + case _Basic_format_arg_type::_Double_type: + return sizeof(double); + case _Basic_format_arg_type::_Long_double_type: + return sizeof(long double); + case _Basic_format_arg_type::_Pointer_type: + return sizeof(void*); + case _Basic_format_arg_type::_CString_type: + return sizeof(const _CharT*); + case _Basic_format_arg_type::_String_type: + return sizeof(basic_string_view<_CharT>); + case _Basic_format_arg_type::_Custom_type: + return sizeof(void*) + sizeof(void (*)()); + case _Basic_format_arg_type::_None: + default: + _STL_INTERNAL_CHECK(false); + return 0; + } +} // See N4878 [format.arg]/5 // clang-format off @@ -1419,42 +1452,6 @@ public: } }; -template -_NODISCARD constexpr size_t _Get_format_arg_type_storage_size(_Basic_format_arg_type _Type) noexcept { - switch (_Type) { - case _Basic_format_arg_type::_Int_type: - return sizeof(int); - case _Basic_format_arg_type::_UInt_type: - return sizeof(unsigned int); - case _Basic_format_arg_type::_Long_long_type: - return sizeof(long long); - case _Basic_format_arg_type::_ULong_long_type: - return sizeof(unsigned long long); - case _Basic_format_arg_type::_Bool_type: - return sizeof(bool); - case _Basic_format_arg_type::_Char_type: - return sizeof(_CharT); - case _Basic_format_arg_type::_Float_type: - return sizeof(float); - case _Basic_format_arg_type::_Double_type: - return sizeof(double); - case _Basic_format_arg_type::_Long_double_type: - return sizeof(long double); - case _Basic_format_arg_type::_Pointer_type: - return sizeof(void*); - case _Basic_format_arg_type::_CString_type: - return sizeof(const _CharT*); - case _Basic_format_arg_type::_String_type: - return sizeof(basic_string_view<_CharT>); - case _Basic_format_arg_type::_Custom_type: - return sizeof(void*) + sizeof(void (*)()); - case _Basic_format_arg_type::_None: - default: - _STL_INTERNAL_CHECK(false); - return 0; - } -} - template _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, monostate) { _STL_INTERNAL_CHECK(false); From 339b67a769116ee8595dda55e5689a37e8ff1c45 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 19:48:23 -0700 Subject: [PATCH 14/45] Update header-units.json. --- stl/inc/header-units.json | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index f4c76b822dc..4d65c03055e 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -52,6 +52,7 @@ "exception", "execution", "filesystem", + "format", "forward_list", "fstream", "functional", From acd12a752fc777fae61161df6a36aa4850e78344 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 10 Apr 2021 20:08:36 -0700 Subject: [PATCH 15/45] Use the plain concepts_matrix.lst when possible. --- tests/std/tests/P0645R10_text_formatting_args/env.lst | 2 +- tests/std/tests/P0645R10_text_formatting_parse_contexts/env.lst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0645R10_text_formatting_args/env.lst b/tests/std/tests/P0645R10_text_formatting_args/env.lst index 22f1f0230a4..f3ccc8613c6 100644 --- a/tests/std/tests/P0645R10_text_formatting_args/env.lst +++ b/tests/std/tests/P0645R10_text_formatting_args/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\strict_winsdk_concepts_matrix.lst +RUNALL_INCLUDE ..\concepts_matrix.lst diff --git a/tests/std/tests/P0645R10_text_formatting_parse_contexts/env.lst b/tests/std/tests/P0645R10_text_formatting_parse_contexts/env.lst index 22f1f0230a4..f3ccc8613c6 100644 --- a/tests/std/tests/P0645R10_text_formatting_parse_contexts/env.lst +++ b/tests/std/tests/P0645R10_text_formatting_parse_contexts/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\strict_winsdk_concepts_matrix.lst +RUNALL_INCLUDE ..\concepts_matrix.lst From ddcba05a4171cff6f044bcb8a94de33cdf64b00a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:22 -0700 Subject: [PATCH 16/45] Silence "expression is always false" warning. --- stl/inc/format | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stl/inc/format b/stl/inc/format index 165f22187cc..60e9e50f2dc 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1828,7 +1828,10 @@ _NODISCARD _OutputIt _Write_integral( const bool _Write_leading_zeroes = _Specs._Leading_zero && _Specs._Alignment == _Align::_None; auto _Writer = [&, _End = _End](_OutputIt _Out) { +#pragma warning(push) +#pragma warning(disable : 4296) // '<': expression is always false _Out = _Write_sign(_STD move(_Out), _Specs._Sgn, _Value < _Integral{0}); +#pragma warning(pop) _Out = _RANGES _Copy_unchecked(_Prefix.begin(), _Prefix.end(), _STD move(_Out)).out; if (_Write_leading_zeroes && _Width < _Specs._Width) { _Out = _RANGES fill_n(_STD move(_Out), _Specs._Width - _Width, '0'); From fe384741efc0b48fa8308978a4b4508b2960dd2e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:25 -0700 Subject: [PATCH 17/45] Refine the xlocnum workaround. --- stl/inc/xlocnum | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index 8872e86d8f8..9b1c2b0bda7 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -253,9 +253,7 @@ protected: }; // STATIC numpunct::id OBJECT -#if !(defined _CRTBLD \ - && (defined _BUILDING_SATELLITE_ATOMIC_WAIT || defined _BUILDING_SATELLITE_1 \ - || defined _BUILDING_SATELLITE_2)) // TRANSITION, VSO-578955 +#if !defined(_CRTBLD) || defined(CRTDLL2) || !defined(_DLL) || defined(_M_CEE_PURE) // TRANSITION, VSO-578955 #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdllimport-static-field-def" @@ -267,8 +265,7 @@ __PURE_APPDOMAIN_GLOBAL locale::id numpunct<_Elem>::id; #ifdef __clang__ #pragma clang diagnostic pop #endif // __clang__ -#endif // !(defined _CRTBLD && (defined _BUILDING_SATELLITE_ATOMIC_WAIT || defined _BUILDING_SATELLITE_1 || defined - // _BUILDING_SATELLITE_2)) +#endif // !defined(_CRTBLD) || defined(CRTDLL2) || !defined(_DLL) || defined(_M_CEE_PURE) // CLASS TEMPLATE num_get template >> From f4c0d0946d10efb3568039ab9a43b9292fd3c313 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:28 -0700 Subject: [PATCH 18/45] Defend against macroized signbit, isnan, isinf. --- stl/inc/format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 60e9e50f2dc..2c7769da91d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1996,7 +1996,7 @@ _NODISCARD _OutputIt _Fmt_write( auto _Buffer_start = _Buffer.data(); auto _Width = static_cast(_Result.ptr - _Buffer_start); - const auto _Is_negative = _STD signbit(_Value); + const auto _Is_negative = (_STD signbit)(_Value); if (_Is_negative) { // Remove the '-', it will be dealt with directly @@ -2012,7 +2012,7 @@ _NODISCARD _OutputIt _Fmt_write( _Exponent = static_cast(_CSTD toupper(_Exponent)); } - const auto _Is_finite = !_STD isnan(_Value) && !_STD isinf(_Value); + const auto _Is_finite = !(_STD isnan)(_Value) && !(_STD isinf)(_Value); auto _Append_decimal = false; auto _Exponent_start = _Result.ptr; From e1d0081327bfc581e2b3bd6089ea51da9f6ba71c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:31 -0700 Subject: [PATCH 19/45] Use _THROW. --- stl/inc/format | 94 +++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 2c7769da91d..baf51f594dc 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -206,7 +206,7 @@ public: // _Next_arg_id < 0 means manual _NODISCARD constexpr size_t next_arg_id() { if (_Next_arg_id < 0) { - throw format_error("Can not switch from manual to automatic indexing"); + _THROW(format_error("Can not switch from manual to automatic indexing")); } return static_cast(_Next_arg_id++); @@ -220,7 +220,7 @@ public: } if (_Next_arg_id > 0) { - throw format_error("Can not switch from automatic to manual indexing"); + _THROW(format_error("Can not switch from automatic to manual indexing")); } _Next_arg_id = -1; } @@ -370,7 +370,7 @@ _NODISCARD constexpr const _CharT* _Parse_nonnegative_integer( } while (_Begin != _End && '0' <= *_Begin && *_Begin <= '9'); if (_Value > _Max_int) { - throw format_error("Number is too big"); + _THROW(format_error("Number is too big")); } return _Begin; @@ -413,14 +413,14 @@ _NODISCARD constexpr const _CharT* _Parse_arg_id( // The only things permitted after the index are the end of the replacement field ('}') // or the beginning of the format spec (':'). if (_Begin == _End || (*_Begin != '}' && *_Begin != ':')) { - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } _Callbacks._On_manual_id(_Index); return _Begin; } // This is where we would parse named arg ids if std::format were to support them. - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } _NODISCARD inline int _Code_units_in_next_character(const char* _First, const char* _Last, const _Cvtvec& _Cvt) { @@ -505,7 +505,7 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, const int _Units = _Code_units_in_next_character(_Begin, _End, _Getcvt()); if (_Units < 0) { // invalid fill character encoding - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } auto _Align_pt = _Begin + _Units; @@ -529,7 +529,7 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, if (_Parsed_align != _Align::_None) { if (_Align_pt != _Begin) { if (*_Begin == '{') { - throw format_error("invalid fill character '{'"); + _THROW(format_error("invalid fill character '{'")); } _Callbacks._On_fill({_Begin, static_cast(_Align_pt - _Begin)}); _Begin = _Align_pt + 1; @@ -614,7 +614,7 @@ _NODISCARD constexpr const _CharT* _Parse_width( } if (_Begin == _End || *_Begin != '}') { - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } ++_Begin; } @@ -641,10 +641,10 @@ _NODISCARD constexpr const _CharT* _Parse_precision( } if (_Begin == _End || *_Begin != '}') { - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } } else { - throw format_error("Missing precision specifier."); + _THROW(format_error("Missing precision specifier.")); } return _Begin; @@ -730,7 +730,7 @@ _NODISCARD constexpr const _CharT* _Parse_replacement_field( const _CharT* _Begin, const _CharT* _End, _HandlerT&& _Handler) { ++_Begin; if (_Begin == _End) { - throw format_error("Invalid format string."); + _THROW(format_error("Invalid format string.")); } if (*_Begin == '}') { @@ -752,10 +752,10 @@ _NODISCARD constexpr const _CharT* _Parse_replacement_field( } else if (_Ch == ':') { _Begin = _Handler._On_format_specs(_Adapter._Arg_id, _Begin + 1, _End); if (_Begin == _End || *_Begin != '}') { - throw format_error("Unknown format specifier."); + _THROW(format_error("Unknown format specifier.")); } } else { - throw format_error("Missing '}' in format string."); + _THROW(format_error("Missing '}' in format string.")); } } @@ -774,7 +774,7 @@ const _CharT* _Find_encoded(const _CharT* _First, const _CharT* _Last, const _Ch while (_First != _Last && *_First != _Val) { const int _Units = _Code_units_in_next_character(_First, _Last, _Cvt); if (_Units < 0) { - throw format_error("Invalid encoded character in format string."); + _THROW(format_error("Invalid encoded character in format string.")); } _First += _Units; } @@ -806,7 +806,7 @@ void _Parse_format_string(basic_string_view<_CharT> _Format_str, _HandlerT&& _Ha // the above condition was not met. ++_ClosingCurl; if (_ClosingCurl == _OpeningCurl || *_ClosingCurl != '}') { - throw format_error("Unmatched '}' in format string."); + _THROW(format_error("Unmatched '}' in format string.")); } // We found two closing curls, so output only one of them _Handler._On_text(_Begin, _ClosingCurl); @@ -861,7 +861,7 @@ public: constexpr void _On_fill(const basic_string_view<_CharT> _Sv) { if (_Sv.size() > _STD size(_Specs._Fill)) { - throw format_error("Invalid fill (too long)."); + _THROW(format_error("Invalid fill (too long).")); } const auto _Pos = _STD _Copy_unchecked(_Sv._Unchecked_begin(), _Sv._Unchecked_end(), _Specs._Fill); @@ -895,7 +895,7 @@ public: constexpr void _On_type(const _CharT _Type) { if (_Type < 0 || _Type > (numeric_limits::max)()) { - throw format_error("Invalid type specification."); + _THROW(format_error("Invalid type specification.")); } _Specs._Type = static_cast(_Type); } @@ -911,7 +911,7 @@ _NODISCARD constexpr basic_format_arg<_Context> _Get_arg(const _Context& _Ctx, c // id or a named id (which we do not support in std::format) auto _Arg = _Ctx.arg(_Arg_id); if (!_Arg) { - throw format_error("Argument not found."); + _THROW(format_error("Argument not found.")); } return _Arg; @@ -926,12 +926,12 @@ public: if constexpr (is_integral_v<_Ty>) { if constexpr (is_signed_v<_Ty>) { if (_Value < 0) { - throw format_error("Negative width."); + _THROW(format_error("Negative width.")); } } return static_cast(_Value); } else { - throw format_error("Width is not an integer."); + _THROW(format_error("Width is not an integer.")); } } }; @@ -945,12 +945,12 @@ public: if constexpr (is_integral_v<_Ty>) { if constexpr (is_signed_v<_Ty>) { if (_Value < 0) { - throw format_error("Negative precision."); + _THROW(format_error("Negative precision.")); } } return static_cast(_Value); } else { - throw format_error("Precision is not an integer."); + _THROW(format_error("Precision is not an integer.")); } } }; @@ -963,7 +963,7 @@ _NODISCARD constexpr int _Get_dynamic_specs(const _FormatArg _Arg) { _STL_INTERNAL_STATIC_ASSERT(_Is_any_of_v<_Handler, _Width_checker, _Precision_checker>); const unsigned long long _Val = _STD visit_format_arg(_Handler(), _Arg); if (_Val > static_cast((numeric_limits::max)())) { - throw format_error("Number is too big."); + _THROW(format_error("Number is too big.")); } return static_cast(_Val); @@ -1036,7 +1036,7 @@ private: _NODISCARD static constexpr int _Verify_dynamic_arg_index_in_range(const size_t _Idx) { if (_Idx > static_cast((numeric_limits::max)())) { - throw format_error("Dynamic width or precision index too large."); + _THROW(format_error("Dynamic width or precision index too large.")); } return static_cast(_Idx); @@ -1052,7 +1052,7 @@ public: constexpr void _Require_numeric_argument() const { if (!_Is_arithmetic_fmt_type(_Arg_type)) { - throw format_error("Format specifier requires numeric argument."); + _THROW(format_error("Format specifier requires numeric argument.")); } } @@ -1061,13 +1061,13 @@ public: if (_Is_integral_fmt_type(_Arg_type) && _Arg_type != _Basic_format_arg_type::_Int_type && _Arg_type != _Basic_format_arg_type::_Long_long_type && _Arg_type != _Basic_format_arg_type::_Char_type) { - throw format_error("Format specifier requires signed argument."); + _THROW(format_error("Format specifier requires signed argument.")); } } constexpr void _Check_precision() const { if (_Is_integral_fmt_type(_Arg_type) || _Arg_type == _Basic_format_arg_type::_Pointer_type) { - throw format_error("Precision not allowed for this argument type."); + _THROW(format_error("Precision not allowed for this argument type.")); } } }; @@ -1533,7 +1533,7 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const void* const _Value) { template _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _CharT* _Value) { if (!_Value) { - throw format_error("String pointer is null."); + _THROW(format_error("String pointer is null.")); } while (*_Value) { @@ -1750,14 +1750,14 @@ _NODISCARD _OutputIt _Write_integral( _OutputIt _Out, const _Integral _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale) { if (_Specs._Type == 'c') { if (!_In_bounds<_CharT>(_Value)) { - throw format_error("integral cannot be stored in charT"); + _THROW(format_error("integral cannot be stored in charT")); } _Specs._Alt = false; return _Fmt_write(_STD move(_Out), static_cast<_CharT>(_Value), _Specs, _Locale); } if (_Specs._Precision != -1) { - throw format_error("integral cannot have a precision"); + _THROW(format_error("integral cannot have a precision")); } if (_Specs._Sgn == _Sign::_None) { @@ -1787,7 +1787,7 @@ _NODISCARD _OutputIt _Write_integral( _Base = 8; break; default: - throw format_error("invalid integral type"); + _THROW(format_error("invalid integral type")); } // long long -1 representation in binary is 64 bits + sign @@ -1867,7 +1867,7 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const bool _Value, _Basic_format } if (_Specs._Precision != -1) { - throw format_error("bool cannot have a precision"); + _THROW(format_error("bool cannot have a precision")); } if (_Specs._Localized) { @@ -1893,7 +1893,7 @@ _NODISCARD _OutputIt _Fmt_write( } if (_Specs._Precision != -1) { - throw format_error("charT cannot have a precision"); + _THROW(format_error("charT cannot have a precision")); } // Clear the type so that the string_view writer doesn't fail on 'c'. @@ -1956,7 +1956,7 @@ _NODISCARD _OutputIt _Fmt_write( _Exponent = 'e'; break; default: - throw format_error("invalid floating point type"); + _THROW(format_error("invalid floating point type")); } // Consider the powers of 2 in decimal: @@ -2120,27 +2120,27 @@ template _NODISCARD _OutputIt _Fmt_write( _OutputIt _Out, const void* const _Value, const _Basic_format_specs<_CharT>& _Specs, locale) { if (_Specs._Type != '\0' && _Specs._Type != 'p') { - throw format_error("invalid const void* type"); + _THROW(format_error("invalid const void* type")); } if (_Specs._Sgn != _Sign::_None) { - throw format_error("const void* cannot have a sign"); + _THROW(format_error("const void* cannot have a sign")); } if (_Specs._Alt) { - throw format_error("const void* cannot have an alternative representation"); + _THROW(format_error("const void* cannot have an alternative representation")); } if (_Specs._Precision != -1) { - throw format_error("const void* cannot have a precision"); + _THROW(format_error("const void* cannot have a precision")); } if (_Specs._Leading_zero) { - throw format_error("const void* cannot have a leading zero"); + _THROW(format_error("const void* cannot have a leading zero")); } if (_Specs._Localized) { - throw format_error("const void* cannot be localized"); + _THROW(format_error("const void* cannot be localized")); } // Compute the bit width of the pointer (i.e. how many bits it takes to be represented). @@ -2282,23 +2282,23 @@ template _NODISCARD _OutputIt _Fmt_write( _OutputIt _Out, const basic_string_view<_CharT> _Value, const _Basic_format_specs<_CharT>& _Specs, locale) { if (_Specs._Type != '\0' && _Specs._Type != 's') { - throw format_error("invalid string type"); + _THROW(format_error("invalid string type")); } if (_Specs._Sgn != _Sign::_None) { - throw format_error("string cannot have a sign"); + _THROW(format_error("string cannot have a sign")); } if (_Specs._Alt) { - throw format_error("string cannot have an alternative representation"); + _THROW(format_error("string cannot have an alternative representation")); } if (_Specs._Leading_zero) { - throw format_error("string cannot have a leading zero"); + _THROW(format_error("string cannot have a leading zero")); } if (_Specs._Localized) { - throw format_error("string cannot be localized"); + _THROW(format_error("string cannot be localized")); } if (_Specs._Precision < 0 && _Specs._Width <= 0) { @@ -2394,7 +2394,7 @@ struct _Format_handler { _Arg._Active_state); _Begin = _Parse_format_specs(_Begin, _End, _Handler); if (_Begin == _End || *_Begin != '}') { - throw format_error("Missing '}' in format string."); + _THROW(format_error("Missing '}' in format string.")); } _Ctx.advance_to(_STD visit_format_arg( @@ -2420,7 +2420,7 @@ struct _Formatter_base { _Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>(_Specs, _ParseCtx), _ArgType); const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler); if (_It != _ParseCtx._Unchecked_end() && *_It != '}') { - throw format_error("Missing '}' in format string."); + _THROW(format_error("Missing '}' in format string.")); } return _ParseCtx.begin() + (_It - _ParseCtx._Unchecked_begin()); } From 7e0c874198fcc084187207c0865784366222448d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:34 -0700 Subject: [PATCH 20/45] Improve locale testing. --- .../test.cpp | 30 +++++++++++++------ .../P0645R10_text_formatting_parsing/test.cpp | 27 ++++++++++++----- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index dc86a496582..74e02e71b90 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include -#include +#include +#include +#include #include #include #include @@ -810,7 +812,7 @@ void test_float_specs() { assert(format(locale{"en-US"}, STR("{:L}"), nan) == STR("nan")); assert(format(locale{"en-US"}, STR("{:L}"), inf) == STR("inf")); - assert(format(locale{"de_DE"}, STR("{:Lf}"), Float{0}) == STR("0,000000")); + assert(format(locale{"de-DE"}, STR("{:Lf}"), Float{0}) == STR("0,000000")); #endif // !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING // Type @@ -974,7 +976,7 @@ void test_size() { void test_multibyte_format_strings() { { - setlocale(LC_ALL, ".932"); + assert(setlocale(LC_ALL, "ja-JP") != nullptr); const auto s = "\x93\xfa\x96{\x92\x6e\x90}"sv; // Note the use of `{` and `}` as continuation bytes (from GH-1576) assert(format(s) == s); @@ -1002,9 +1004,9 @@ void test_multibyte_format_strings() { assert(format("{:\x90}>4.3}", s) == "\x90}\x90}\x93\xfa"sv); } -#ifndef MSVC_INTERNAL_TESTING // TRANSITION, Windows on Contest VMs understand ".UTF-8" codepage +#ifndef MSVC_INTERNAL_TESTING // TRANSITION, the Windows version on Contest VMs doesn't always understand ".UTF-8" { - setlocale(LC_ALL, ".UTF-8"); + assert(setlocale(LC_ALL, ".UTF-8") != nullptr); // Filling with footballs ("\xf0\x9f\x8f\x88" is U+1F3C8 AMERICAN FOOTBALL) assert(format("{:\xf0\x9f\x8f\x88>4}"sv, 42) == "\xf0\x9f\x8f\x88\xf0\x9f\x8f\x88\x34\x32"); @@ -1014,7 +1016,7 @@ void test_multibyte_format_strings() { } { - setlocale(LC_ALL, ".UTF-8"); + assert(setlocale(LC_ALL, ".UTF-8") != nullptr); try { (void) format("{:\x9f\x8f\x88<10}"sv, 42); // Bad fill character encoding: missing lead byte before \x9f assert(false); @@ -1023,7 +1025,7 @@ void test_multibyte_format_strings() { } #endif // MSVC_INTERNAL_TESTING - setlocale(LC_ALL, nullptr); + assert(setlocale(LC_ALL, "C") != nullptr); } // The libfmt_ tests are derived from tests in @@ -1247,7 +1249,7 @@ void libfmt_formatter_test_zero_flag() { throw_helper(STR("{0:05}"), reinterpret_cast(0x42)); } -int main() { +void test() { test_simple_formatting(); test_simple_formatting(); @@ -1303,6 +1305,16 @@ int main() { libfmt_formatter_test_zero_flag(); libfmt_formatter_test_zero_flag(); +} - return 0; +int main() { + try { + test(); + } catch (const format_error& e) { + printf("format_error: %s\n", e.what()); + assert(false); + } catch (const exception& e) { + printf("exception: %s\n", e.what()); + assert(false); + } } diff --git a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp index 9a7f62083d7..6b4bf530395 100644 --- a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include +#include #include +#include +#include #include #include -#include #include using namespace std; @@ -163,7 +164,7 @@ bool test_parse_align() { } else { // test multibyte fill characters { - setlocale(LC_ALL, ".932"); + assert(setlocale(LC_ALL, "ja-JP") != nullptr); test_parse_helper(parse_align_fn, "\x93\xfaX"sv, false, 3, @@ -172,9 +173,9 @@ bool test_parse_align() { {.expected_alignment = _Align::_Center, .expected_fill = "\x92\x6e"sv}); } -#ifndef MSVC_INTERNAL_TESTING // TRANSITION, Windows on Contest VMs understand ".UTF-8" codepage +#ifndef MSVC_INTERNAL_TESTING // TRANSITION, the Windows version on Contest VMs doesn't always understand ".UTF-8" { - setlocale(LC_ALL, ".UTF-8"); + assert(setlocale(LC_ALL, ".UTF-8") != nullptr); // "\xf0\x9f\x8f\x88" is U+1F3C8 AMERICAN FOOTBALL test_parse_helper(parse_align_fn, "\xf0\x9f\x8f\x88(); test_parse_align(); @@ -365,6 +366,16 @@ int main() { test_specs_checker(); static_assert(test_specs_checker()); static_assert(test_specs_checker()); +} - return 0; +int main() { + try { + test(); + } catch (const format_error& e) { + printf("format_error: %s\n", e.what()); + assert(false); + } catch (const exception& e) { + printf("exception: %s\n", e.what()); + assert(false); + } } From fa256ee6cfc7a1738437a3dd3acd5c0d1ee56a23 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 11 Apr 2021 23:52:37 -0700 Subject: [PATCH 21/45] Work around VSO-1309454 (duplicated deduction guides). --- .../std/tests/P1502R1_standard_library_header_units/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp index 8f3c55cd999..c34aa8835ab 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp +++ b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp @@ -126,7 +126,7 @@ int main() { { puts("Testing ."); -#ifdef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1088552 (deduction guides) +#if 0 // TRANSITION, VSO-1088552 (deduction guides), VSO-1309454 (duplicated deduction guides) constexpr array arr{10, 20, 30, 40, 50}; #else // ^^^ no workaround / workaround vvv constexpr array arr{10, 20, 30, 40, 50}; @@ -581,7 +581,7 @@ int main() { { puts("Testing ."); constexpr int arr[]{11, 0, 22, 0, 33, 0, 44, 0, 55}; -#ifdef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1088552 (deduction guides) +#if 0 // TRANSITION, VSO-1088552 (deduction guides), VSO-1309454 (duplicated deduction guides) assert(ranges::distance(views::filter(arr, [](int x) { return x == 0; })) == 4); static_assert(ranges::distance(views::filter(arr, [](int x) { return x != 0; })) == 5); #else // ^^^ no workaround / workaround vvv From a4a56cb4e0919ec5bfb4c4c8598893585215c3fb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 16:41:04 -0700 Subject: [PATCH 22/45] Add const. --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index e5612436d5a..0fc32ee7efe 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5326,7 +5326,7 @@ namespace chrono { _THROW(format_error("Invalid format string - missing type after %")); } - _CharT _Next_ch = *(_Begin + 1); + const _CharT _Next_ch = *(_Begin + 1); switch (_Next_ch) { case 'n': _Callbacks._On_lit_char('\n'); From f71dadc2836d0845f940e11e452d2f57b3cb38fe Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 16:52:02 -0700 Subject: [PATCH 23/45] Add missing `_WIDEN(_CharT, '.')`. --- stl/inc/xcharconv_ryu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xcharconv_ryu.h b/stl/inc/xcharconv_ryu.h index 030d08be992..e045f8e5a37 100644 --- a/stl/inc/xcharconv_ryu.h +++ b/stl/inc/xcharconv_ryu.h @@ -673,7 +673,7 @@ _NODISCARD pair<_CharT*, errc> __d2fixed_buffered_n(_CharT* _First, _CharT* cons } --_Round; const _CharT __c = _Round[0]; - if (__c == '.') { + if (__c == _WIDEN(_CharT, '.')) { _Dot = _Round; } else if (__c == _WIDEN(_CharT, '9')) { _Round[0] = _WIDEN(_CharT, '0'); @@ -1482,7 +1482,7 @@ _NODISCARD pair<_CharT*, errc> __to_chars(_CharT* const _First, _CharT* const _L } else if (_Whole_digits > 0) { // case "17.29" // Performance note: moving digits might not be optimal. _CSTD memmove(_First, _First + 1, static_cast(_Whole_digits) * sizeof(_CharT)); - _First[_Whole_digits] = '.'; + _First[_Whole_digits] = _WIDEN(_CharT, '.'); } else { // case "0.001729" // Performance note: a larger memset() followed by overwriting '.' might be more efficient. _First[0] = _WIDEN(_CharT, '0'); From 12c358155f7361613a16934c87df13be328d3102 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 19:43:15 -0700 Subject: [PATCH 24/45] Add const, verify __d2s_buffered_n() etc. succeeded. --- tests/std/tests/P0067R5_charconv/test.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0067R5_charconv/test.cpp b/tests/std/tests/P0067R5_charconv/test.cpp index fb80283c18c..8eaf8e2a9b2 100644 --- a/tests/std/tests/P0067R5_charconv/test.cpp +++ b/tests/std/tests/P0067R5_charconv/test.cpp @@ -1090,19 +1090,23 @@ void wchar_tests() { wchar_t buffer[32]; for (const auto& t : double_to_wide_test_cases) { - auto result = __d2s_buffered_n(begin(buffer), end(buffer), t.value, t.fmt); + const auto result = __d2s_buffered_n(begin(buffer), end(buffer), t.value, t.fmt); + assert(result.second == errc{}); const wstring_view sv(t.correct); assert(equal(buffer, result.first, sv.begin(), sv.end())); } for (const auto& t : float_to_wide_test_cases) { - auto result = __f2s_buffered_n(begin(buffer), end(buffer), t.value, t.fmt); + const auto result = __f2s_buffered_n(begin(buffer), end(buffer), t.value, t.fmt); + assert(result.second == errc{}); const wstring_view sv(t.correct); assert(equal(buffer, result.first, sv.begin(), sv.end())); } for (const auto& t : wide_digit_pairs_test_cases) { - auto result = __d2fixed_buffered_n(begin(buffer), end(buffer), t.value, static_cast(t.precision)); + const auto result = + __d2fixed_buffered_n(begin(buffer), end(buffer), t.value, static_cast(t.precision)); + assert(result.second == errc{}); const wstring_view sv(t.correct); assert(equal(buffer, result.first, sv.begin(), sv.end())); } From 7146857174ccca8e3583c7400b29db732f545fa2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 20:45:57 -0700 Subject: [PATCH 25/45] Include more headers. --- stl/inc/format | 2 ++ .../tests/P0645R10_text_formatting_custom_formatting/test.cpp | 1 + tests/std/tests/P0645R10_text_formatting_formatting/test.cpp | 1 + tests/std/tests/P0645R10_text_formatting_parsing/test.cpp | 1 + 4 files changed, 5 insertions(+) diff --git a/stl/inc/format b/stl/inc/format index 31874176023..d2bfb67208d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -46,9 +46,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include diff --git a/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp index 211956f947c..a087e83d50a 100644 --- a/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index e9d39468e59..4b22d8a082d 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp index 49faaf343e0..8b90053be26 100644 --- a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "test_format_support.hpp" From c7d570c9f9ce285796f4d3d6c2ea6733d98feff9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 21:01:32 -0700 Subject: [PATCH 26/45] Rename integral to Integral to avoid shadowing the concept. --- .../test.cpp | 120 +++++++++--------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index 4b22d8a082d..5f3b28a6a8d 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -477,97 +477,97 @@ void test_fill_and_align() { assert(tester() == STR("*AB**")); } -template +template void test_integral_specs() { - assert(format(STR("{:}"), integral{0}) == STR("0")); + assert(format(STR("{:}"), Integral{0}) == STR("0")); // Sign - assert(format(STR("{: }"), integral{0}) == STR(" 0")); - assert(format(STR("{:+}"), integral{0}) == STR("+0")); - assert(format(STR("{:-}"), integral{0}) == STR("0")); - - if constexpr (is_signed_v) { - assert(format(STR("{: }"), integral{-1}) == STR("-1")); - assert(format(STR("{:+}"), integral{-1}) == STR("-1")); - assert(format(STR("{:-}"), integral{-1}) == STR("-1")); + assert(format(STR("{: }"), Integral{0}) == STR(" 0")); + assert(format(STR("{:+}"), Integral{0}) == STR("+0")); + assert(format(STR("{:-}"), Integral{0}) == STR("0")); + + if constexpr (is_signed_v) { + assert(format(STR("{: }"), Integral{-1}) == STR("-1")); + assert(format(STR("{:+}"), Integral{-1}) == STR("-1")); + assert(format(STR("{:-}"), Integral{-1}) == STR("-1")); } - assert(format(STR("{: 3}"), integral{1}) == STR(" 1")); - assert(format(STR("{:+3}"), integral{1}) == STR(" +1")); - assert(format(STR("{:-3}"), integral{1}) == STR(" 1")); + assert(format(STR("{: 3}"), Integral{1}) == STR(" 1")); + assert(format(STR("{:+3}"), Integral{1}) == STR(" +1")); + assert(format(STR("{:-3}"), Integral{1}) == STR(" 1")); // Alternate form - assert(format(STR("{:#}"), integral{0}) == STR("0")); - assert(format(STR("{:#d}"), integral{0}) == STR("0")); - assert(format(STR("{:#c}"), integral{'a'}) == STR("a")); + assert(format(STR("{:#}"), Integral{0}) == STR("0")); + assert(format(STR("{:#d}"), Integral{0}) == STR("0")); + assert(format(STR("{:#c}"), Integral{'a'}) == STR("a")); - assert(format(STR("{:#b}"), integral{0}) == STR("0b0")); - assert(format(STR("{:#B}"), integral{0}) == STR("0B0")); + assert(format(STR("{:#b}"), Integral{0}) == STR("0b0")); + assert(format(STR("{:#B}"), Integral{0}) == STR("0B0")); - assert(format(STR("{:#o}"), integral{0}) == STR("0")); - assert(format(STR("{:#o}"), integral{1}) == STR("01")); + assert(format(STR("{:#o}"), Integral{0}) == STR("0")); + assert(format(STR("{:#o}"), Integral{1}) == STR("01")); - assert(format(STR("{:#x}"), integral{0}) == STR("0x0")); - assert(format(STR("{:#X}"), integral{0}) == STR("0X0")); - assert(format(STR("{:#x}"), integral{255}) == STR("0xff")); - assert(format(STR("{:#X}"), integral{255}) == STR("0XFF")); + assert(format(STR("{:#x}"), Integral{0}) == STR("0x0")); + assert(format(STR("{:#X}"), Integral{0}) == STR("0X0")); + assert(format(STR("{:#x}"), Integral{255}) == STR("0xff")); + assert(format(STR("{:#X}"), Integral{255}) == STR("0XFF")); - assert(format(STR("{:+#6x}"), integral{255}) == STR(" +0xff")); + assert(format(STR("{:+#6x}"), Integral{255}) == STR(" +0xff")); - if constexpr (is_signed_v) { - assert(format(STR("{:#o}"), integral{-1}) == STR("-01")); - assert(format(STR("{:#x}"), integral{-255}) == STR("-0xff")); - assert(format(STR("{:#X}"), integral{-255}) == STR("-0XFF")); + if constexpr (is_signed_v) { + assert(format(STR("{:#o}"), Integral{-1}) == STR("-01")); + assert(format(STR("{:#x}"), Integral{-255}) == STR("-0xff")); + assert(format(STR("{:#X}"), Integral{-255}) == STR("-0XFF")); } - if constexpr (is_same_v) { + if constexpr (is_same_v) { assert(format(STR("{:b}"), numeric_limits::min()) == STR("-1000000000000000000000000000000000000000000000000000000000000000")); } // Leading zero - assert(format(STR("{:0}"), integral{0}) == STR("0")); - assert(format(STR("{:03}"), integral{0}) == STR("000")); - assert(format(STR("{:+03}"), integral{0}) == STR("+00")); - assert(format(STR("{:<03}"), integral{0}) == STR("0 ")); - assert(format(STR("{:>03}"), integral{0}) == STR(" 0")); - assert(format(STR("{:+#06X}"), integral{5}) == STR("+0X005")); + assert(format(STR("{:0}"), Integral{0}) == STR("0")); + assert(format(STR("{:03}"), Integral{0}) == STR("000")); + assert(format(STR("{:+03}"), Integral{0}) == STR("+00")); + assert(format(STR("{:<03}"), Integral{0}) == STR("0 ")); + assert(format(STR("{:>03}"), Integral{0}) == STR(" 0")); + assert(format(STR("{:+#06X}"), Integral{5}) == STR("+0X005")); // Width - assert(format(STR("{:3}"), integral{0}) == STR(" 0")); + assert(format(STR("{:3}"), Integral{0}) == STR(" 0")); // Precision - throw_helper(STR("{:.1}"), integral{0}); + throw_helper(STR("{:.1}"), Integral{0}); // Locale #if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING - assert(format(locale{"en-US"}, STR("{:L}"), integral{0}) == STR("0")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{100}) == STR("100")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{1'000}) == STR("1,000")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{10'000}) == STR("10,000")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{100'000}) == STR("100,000")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{1'000'000}) == STR("1,000,000")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{10'000'000}) == STR("10,000,000")); - assert(format(locale{"en-US"}, STR("{:L}"), integral{100'000'000}) == STR("100,000,000")); - - assert(format(locale{"en-US"}, STR("{:Lx}"), integral{0x123'abc}) == STR("123,abc")); - assert(format(locale{"en-US"}, STR("{:6L}"), integral{1'000}) == STR(" 1,000")); - - assert(format(locale{"hi-IN"}, STR("{:L}"), integral{10'000'000}) == STR("1,00,00,000")); - assert(format(locale{"hi-IN"}, STR("{:L}"), integral{100'000'000}) == STR("10,00,00,000")); - - assert(format(locale{"hi-IN"}, STR("{:Lx}"), integral{0x123'abc}) == STR("1,23,abc")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{0}) == STR("0")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{100}) == STR("100")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{1'000}) == STR("1,000")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{10'000}) == STR("10,000")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{100'000}) == STR("100,000")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{1'000'000}) == STR("1,000,000")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{10'000'000}) == STR("10,000,000")); + assert(format(locale{"en-US"}, STR("{:L}"), Integral{100'000'000}) == STR("100,000,000")); + + assert(format(locale{"en-US"}, STR("{:Lx}"), Integral{0x123'abc}) == STR("123,abc")); + assert(format(locale{"en-US"}, STR("{:6L}"), Integral{1'000}) == STR(" 1,000")); + + assert(format(locale{"hi-IN"}, STR("{:L}"), Integral{10'000'000}) == STR("1,00,00,000")); + assert(format(locale{"hi-IN"}, STR("{:L}"), Integral{100'000'000}) == STR("10,00,00,000")); + + assert(format(locale{"hi-IN"}, STR("{:Lx}"), Integral{0x123'abc}) == STR("1,23,abc")); #endif // !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING // Type - assert(format(STR("{:b}"), integral{0}) == STR("0")); - assert(format(STR("{:b}"), integral{100}) == STR("1100100")); + assert(format(STR("{:b}"), Integral{0}) == STR("0")); + assert(format(STR("{:b}"), Integral{100}) == STR("1100100")); - assert(format(STR("{:d}"), integral{100}) == STR("100")); + assert(format(STR("{:d}"), Integral{100}) == STR("100")); - throw_helper(STR("{:c}"), integral{numeric_limits::max()} + 1); - if constexpr (is_signed_v) { - throw_helper(STR("{:c}"), integral{numeric_limits::min()} - 1); + throw_helper(STR("{:c}"), Integral{numeric_limits::max()} + 1); + if constexpr (is_signed_v) { + throw_helper(STR("{:c}"), Integral{numeric_limits::min()} - 1); } } From bec21d4008f8957aa3cb56531440a0f06ee74406 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:13:10 -0700 Subject: [PATCH 27/45] Change _Align and _Sign's underlying type to uint8_t. _Align is stored as a data member, so this matters. --- stl/inc/format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index d2bfb67208d..27b0dbebc89 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -69,9 +69,9 @@ class format_error : public runtime_error { using runtime_error::runtime_error; }; -enum class _Align { _None, _Left, _Right, _Center }; +enum class _Align : uint8_t { _None, _Left, _Right, _Center }; -enum class _Sign { _None, _Plus, _Minus, _Space }; +enum class _Sign : uint8_t { _None, _Plus, _Minus, _Space }; enum class _Basic_format_arg_type : uint8_t { _None, From 2e95f19647da10d1223f968057d44bcf11000db8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:23:55 -0700 Subject: [PATCH 28/45] 4-bit bitfield requires strictly less than 16. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 27b0dbebc89..bde588b6dda 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -89,7 +89,7 @@ enum class _Basic_format_arg_type : uint8_t { _String_type, _Custom_type, }; -static_assert(static_cast(_Basic_format_arg_type::_Custom_type) <= 16); +static_assert(static_cast(_Basic_format_arg_type::_Custom_type) < 16, "must fit in 4-bit bitfield"); _NODISCARD constexpr bool _Is_integral_fmt_type(_Basic_format_arg_type _Ty) { return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_ULong_long_type; From 6aad0473df29d6fbb2977f94d786bf04c4cd984e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:27:02 -0700 Subject: [PATCH 29/45] Style: Add newlines. --- stl/inc/format | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stl/inc/format b/stl/inc/format index bde588b6dda..985cdb4f9cb 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -97,6 +97,7 @@ _NODISCARD constexpr bool _Is_integral_fmt_type(_Basic_format_arg_type _Ty) { _NODISCARD constexpr bool _Is_arithmetic_fmt_type(_Basic_format_arg_type _Ty) { return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_Long_double_type; } + struct _Auto_id_tag {}; // clang-format off @@ -194,6 +195,7 @@ public: _NODISCARD constexpr const _CharT* _Unchecked_end() const noexcept { return _Format_string._Unchecked_end(); } + constexpr void advance_to(const const_iterator _It) { _Adl_verify_range(_It, _Format_string.end()); // _It must be after _Format_string.begin(). @@ -291,6 +293,7 @@ public: : _Active_state(_Basic_format_arg_type::_String_type), _String_state(_Val) {} explicit basic_format_arg(const handle _Val) noexcept : _Active_state(_Basic_format_arg_type::_Custom_type), _Custom_state(_Val) {} + explicit operator bool() const noexcept { return _Active_state != _Basic_format_arg_type::_None; } @@ -1062,6 +1065,7 @@ public: _Parse_ctx.check_arg_id(_Arg_id); _Dynamic_specs._Dynamic_precision_index = _Verify_dynamic_arg_index_in_range(_Arg_id); } + constexpr void _On_dynamic_precision(const _Auto_id_tag) { _Dynamic_specs._Dynamic_precision_index = _Verify_dynamic_arg_index_in_range(_Parse_ctx.next_arg_id()); } @@ -1872,6 +1876,7 @@ _NODISCARD _OutputIt _Write_integral( if (_Write_leading_zeroes && _Width < _Specs._Width) { _Out = _RANGES fill_n(_STD move(_Out), _Specs._Width - _Width, '0'); } + if (_Separators > 0) { return _Write_separated_integer(_Buffer_start, _End, _Groups, _STD use_facet>(_Locale).thousands_sep(), _Separators, _STD move(_Out)); @@ -2074,6 +2079,7 @@ _NODISCARD _OutputIt _Fmt_write( ++_Width; _Append_decimal = true; } + if (_Specs._Type == 'g' || _Specs._Type == 'G') { auto _Digits = static_cast(_Exponent_start - _Buffer_start); From 34a457250db1cf82e9e34314612d95f8edb40579 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:41:26 -0700 Subject: [PATCH 30/45] Bugfix: Add missing typedefs. --- stl/inc/format | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stl/inc/format b/stl/inc/format index 985cdb4f9cb..380041fdaad 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -238,6 +238,9 @@ private: ptrdiff_t _Next_arg_id = 0; }; +using format_parse_context = basic_format_parse_context; +using wformat_parse_context = basic_format_parse_context; + template class basic_format_arg { public: From 87755dcf973ce04479045535b342a60cef9f373f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:48:23 -0700 Subject: [PATCH 31/45] basic_format_arg::handle should store a __cdecl function pointer. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 380041fdaad..79f85d913b5 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -249,7 +249,7 @@ public: class handle { private: const void* _Ptr; - void (*_Format)(basic_format_parse_context<_CharType>& _Parse_ctx, _Context& _Format_ctx, const void*); + void(__cdecl* _Format)(basic_format_parse_context<_CharType>& _Parse_ctx, _Context& _Format_ctx, const void*); friend basic_format_arg; public: From a0f0c02acb657ffaae1af6a2b4fe7230814c3df8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 00:53:35 -0700 Subject: [PATCH 32/45] basic_format_arg::handle::format is const in the Standard. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 79f85d913b5..c73a3cc1e42 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -262,7 +262,7 @@ public: _Format_ctx.advance_to(_Formatter.format(*static_cast(_Ptr), _Format_ctx)); }) {} - void format(basic_format_parse_context<_CharType>& _Parse_ctx, _Context& _Format_ctx) { + void format(basic_format_parse_context<_CharType>& _Parse_ctx, _Context& _Format_ctx) const { _Format(_Parse_ctx, _Format_ctx, _Ptr); } }; From e9e7e433f984d7f1551b7ac54880fd3eec4e8ffd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 01:02:01 -0700 Subject: [PATCH 33/45] Bugfix: visit_format_arg() must return decltype(auto). --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index c73a3cc1e42..a2f76899160 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -321,7 +321,7 @@ public: }; template -auto visit_format_arg(_Visitor&& _Vis, basic_format_arg<_Context> _Arg) { +decltype(auto) visit_format_arg(_Visitor&& _Vis, basic_format_arg<_Context> _Arg) { switch (_Arg._Active_state) { case _Basic_format_arg_type::_None: return _STD forward<_Visitor>(_Vis)(_Arg._No_state); From 2cd72e6955d3bba7bfd3985a59e00f06af4003b7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 01:23:11 -0700 Subject: [PATCH 34/45] Style: constexpr explicit is conventional. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index a2f76899160..364f52002fa 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -895,7 +895,7 @@ struct _Dynamic_format_specs : _Basic_format_specs<_CharT> { template class _Specs_setter { public: - explicit constexpr _Specs_setter(_Basic_format_specs<_CharT>& _Specs_) : _Specs(_Specs_) {} + constexpr explicit _Specs_setter(_Basic_format_specs<_CharT>& _Specs_) : _Specs(_Specs_) {} constexpr void _On_align(const _Align _Aln) { _Specs._Alignment = _Aln; From 46e8971a52813e1ef495c39c856297e03c4eb8e4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 01:33:50 -0700 Subject: [PATCH 35/45] Add _NODISCARD to _Find_encoded(). --- stl/inc/format | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 364f52002fa..70b8c926811 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -801,7 +801,8 @@ _NODISCARD constexpr const _CharT* _Parse_replacement_field( } template -const _CharT* _Find_encoded(const _CharT* _First, const _CharT* _Last, const _CharT _Val, const _Cvtvec& _Cvt) { +_NODISCARD const _CharT* _Find_encoded( + const _CharT* _First, const _CharT* _Last, const _CharT _Val, const _Cvtvec& _Cvt) { // Returns the first occurrence of _Val as an encoded character (and not, for example, as a // continuation byte) in [_First, _Last). if constexpr (_Is_execution_charset_utf8_v) { From 0f4dd38e1de13f9dabef6cfd0e2add6effd24ef6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 01:45:01 -0700 Subject: [PATCH 36/45] Style: Use braces to construct temporaries. --- stl/inc/format | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 70b8c926811..415cb16712d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1004,7 +1004,7 @@ public: template _NODISCARD constexpr int _Get_dynamic_specs(const _FormatArg _Arg) { _STL_INTERNAL_STATIC_ASSERT(_Is_any_of_v<_Handler, _Width_checker, _Precision_checker>); - const unsigned long long _Val = _STD visit_format_arg(_Handler(), _Arg); + const unsigned long long _Val = _STD visit_format_arg(_Handler{}, _Arg); if (_Val > static_cast((numeric_limits::max)())) { _THROW(format_error("Number is too big.")); } @@ -2446,7 +2446,7 @@ struct _Format_handler { _Basic_format_specs<_CharT> _Specs; _Specs_checker<_Specs_handler, _Context>> _Handler( - _Specs_handler, _Context>(_Specs, _Parse_context, _Ctx), + _Specs_handler, _Context>{_Specs, _Parse_context, _Ctx}, _Arg._Active_state); _Begin = _Parse_format_specs(_Begin, _End, _Handler); if (_Begin == _End || *_Begin != '}') { @@ -2473,7 +2473,7 @@ struct _Formatter_base { using _Pc = basic_format_parse_context<_CharT>; typename _Pc::iterator parse(_Pc& _ParseCtx) { - _Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>(_Specs, _ParseCtx), _ArgType); + _Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>{_Specs, _ParseCtx}, _ArgType); const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler); if (_It != _ParseCtx._Unchecked_end() && *_It != '}') { _THROW(format_error("Missing '}' in format string.")); From f2b2a6cf3b4414dc324e2823b0882a03d98885df Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 01:55:37 -0700 Subject: [PATCH 37/45] Style: Avoid shadowing, remove unnecessary static_cast. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 415cb16712d..0a0e6a05abe 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1268,7 +1268,7 @@ struct _Format_arg_store_packed_index { using _Index_type = size_t; constexpr _Format_arg_store_packed_index() = default; - constexpr explicit _Format_arg_store_packed_index(const size_t _Index) : _Index(static_cast<_Index_type>(_Index)) { + constexpr explicit _Format_arg_store_packed_index(const size_t _Index_) : _Index(_Index_) { _Type(_Basic_format_arg_type::_None); } From 95958fedf760e46a170943177edca0a59d9428c1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 02:16:20 -0700 Subject: [PATCH 38/45] alignas(_Index_type) _Format_arg_store::_Storage, fix comment. --- stl/inc/format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 0a0e6a05abe..6a8754ab5f3 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1299,8 +1299,8 @@ private: static constexpr size_t _Index_length = _Num_args * sizeof(_Index_type); static constexpr size_t _Storage_length = (_Get_format_arg_storage_size<_Context, _Args> + ... + 0); - // we store the data in memory as _Format_arg_store_packed_index[_Index_length] + unsigned char[_Storage_length] - unsigned char _Storage[_Index_length + _Storage_length]; + // we store the data in memory as _Format_arg_store_packed_index[_Num_args] + unsigned char[_Storage_length] + alignas(_Index_type) unsigned char _Storage[_Index_length + _Storage_length]; template void _Store_impl(const size_t _Arg_index, const _Basic_format_arg_type _Arg_type, _Ty _Val) noexcept { From 8246a766648d1f6cbbe0657309bcf728076712e6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 12 Apr 2021 20:42:10 -0700 Subject: [PATCH 39/45] Improve comments. --- stl/inc/format | 36 +++++++++++-------- .../P0645R10_text_formatting_parsing/test.cpp | 2 +- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 6a8754ab5f3..205ce6853e3 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -839,7 +839,7 @@ void _Parse_format_string(basic_string_view<_CharT> _Format_str, _HandlerT&& _Ha for (;;) { const _CharT* _ClosingCurl = _Find_encoded(_Begin, _OpeningCurl, _CharT{'}'}, _Cvt); - // In this case there are neither closing nor opening curls in [_Begin, _OpenCurl) + // In this case there are neither closing nor opening curls in [_Begin, _OpeningCurl) // Write the whole thing out. if (_ClosingCurl == _OpeningCurl) { _Handler._On_text(_Begin, _OpeningCurl); @@ -884,8 +884,8 @@ struct _Basic_format_specs { }; // Adds width and precision references to _Basic_format_specs. -// this is required for std::formatter implementations because we must -// parse the format specs without having access to the format args (via a format context) +// This is required for std::formatter implementations because we must +// parse the format specs without having access to the format args (via a format context). template struct _Dynamic_format_specs : _Basic_format_specs<_CharT> { int _Dynamic_width_index = -1; @@ -1012,8 +1012,8 @@ _NODISCARD constexpr int _Get_dynamic_specs(const _FormatArg _Arg) { return static_cast(_Val); } -// Parses standard format specs into a _Basic_format_specs using _Specs_setter, and, -// in addition handles dynamic width and precision. This is separate from _Specs setter +// Parses standard format specs into a _Basic_format_specs using _Specs_setter, and +// additionally handles dynamic width and precision. This is separate from _Specs_setter // because it needs to know about the current basic_format_parse_context and basic_format_context // in order to fetch the width from the arguments. template @@ -1316,7 +1316,7 @@ private: } } - // See [format.arg]/5 + // See N4885 [format.arg]/5 // clang-format off template requires _Has_formatter<_Context, _Ty> @@ -1502,10 +1502,16 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, monostate) { return _Out; } -// This size is derived from the maximum length of an arithmetic type. The two contenders for widest are double and long -// long. long long has a max length of ceil(log_10(2^64)) = 20 characters. double has a max length of -// limits::max_digits10 + the decimal + the sign + e + the exponent's sign + ceil(log_10(DBL_MAX_10_EXP)) -// = 17 + 1 + 1 + 1 + 3 = 24. An example is DBL_MAX which is "-1.7976931348623158e+308". +// This size is derived from the maximum length of an arithmetic type. The contenders for widest are: +// (a) long long has a max length of 20 characters: LLONG_MIN is "-9223372036854775807". +// (b) unsigned long long has a max length of 20 characters: ULLONG_MAX is "18446744073709551615". +// (c) double has a max length of 24 characters: -DBL_MAX is "-1.7976931348623158e+308". +// That's 17 characters for numeric_limits::max_digits10, +// plus 1 character for the sign, +// plus 1 character for the decimal point, +// plus 1 character for 'e', +// plus 1 character for the exponent's sign, +// plus 3 characters for the max exponent. inline constexpr size_t _Format_min_buffer_length = 24; // clang-format off @@ -2191,7 +2197,7 @@ _NODISCARD _OutputIt _Fmt_write( // Compute the bit width of the pointer (i.e. how many bits it takes to be represented). // Add 3 to the bit width so we always round up on the division. - // Divide that by the amount of bits a hex number represents (log2(16) = log2(2^4) = 4). + // Divide that by the amount of bits a hexit represents (log2(16) = log2(2^4) = 4). // Add 2 for the 0x prefix. auto _Width = 2 + static_cast(_STD bit_width(reinterpret_cast(_Value)) + 3) / 4; @@ -2369,10 +2375,10 @@ _NODISCARD _OutputIt _Fmt_write( }); } -// This is the visitor that's used for "simple" replacement fields, -// it could be a generic lambda (with overloaded), but that's -// bad for throughput. A simple replacement field is a replacement field -// that's just "{}", without any format specs. +// This is the visitor that's used for "simple" replacement fields. +// It could be a generic lambda, but that's bad for throughput. +// A simple replacement field is a replacement field that's just "{}", +// without any format specs. template struct _Default_arg_formatter { using _Context = basic_format_context<_OutputIt, _CharT>; diff --git a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp index 8b90053be26..d82b6985af4 100644 --- a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp @@ -31,7 +31,7 @@ bool test_parse_align() { {.expected_alignment = _Align::_Center, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); if constexpr (same_as) { - // This is a CJK character where the least significant byte is the same as ascii '>', + // This is a CJK character where the least significant byte is the same as ASCII '>', // libfmt and initial drafts of narrowed characters when parsing alignments, causing // \x343E (which is from CJK unified ideographs extension A) and similar characters to parse as // an alignment specifier. From 110bc90f9d73c77a213592b76bd7e0059a659bac Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 03:01:47 -0700 Subject: [PATCH 40/45] Style: Adjust spacing. --- stl/inc/format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 205ce6853e3..c8051849377 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1516,7 +1516,7 @@ inline constexpr size_t _Format_min_buffer_length = 24; // clang-format off template - requires(is_arithmetic_v<_Arithmetic> && !_CharT_or_bool<_Arithmetic, _CharT>) + requires (is_arithmetic_v<_Arithmetic> && !_CharT_or_bool<_Arithmetic, _CharT>) _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _Arithmetic _Value); // clang-format on @@ -1765,7 +1765,7 @@ _NODISCARD _OutputIt _Write_integral( // clang-format off template - requires(!_CharT_or_bool<_Integral, _CharT>) + requires (!_CharT_or_bool<_Integral, _CharT>) _NODISCARD _OutputIt _Fmt_write( _OutputIt _Out, const _Integral _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale); // clang-format on From d1fad5437035a0e1930d8bffec933187fa932b39 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 03:04:21 -0700 Subject: [PATCH 41/45] Style: When declaring functions, don't mark value params as const. --- stl/inc/format | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index c8051849377..446bbfeb519 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -1517,23 +1517,23 @@ inline constexpr size_t _Format_min_buffer_length = 24; // clang-format off template requires (is_arithmetic_v<_Arithmetic> && !_CharT_or_bool<_Arithmetic, _CharT>) -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _Arithmetic _Value); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, _Arithmetic _Value); // clang-format on template -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const bool _Value); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, bool _Value); template -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _CharT _Value); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, _CharT _Value); template -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const void* const _Value); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const void* _Value); template _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const _CharT* _Value); template -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const basic_string_view<_CharT> _Value); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, basic_string_view<_CharT> _Value); #pragma warning(push) #pragma warning(disable : 4365) // 'argument': conversion from 'char' to 'const wchar_t', signed/unsigned mismatch @@ -1761,29 +1761,27 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, monostate, const _Basic_format_s template _NODISCARD _OutputIt _Write_integral( - _OutputIt _Out, const _Integral _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); + _OutputIt _Out, _Integral _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); // clang-format off template requires (!_CharT_or_bool<_Integral, _CharT>) _NODISCARD _OutputIt _Fmt_write( - _OutputIt _Out, const _Integral _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale); + _OutputIt _Out, _Integral _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale); // clang-format on template -_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const bool _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, bool _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); template -_NODISCARD _OutputIt _Fmt_write( - _OutputIt _Out, const _CharT _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, _CharT _Value, _Basic_format_specs<_CharT> _Specs, locale _Locale); template _NODISCARD _OutputIt _Fmt_write( - _OutputIt _Out, const _Float _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale); + _OutputIt _Out, _Float _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale); template -_NODISCARD _OutputIt _Fmt_write( - _OutputIt _Out, const void* const _Value, const _Basic_format_specs<_CharT>& _Specs, locale); +_NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const void* _Value, const _Basic_format_specs<_CharT>& _Specs, locale); template _NODISCARD _OutputIt _Fmt_write( @@ -1791,7 +1789,7 @@ _NODISCARD _OutputIt _Fmt_write( template _NODISCARD _OutputIt _Fmt_write( - _OutputIt _Out, const basic_string_view<_CharT> _Value, const _Basic_format_specs<_CharT>& _Specs, locale); + _OutputIt _Out, basic_string_view<_CharT> _Value, const _Basic_format_specs<_CharT>& _Specs, locale); #pragma warning(push) #pragma warning(disable : 4365) // 'argument': conversion from 'char' to 'const wchar_t', signed/unsigned mismatch From d2b6ebbce00cbee3ad3fc7a6acbc2440fc018e8e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 03:28:17 -0700 Subject: [PATCH 42/45] Use isfinite for simplicity. --- stl/inc/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/format b/stl/inc/format index 446bbfeb519..97e1da6b997 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2061,7 +2061,7 @@ _NODISCARD _OutputIt _Fmt_write( _Exponent = static_cast(_CSTD toupper(_Exponent)); } - const auto _Is_finite = !(_STD isnan)(_Value) && !(_STD isinf)(_Value); + const auto _Is_finite = (_STD isfinite)(_Value); auto _Append_decimal = false; auto _Exponent_start = _Result.ptr; From 0acf9ecf448fd1dee3389ad34b52513f695c8126 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 03:47:22 -0700 Subject: [PATCH 43/45] Style: Use _Nx for N (it's not a type, or a number of types). --- stl/inc/format | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 97e1da6b997..bcee8dea899 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2545,9 +2545,9 @@ template <_Format_supported_charT _CharT> struct formatter : _Formatter_base {}; -template <_Format_supported_charT _CharT, size_t _Nty> -struct formatter - : _Formatter_base {}; +template <_Format_supported_charT _CharT, size_t _Nx> +struct formatter + : _Formatter_base {}; template <_Format_supported_charT _CharT, class _Traits, class _Allocator> struct formatter, _CharT> From 7bbec5b329aa8c1d4d974ac94415ac6c9a2b903b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 04:13:08 -0700 Subject: [PATCH 44/45] Big rename: _Align to _Fmt_align. --- stl/inc/chrono | 6 +- stl/inc/format | 60 +++++++++---------- tests/std/include/test_format_support.hpp | 10 ++-- .../test.cpp | 8 +-- .../test.cpp | 14 ++--- .../test.cpp | 6 +- .../P0645R10_text_formatting_parsing/test.cpp | 28 ++++----- .../P0645R10_text_formatting_utf8/test.cpp | 6 +- 8 files changed, 69 insertions(+), 69 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 0fc32ee7efe..94027aadf50 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5187,7 +5187,7 @@ namespace chrono { && _Parse_precision_callbacks<_Ty, _CharT> && _Width_adapter_callbacks<_Ty, _CharT> && _Precision_adapter_callbacks<_Ty, _CharT> - && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Align _Aln) { + && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln) { { _At._On_conversion_spec(_CharT{}, _CharT{}) } -> same_as; { _At._On_lit_char(_CharT{}) } -> same_as; }; @@ -5206,7 +5206,7 @@ namespace chrono { int _Precision = -1; int _Dynamic_width_index = -1; int _Dynamic_precision_index = -1; - _Align _Alignment = _Align::_None; + _Fmt_align _Alignment = _Fmt_align::_None; uint8_t _Fill_length = 1; // At most one codepoint (so one char32_t or four utf-8 char8_t) _CharT _Fill[4 / sizeof(_CharT)] = {_CharT{' '}}; @@ -5221,7 +5221,7 @@ namespace chrono { constexpr explicit _Chrono_specs_setter(_Chrono_format_specs<_CharT>& _Specs_) : _Specs(_Specs_) {} // same as _Specs_setter - constexpr void _On_align(_Align _Aln) { + constexpr void _On_align(_Fmt_align _Aln) { _Specs._Alignment = _Aln; } diff --git a/stl/inc/format b/stl/inc/format index bcee8dea899..a41bf068fa9 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -69,7 +69,7 @@ class format_error : public runtime_error { using runtime_error::runtime_error; }; -enum class _Align : uint8_t { _None, _Left, _Right, _Center }; +enum class _Fmt_align : uint8_t { _None, _Left, _Right, _Center }; enum class _Sign : uint8_t { _None, _Plus, _Minus, _Space }; @@ -116,7 +116,7 @@ concept _Parse_replacement_field_callbacks = requires(_Ty _At, const _CharT* _Be }; template -concept _Parse_align_callbacks = requires(_Ty _At, basic_string_view<_CharT> _Sv, _Align _Aln) { +concept _Parse_align_callbacks = requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln) { { _At._On_fill(_Sv) } -> same_as; { _At._On_align(_Aln) } -> same_as; }; @@ -149,7 +149,7 @@ concept _Parse_spec_callbacks = _Parse_align_callbacks<_Ty, _CharT> && _Parse_precision_callbacks<_Ty, _CharT> && _Width_adapter_callbacks<_Ty, _CharT> && _Precision_adapter_callbacks<_Ty, _CharT> - && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Align _Aln, _Sign _Sgn) { + && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln, _Sign _Sgn) { { _At._On_sign(_Sgn) } -> same_as; { _At._On_hash() } -> same_as; { _At._On_zero() } -> same_as; @@ -539,7 +539,7 @@ template _Callbacks_type> _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, _Callbacks_type&& _Callbacks) { // align and fill _STL_INTERNAL_CHECK(_Begin != _End && *_Begin != '}'); - auto _Parsed_align = _Align::_None; + auto _Parsed_align = _Fmt_align::_None; const int _Units = _Code_units_in_next_character(_Begin, _End, _Getcvt()); if (_Units < 0) { // invalid fill character encoding @@ -554,17 +554,17 @@ _NODISCARD const _CharT* _Parse_align(const _CharT* _Begin, const _CharT* _End, for (;;) { switch (*_Align_pt) { case '<': - _Parsed_align = _Align::_Left; + _Parsed_align = _Fmt_align::_Left; break; case '>': - _Parsed_align = _Align::_Right; + _Parsed_align = _Fmt_align::_Right; break; case '^': - _Parsed_align = _Align::_Center; + _Parsed_align = _Fmt_align::_Center; break; } - if (_Parsed_align != _Align::_None) { + if (_Parsed_align != _Fmt_align::_None) { if (_Align_pt != _Begin) { if (*_Begin == '{') { _THROW(format_error("invalid fill character '{'")); @@ -870,15 +870,15 @@ void _Parse_format_string(basic_string_view<_CharT> _Format_str, _HandlerT&& _Ha template struct _Basic_format_specs { - int _Width = 0; - int _Precision = -1; - char _Type = '\0'; - _Align _Alignment = _Align::_None; - _Sign _Sgn = _Sign::_None; - bool _Alt = false; - bool _Localized = false; - bool _Leading_zero = false; - uint8_t _Fill_length = 1; + int _Width = 0; + int _Precision = -1; + char _Type = '\0'; + _Fmt_align _Alignment = _Fmt_align::_None; + _Sign _Sgn = _Sign::_None; + bool _Alt = false; + bool _Localized = false; + bool _Leading_zero = false; + uint8_t _Fill_length = 1; // At most one codepoint (so one char32_t or four utf-8 char8_t). _CharT _Fill[4 / sizeof(_CharT)] = {_CharT{' '}}; }; @@ -898,7 +898,7 @@ class _Specs_setter { public: constexpr explicit _Specs_setter(_Basic_format_specs<_CharT>& _Specs_) : _Specs(_Specs_) {} - constexpr void _On_align(const _Align _Aln) { + constexpr void _On_align(const _Fmt_align _Aln) { _Specs._Alignment = _Aln; } @@ -1600,28 +1600,28 @@ _NODISCARD _OutputIt _Fmt_write(_OutputIt _Out, const basic_string_view<_CharT> template _NODISCARD _OutputIt _Write_aligned(_OutputIt _Out, const int _Width, const _Basic_format_specs<_CharT>& _Specs, - const _Align _Default_align, _Func&& _Fn) { + const _Fmt_align _Default_align, _Func&& _Fn) { int _Fill_left = 0; int _Fill_right = 0; auto _Alignment = _Specs._Alignment; - if (_Alignment == _Align::_None) { + if (_Alignment == _Fmt_align::_None) { _Alignment = _Default_align; } if (_Width < _Specs._Width) { switch (_Alignment) { - case _Align::_Left: + case _Fmt_align::_Left: _Fill_right = _Specs._Width - _Width; break; - case _Align::_Right: + case _Fmt_align::_Right: _Fill_left = _Specs._Width - _Width; break; - case _Align::_Center: + case _Fmt_align::_Center: _Fill_left = (_Specs._Width - _Width) / 2; _Fill_right = _Specs._Width - _Width - _Fill_left; break; - case _Align::_None: + case _Fmt_align::_None: _STL_ASSERT(false, "Invalid alignment"); break; } @@ -1874,7 +1874,7 @@ _NODISCARD _OutputIt _Write_integral( _Width += _Separators; } - const bool _Write_leading_zeroes = _Specs._Leading_zero && _Specs._Alignment == _Align::_None; + const bool _Write_leading_zeroes = _Specs._Leading_zero && _Specs._Alignment == _Fmt_align::_None; auto _Writer = [&, _End = _End](_OutputIt _Out) { #pragma warning(push) #pragma warning(disable : 4296) // '<': expression is always false @@ -1896,7 +1896,7 @@ _NODISCARD _OutputIt _Write_integral( return _Writer(_STD move(_Out)); } - return _Write_aligned(_STD move(_Out), _Width, _Specs, _Align::_Right, _Writer); + return _Write_aligned(_STD move(_Out), _Width, _Specs, _Fmt_align::_Right, _Writer); } #pragma warning(pop) @@ -2122,7 +2122,7 @@ _NODISCARD _OutputIt _Fmt_write( _Width += _Zeroes_to_append; - const bool _Write_leading_zeroes = _Specs._Leading_zero && _Specs._Alignment == _Align::_None && _Is_finite; + const bool _Write_leading_zeroes = _Specs._Leading_zero && _Specs._Alignment == _Fmt_align::_None && _Is_finite; auto _Writer = [&](_OutputIt _Out) { _Out = _Write_sign(_STD move(_Out), _Sgn, _Is_negative); @@ -2162,7 +2162,7 @@ _NODISCARD _OutputIt _Fmt_write( return _Writer(_STD move(_Out)); } - return _Write_aligned(_STD move(_Out), _Width, _Specs, _Align::_Right, _Writer); + return _Write_aligned(_STD move(_Out), _Width, _Specs, _Fmt_align::_Right, _Writer); } #pragma warning(pop) @@ -2204,7 +2204,7 @@ _NODISCARD _OutputIt _Fmt_write( _Width = 3; } - return _Write_aligned(_STD move(_Out), _Width, _Specs, _Align::_Left, + return _Write_aligned(_STD move(_Out), _Width, _Specs, _Fmt_align::_Left, [=](_OutputIt _Out) { return _Fmt_write<_CharT>(_STD move(_Out), _Value); }); } @@ -2368,7 +2368,7 @@ _NODISCARD _OutputIt _Fmt_write( int _Width = _Specs._Precision; const _CharT* _Last = _Measure_string_prefix(_Value, _Width); - return _Write_aligned(_STD move(_Out), _Width, _Specs, _Align::_Left, [=](_OutputIt _Out) { + return _Write_aligned(_STD move(_Out), _Width, _Specs, _Fmt_align::_Left, [=](_OutputIt _Out) { return _Fmt_write(_STD move(_Out), basic_string_view<_CharT>{_Value.data(), _Last}); }); } diff --git a/tests/std/include/test_format_support.hpp b/tests/std/include/test_format_support.hpp index d3bf9b92ac1..fa4246738ca 100644 --- a/tests/std/include/test_format_support.hpp +++ b/tests/std/include/test_format_support.hpp @@ -31,7 +31,7 @@ struct choose_literal { template struct noop_testing_callbacks { - constexpr void _On_align(std::_Align) {} + constexpr void _On_align(std::_Fmt_align) {} constexpr void _On_fill(std::basic_string_view) {} constexpr void _On_width(unsigned int) {} constexpr void _On_dynamic_width(std::size_t) {} @@ -48,8 +48,8 @@ struct noop_testing_callbacks { template struct testing_callbacks { - std::_Align expected_alignment = std::_Align::_None; - std::_Sign expected_sign = std::_Sign::_None; + std::_Fmt_align expected_alignment = std::_Fmt_align::_None; + std::_Sign expected_sign = std::_Sign::_None; std::basic_string_view expected_fill; int expected_width = -1; std::size_t expected_dynamic_width = static_cast(-1); @@ -62,7 +62,7 @@ struct testing_callbacks { bool expected_localized = false; CharT expected_type = '\0'; - constexpr void _On_align(std::_Align aln) { + constexpr void _On_align(std::_Fmt_align aln) { assert(aln == expected_alignment); } constexpr void _On_fill(std::basic_string_view str_view) { @@ -103,7 +103,7 @@ struct testing_callbacks { } }; template -testing_callbacks(std::_Align, std::basic_string_view) -> testing_callbacks; +testing_callbacks(std::_Fmt_align, std::basic_string_view) -> testing_callbacks; struct testing_arg_id_callbacks { constexpr void _On_auto_id() {} diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index 4aaf3288dd4..2ae3a52bb3e 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -36,7 +36,7 @@ struct choose_literal { template struct testing_callbacks { - _Align expected_alignment = _Align::_None; + _Fmt_align expected_alignment = _Fmt_align::_None; basic_string_view expected_fill; int expected_width = -1; size_t expected_dynamic_width = static_cast(-1); @@ -47,7 +47,7 @@ struct testing_callbacks { vector<_Chrono_specs>& expected_chrono_specs; size_t curr_index = 0; - void _On_align(_Align aln) { + void _On_align(_Fmt_align aln) { assert(aln == expected_alignment); } void _On_fill(basic_string_view str_view) { @@ -168,14 +168,14 @@ bool test_parse_chrono_format_specs() { vector v4{{._Lit_char = 'h'}, {._Lit_char = 'i'}}; test_parse_helper(parse_chrono_format_specs_fn, s4, false, s4.size(), - {.expected_alignment = _Align::_Left, + {.expected_alignment = _Fmt_align::_Left, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 6, .expected_chrono_specs = v4}); vector v5{{._Type = 'y'}, {._Lit_char = 'm'}, {._Lit_char = 'm'}}; test_parse_helper(parse_chrono_format_specs_fn, s5, false, s5.size(), - {.expected_alignment = _Align::_Center, + {.expected_alignment = _Fmt_align::_Center, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 4, .expected_precision = 4, diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index 5f3b28a6a8d..bccd47e9893 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -445,7 +445,7 @@ void test_fill_and_align() { auto tester = [&] { basic_string output_string; - (void) _Write_aligned(back_inserter(output_string), 2, specs, _Align::_Left, writer); + (void) _Write_aligned(back_inserter(output_string), 2, specs, _Fmt_align::_Left, writer); return output_string; }; @@ -456,24 +456,24 @@ void test_fill_and_align() { specs._Width = 5; - specs._Alignment = _Align::_Left; + specs._Alignment = _Fmt_align::_Left; assert(tester() == STR("AB ")); - specs._Alignment = _Align::_Right; + specs._Alignment = _Fmt_align::_Right; assert(tester() == STR(" AB")); - specs._Alignment = _Align::_Center; + specs._Alignment = _Fmt_align::_Center; assert(tester() == STR(" AB ")); - specs._Alignment = _Align::_Left; + specs._Alignment = _Fmt_align::_Left; specs._Fill[0] = {'*'}; assert(tester() == STR("AB***")); - specs._Alignment = _Align::_Right; + specs._Alignment = _Fmt_align::_Right; assert(tester() == STR("***AB")); - specs._Alignment = _Align::_Center; + specs._Alignment = _Fmt_align::_Center; assert(tester() == STR("*AB**")); } diff --git a/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/test.cpp b/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/test.cpp index af57f610fc3..beb4a499c62 100644 --- a/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_legacy_text_encoding/test.cpp @@ -49,11 +49,11 @@ void test_parse_align() { { assert(setlocale(LC_ALL, ".932") != nullptr); test_parse_helper(parse_align_fn, "\x93\xfaX"sv, false, 3, - {.expected_alignment = _Align::_Right, .expected_fill = "\x96\x7b"sv}); + {.expected_alignment = _Fmt_align::_Right, .expected_fill = "\x96\x7b"sv}); test_parse_helper(parse_align_fn, "\x92\x6e^X"sv, false, 3, - {.expected_alignment = _Align::_Center, .expected_fill = "\x92\x6e"sv}); + {.expected_alignment = _Fmt_align::_Center, .expected_fill = "\x92\x6e"sv}); } assert(setlocale(LC_ALL, "C") != nullptr); diff --git a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp index d82b6985af4..e44b7792888 100644 --- a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp @@ -24,11 +24,11 @@ bool test_parse_align() { view_typ s3(TYPED_LITERAL(CharT, "*^")); test_parse_helper(parse_align_fn, s1, false, view_typ::npos, - {.expected_alignment = _Align::_Left, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); + {.expected_alignment = _Fmt_align::_Left, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); test_parse_helper(parse_align_fn, s2, false, view_typ::npos, - {.expected_alignment = _Align::_Right, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); + {.expected_alignment = _Fmt_align::_Right, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); test_parse_helper(parse_align_fn, s3, false, view_typ::npos, - {.expected_alignment = _Align::_Center, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); + {.expected_alignment = _Fmt_align::_Center, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*"))}); if constexpr (same_as) { // This is a CJK character where the least significant byte is the same as ASCII '>', @@ -41,11 +41,11 @@ bool test_parse_align() { // test multi-code-unit fill characters { test_parse_helper(parse_align_fn, L"\U0001F3C8X"sv, false, 3, - {.expected_alignment = _Align::_Right, .expected_fill = L"\U0001F3C8"sv}); + {.expected_alignment = _Fmt_align::_Right, .expected_fill = L"\U0001F3C8"sv}); test_parse_helper(parse_align_fn, L"\U0001F3C8^X"sv, false, 3, - {.expected_alignment = _Align::_Center, .expected_fill = L"\U0001F3C8"sv}); + {.expected_alignment = _Fmt_align::_Center, .expected_fill = L"\U0001F3C8"sv}); } } else { // test multibyte fill characters @@ -54,11 +54,11 @@ bool test_parse_align() { assert(setlocale(LC_ALL, ".UTF-8") != nullptr); // "\xf0\x9f\x8f\x88" is U+1F3C8 AMERICAN FOOTBALL test_parse_helper(parse_align_fn, "\xf0\x9f\x8f\x88X"sv, false, 5, - {.expected_alignment = _Align::_Right, .expected_fill = "\xf0\x9f\x8f\x88"sv}); + {.expected_alignment = _Fmt_align::_Right, .expected_fill = "\xf0\x9f\x8f\x88"sv}); test_parse_helper(parse_align_fn, "\xf0\x9f\x8f\x88^X"sv, false, 5, - {.expected_alignment = _Align::_Center, .expected_fill = "\xf0\x9f\x8f\x88"sv}); + {.expected_alignment = _Fmt_align::_Center, .expected_fill = "\xf0\x9f\x8f\x88"sv}); } #endif // MSVC_INTERNAL_TESTING @@ -167,27 +167,27 @@ bool test_parse_format_specs() { view_typ s6(TYPED_LITERAL(CharT, "*^+#04.4La}")); test_parse_helper(parse_format_specs_fn, s0, false, s0.size() - 1, {.expected_width = 6}); test_parse_helper(parse_format_specs_fn, s1, false, s1.size(), - {.expected_alignment = _Align::_Left, + {.expected_alignment = _Fmt_align::_Left, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 6}); test_parse_helper(parse_format_specs_fn, s2, false, s2.size() - 1, - {.expected_alignment = _Align::_Right, + {.expected_alignment = _Fmt_align::_Right, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 6}); test_parse_helper(parse_format_specs_fn, s3, false, s3.size() - 1, - {.expected_alignment = _Align::_Center, + {.expected_alignment = _Fmt_align::_Center, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 6}); test_parse_helper(parse_format_specs_fn, s4, false, s4.size() - 1, {.expected_width = 6, .expected_type = 'd'}); test_parse_helper(parse_format_specs_fn, s5, false, s5.size() - 1, - {.expected_alignment = _Align::_Center, + {.expected_alignment = _Fmt_align::_Center, .expected_sign = _Sign::_Plus, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 4, .expected_precision = 4, .expected_type = 'a'}); test_parse_helper(parse_format_specs_fn, s6, false, s6.size() - 1, - {.expected_alignment = _Align::_Center, + {.expected_alignment = _Fmt_align::_Center, .expected_sign = _Sign::_Plus, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 4, diff --git a/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp b/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp index 4e6c895c5b5..5b988794238 100644 --- a/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp @@ -35,11 +35,11 @@ void test_parse_align() { { // "\xf0\x9f\x8f\x88" is U+1F3C8 AMERICAN FOOTBALL test_parse_helper(parse_align_fn, "\xf0\x9f\x8f\x88X"sv, false, 5, - {.expected_alignment = _Align::_Right, .expected_fill = "\xf0\x9f\x8f\x88"sv}); + {.expected_alignment = _Fmt_align::_Right, .expected_fill = "\xf0\x9f\x8f\x88"sv}); test_parse_helper(parse_align_fn, "\xf0\x9f\x8f\x88^X"sv, false, 5, - {.expected_alignment = _Align::_Center, .expected_fill = "\xf0\x9f\x8f\x88"sv}); + {.expected_alignment = _Fmt_align::_Center, .expected_fill = "\xf0\x9f\x8f\x88"sv}); } } From a04936db6afbc63dd86d5b0c1bb20f1c738971b3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 13 Apr 2021 04:15:11 -0700 Subject: [PATCH 45/45] Big rename: _Sign to _Fmt_sign. --- stl/inc/format | 40 +++++++++---------- tests/std/include/test_format_support.hpp | 6 +-- .../P0645R10_text_formatting_parsing/test.cpp | 4 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index a41bf068fa9..1970efdedbd 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -71,7 +71,7 @@ class format_error : public runtime_error { enum class _Fmt_align : uint8_t { _None, _Left, _Right, _Center }; -enum class _Sign : uint8_t { _None, _Plus, _Minus, _Space }; +enum class _Fmt_sign : uint8_t { _None, _Plus, _Minus, _Space }; enum class _Basic_format_arg_type : uint8_t { _None, @@ -149,7 +149,7 @@ concept _Parse_spec_callbacks = _Parse_align_callbacks<_Ty, _CharT> && _Parse_precision_callbacks<_Ty, _CharT> && _Width_adapter_callbacks<_Ty, _CharT> && _Precision_adapter_callbacks<_Ty, _CharT> - && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln, _Sign _Sgn) { + && requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln, _Fmt_sign _Sgn) { { _At._On_sign(_Sgn) } -> same_as; { _At._On_hash() } -> same_as; { _At._On_zero() } -> same_as; @@ -702,15 +702,15 @@ _NODISCARD constexpr const _CharT* _Parse_format_specs( switch (*_Begin) { case '+': - _Callbacks._On_sign(_Sign::_Plus); + _Callbacks._On_sign(_Fmt_sign::_Plus); ++_Begin; break; case '-': - _Callbacks._On_sign(_Sign::_Minus); + _Callbacks._On_sign(_Fmt_sign::_Minus); ++_Begin; break; case ' ': - _Callbacks._On_sign(_Sign::_Space); + _Callbacks._On_sign(_Fmt_sign::_Space); ++_Begin; break; default: @@ -874,7 +874,7 @@ struct _Basic_format_specs { int _Precision = -1; char _Type = '\0'; _Fmt_align _Alignment = _Fmt_align::_None; - _Sign _Sgn = _Sign::_None; + _Fmt_sign _Sgn = _Fmt_sign::_None; bool _Alt = false; bool _Localized = false; bool _Leading_zero = false; @@ -912,7 +912,7 @@ public: _Specs._Fill_length = static_cast(_Sv.size()); } - constexpr void _On_sign(const _Sign _Sgn) { + constexpr void _On_sign(const _Fmt_sign _Sgn) { _Specs._Sgn = _Sgn; } @@ -1663,19 +1663,19 @@ _NODISCARD constexpr string_view _Get_integral_prefix(const char _Type, const _I } template -_NODISCARD _OutputIt _Write_sign(_OutputIt _Out, const _Sign _Sgn, const bool _Is_negative) { +_NODISCARD _OutputIt _Write_sign(_OutputIt _Out, const _Fmt_sign _Sgn, const bool _Is_negative) { if (_Is_negative) { *_Out++ = '-'; } else { switch (_Sgn) { - case _Sign::_Plus: + case _Fmt_sign::_Plus: *_Out++ = '+'; break; - case _Sign::_Space: + case _Fmt_sign::_Space: *_Out++ = ' '; break; - case _Sign::_None: - case _Sign::_Minus: + case _Fmt_sign::_None: + case _Fmt_sign::_Minus: break; } } @@ -1808,8 +1808,8 @@ _NODISCARD _OutputIt _Write_integral( _THROW(format_error("integral cannot have a precision")); } - if (_Specs._Sgn == _Sign::_None) { - _Specs._Sgn = _Sign::_Minus; + if (_Specs._Sgn == _Fmt_sign::_None) { + _Specs._Sgn = _Fmt_sign::_Minus; } int _Base = 10; @@ -1847,7 +1847,7 @@ _NODISCARD _OutputIt _Write_integral( auto _Width = static_cast(_End - _Buffer_start); if (_Value >= _Integral{0}) { - if (_Specs._Sgn != _Sign::_Minus) { + if (_Specs._Sgn != _Fmt_sign::_Minus) { _Width += 1; } } else { @@ -1956,8 +1956,8 @@ template _NODISCARD _OutputIt _Fmt_write( _OutputIt _Out, const _Float _Value, const _Basic_format_specs<_CharT>& _Specs, locale _Locale) { auto _Sgn = _Specs._Sgn; - if (_Sgn == _Sign::_None) { - _Sgn = _Sign::_Minus; + if (_Sgn == _Fmt_sign::_None) { + _Sgn = _Fmt_sign::_Minus; } auto _To_upper = false; @@ -2051,7 +2051,7 @@ _NODISCARD _OutputIt _Fmt_write( // Remove the '-', it will be dealt with directly _Buffer_start += 1; } else { - if (_Sgn != _Sign::_Minus) { + if (_Sgn != _Fmt_sign::_Minus) { _Width += 1; } } @@ -2173,7 +2173,7 @@ _NODISCARD _OutputIt _Fmt_write( _THROW(format_error("invalid const void* type")); } - if (_Specs._Sgn != _Sign::_None) { + if (_Specs._Sgn != _Fmt_sign::_None) { _THROW(format_error("const void* cannot have a sign")); } @@ -2345,7 +2345,7 @@ _NODISCARD _OutputIt _Fmt_write( _THROW(format_error("invalid string type")); } - if (_Specs._Sgn != _Sign::_None) { + if (_Specs._Sgn != _Fmt_sign::_None) { _THROW(format_error("string cannot have a sign")); } diff --git a/tests/std/include/test_format_support.hpp b/tests/std/include/test_format_support.hpp index fa4246738ca..89dd541e85c 100644 --- a/tests/std/include/test_format_support.hpp +++ b/tests/std/include/test_format_support.hpp @@ -39,7 +39,7 @@ struct noop_testing_callbacks { constexpr void _On_precision(unsigned int) {} constexpr void _On_dynamic_precision(std::size_t) {} constexpr void _On_dynamic_precision(std::_Auto_id_tag) {} - constexpr void _On_sign(std::_Sign) {} + constexpr void _On_sign(std::_Fmt_sign) {} constexpr void _On_hash() {} constexpr void _On_zero() {} constexpr void _On_localized() {} @@ -49,7 +49,7 @@ struct noop_testing_callbacks { template struct testing_callbacks { std::_Fmt_align expected_alignment = std::_Fmt_align::_None; - std::_Sign expected_sign = std::_Sign::_None; + std::_Fmt_sign expected_sign = std::_Fmt_sign::_None; std::basic_string_view expected_fill; int expected_width = -1; std::size_t expected_dynamic_width = static_cast(-1); @@ -86,7 +86,7 @@ struct testing_callbacks { constexpr void _On_dynamic_precision(std::_Auto_id_tag) { assert(expected_auto_dynamic_precision); } - constexpr void _On_sign(std::_Sign sgn) { + constexpr void _On_sign(std::_Fmt_sign sgn) { assert(sgn == expected_sign); } constexpr void _On_hash() { diff --git a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp index e44b7792888..ddf204c0db5 100644 --- a/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_parsing/test.cpp @@ -181,14 +181,14 @@ bool test_parse_format_specs() { test_parse_helper(parse_format_specs_fn, s4, false, s4.size() - 1, {.expected_width = 6, .expected_type = 'd'}); test_parse_helper(parse_format_specs_fn, s5, false, s5.size() - 1, {.expected_alignment = _Fmt_align::_Center, - .expected_sign = _Sign::_Plus, + .expected_sign = _Fmt_sign::_Plus, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 4, .expected_precision = 4, .expected_type = 'a'}); test_parse_helper(parse_format_specs_fn, s6, false, s6.size() - 1, {.expected_alignment = _Fmt_align::_Center, - .expected_sign = _Sign::_Plus, + .expected_sign = _Fmt_sign::_Plus, .expected_fill = view_typ(TYPED_LITERAL(CharT, "*")), .expected_width = 4, .expected_precision = 4,