[libcxx-commits] [libcxx] [libc++][format] Don't treat a closing '}' as part of format-spec (PR #81305)
Po-yao Chang via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Feb 10 07:30:22 PST 2024
https://github.com/poyaoc97 updated https://github.com/llvm/llvm-project/pull/81305
>From 12dc222f05737d1950c50c4fa426011d39805acf Mon Sep 17 00:00:00 2001
From: Po-yao Chang <poyaoc97 at gmail.com>
Date: Sat, 10 Feb 2024 04:06:01 +0800
Subject: [PATCH] [libc++][format] Don't treat a closing '}' as part of
format-spec
This allows:
```
std::println("{}>42", std::thread::id{});
std::println("{}>42", std::span<int>{});
std::println("{}>42", std::pair{42, "Hello"sv});
```
to compile and run.
---
libcxx/include/__format/format_functions.h | 4 ++--
libcxx/include/__format/format_parse_context.h | 6 +++++-
libcxx/include/__format/parser_std_format_spec.h | 2 +-
.../utilities/format/format.tuple/format.functions.tests.h | 1 +
4 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index 3ee53539f4ee6c..ad0ec354686807 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -251,7 +251,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
if (__r.__last == __end)
std::__throw_format_error("The argument index should end with a ':' or a '}'");
- bool __parse = *__r.__last == _CharT(':');
+ bool __parse = __parse_ctx.__should_parse() = *__r.__last == _CharT(':');
switch (*__r.__last) {
case _CharT(':'):
// The arg-id has a format-specifier, advance the input to the format-spec.
@@ -269,7 +269,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
__arg_t __type = __ctx.arg(__r.__value);
if (__type == __arg_t::__none)
std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
- else if (__type == __arg_t::__handle)
+ else if (__parse && __type == __arg_t::__handle)
__ctx.__handle(__r.__value).__parse(__parse_ctx);
else if (__parse)
__format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
diff --git a/libcxx/include/__format/format_parse_context.h b/libcxx/include/__format/format_parse_context.h
index aefcd5497f3b9b..74a0d0a6305c69 100644
--- a/libcxx/include/__format/format_parse_context.h
+++ b/libcxx/include/__format/format_parse_context.h
@@ -36,7 +36,8 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
__end_(__fmt.end()),
__indexing_(__unknown),
__next_arg_id_(0),
- __num_args_(__num_args) {}
+ __num_args_(__num_args),
+ __parse_(true) {}
basic_format_parse_context(const basic_format_parse_context&) = delete;
basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
@@ -83,6 +84,8 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
std::__throw_format_error("Argument index outside the valid range");
}
+ _LIBCPP_HIDE_FROM_ABI constexpr bool& __should_parse() { return __parse_; }
+
private:
iterator __begin_;
iterator __end_;
@@ -90,6 +93,7 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
_Indexing __indexing_;
size_t __next_arg_id_;
size_t __num_args_;
+ bool __parse_;
};
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context);
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index cf8af87b212849..d42ce2dbb456aa 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) {
auto __begin = __ctx.begin();
auto __end = __ctx.end();
- if (__begin == __end)
+ if (__begin == __end || !__ctx.__should_parse())
return __begin;
if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end)
diff --git a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
index dd99d2070dbb8a..bcb2bc7ebe03b8 100644
--- a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
@@ -77,6 +77,7 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>
void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {
check(SV("(42, \"hello\")"), SV("{}"), input);
+ check(SV("(42, \"hello\")^42"), SV("{}^42"), input);
// *** align-fill & width ***
check(SV("(42, \"hello\") "), SV("{:18}"), input);
More information about the libcxx-commits
mailing list