[libcxx-commits] [libcxx] a9e5773 - [libc++][format] Implements formatting pointer.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 5 09:23:38 PDT 2023
Author: Mark de Wever
Date: 2023-07-05T18:23:31+02:00
New Revision: a9e5773f520bed4099950b5f4b42a17151c2ef36
URL: https://github.com/llvm/llvm-project/commit/a9e5773f520bed4099950b5f4b42a17151c2ef36
DIFF: https://github.com/llvm/llvm-project/commit/a9e5773f520bed4099950b5f4b42a17151c2ef36.diff
LOG: [libc++][format] Implements formatting pointer.
The feature is applied as DR instead of a normal paper. MSVC STL and
libstdc++ will do the same.
Implements
- P2510R3 Formatting pointers
Depends on D153192
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D153195
Added:
Modified:
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx2c.rst
libcxx/docs/Status/Cxx2cPapers.csv
libcxx/docs/Status/FormatIssues.csv
libcxx/docs/UsingLibcxx.rst
libcxx/include/__format/formatter_pointer.h
libcxx/include/__format/parser_std_format_spec.h
libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
libcxx/test/std/utilities/format/format.functions/format_tests.h
libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
libcxx/test/support/format.functions.common.h
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 0dd9cde29f824e..cfed0b0949f299 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -47,6 +47,7 @@ Implemented Papers
- P2505R5 - Monadic operations for ``std::expected``
- P2711R1 - Making Multi-Param Constructors Of views explicit (``join_with_view`` is not done yet)
- P2572R1 - ``std::format`` fill character allowances
+- P2510R3 - Formatting pointers
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx2c.rst b/libcxx/docs/Status/Cxx2c.rst
index 8f5ca4f96f7ae6..a7ebc4662f517c 100644
--- a/libcxx/docs/Status/Cxx2c.rst
+++ b/libcxx/docs/Status/Cxx2c.rst
@@ -37,6 +37,10 @@ Paper Status
:header-rows: 1
:widths: auto
+.. note::
+
+ .. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
+
.. _issues-status-cxx2c:
Library Working Group Issues Status
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 19836a683dd315..f00a123bd85a25 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -7,7 +7,7 @@
"`P2530R3 <https://wg21.link/P2530R3>`__","LWG","Hazard Pointers for C++26","Varna June 2023","","",""
"`P2538R1 <https://wg21.link/P2538R1>`__","LWG","ADL-proof ``std::projected``","Varna June 2023","","","|ranges|"
"`P2495R3 <https://wg21.link/P2495R3>`__","LWG","Interfacing ``stringstreams`` with ``string_view``","Varna June 2023","","",""
-"`P2510R3 <https://wg21.link/P2510R3>`__","LWG","Formatting pointers","Varna June 2023","|In Progress|","","|format|"
+"`P2510R3 <https://wg21.link/P2510R3>`__","LWG","Formatting pointers","Varna June 2023","|Complete| [#note-P2510R3]_","17.0","|format|"
"`P2198R7 <https://wg21.link/P2198R7>`__","LWG","Freestanding Feature-Test Macros and Implementation-Defined Extensions","Varna June 2023","","",""
"`P2338R4 <https://wg21.link/P2338R4>`__","LWG","Freestanding Library: Character primitives and the C library","Varna June 2023","","",""
"`P2013R5 <https://wg21.link/P2013R5>`__","LWG","Freestanding Language: Optional ``::operator new``","Varna June 2023","","",""
diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv
index 72c9a923eecf60..5fc53ece784316 100644
--- a/libcxx/docs/Status/FormatIssues.csv
+++ b/libcxx/docs/Status/FormatIssues.csv
@@ -14,7 +14,7 @@ Number,Name,Standard,Assignee,Status,First released version
"`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","C++23","Mark de Wever","|Complete|",17.0
"`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","C++23","Mark de Wever","|Complete|",17.0
"`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``","C++23","Mark de Wever","|In progress|"
-"`P2510R3 <https://wg21.link/P2510R3>`__","Formatting pointers","C++26","Mark de Wever","|In Progress|",
+"`P2510R3 <https://wg21.link/P2510R3>`__","Formatting pointers","C++26","Mark de Wever","|Complete|", 17.0
"`P2757R3 <https://wg21.link/P2757R3>`__","Type-checking format args","C++26","","",
"`P2637R3 <https://wg21.link/P2637R3>`__","Member ``visit``","C++26","","",
`P1361 <https://wg21.link/P1361>`_,"Integration of chrono with text formatting","C++20",Mark de Wever,|In Progress|,
diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst
index 96fee66557e5be..4cc649d1ccb114 100644
--- a/libcxx/docs/UsingLibcxx.rst
+++ b/libcxx/docs/UsingLibcxx.rst
@@ -537,6 +537,9 @@ versions. This allows the library to have better estimates for newly introduced
Unicode code points, without requiring the user to use the latest C++ version
in their code base.
+In C++26 formatting pointers gained a type ``P`` and allows to use
+zero-padding. These options have been retroactively applied to C++20.
+
Turning off ASan annotation in containers
-----------------------------------------
diff --git a/libcxx/include/__format/formatter_pointer.h b/libcxx/include/__format/formatter_pointer.h
index ab699ba65ccd84..18aaee10de195f 100644
--- a/libcxx/include/__format/formatter_pointer.h
+++ b/libcxx/include/__format/formatter_pointer.h
@@ -43,11 +43,15 @@ struct _LIBCPP_TEMPLATE_VIS __formatter_pointer {
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const void* __ptr, _FormatContext& __ctx) const {
__format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
__specs.__std_.__alternate_form_ = true;
- __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case;
+ __specs.__std_.__type_ =
+ __specs.__std_.__type_ == __format_spec::__type::__pointer_upper_case
+ ? __format_spec::__type::__hexadecimal_upper_case
+ : __format_spec::__type::__hexadecimal_lower_case;
+
return __formatter::__format_integer(reinterpret_cast<uintptr_t>(__ptr), __ctx, __specs);
}
- __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right};
+ __format_spec::__parser<_CharT> __parser_;
};
// [format.formatter.spec]/2.4
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index 25f2567cde20d0..30fecffb00de0d 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -151,7 +151,7 @@ inline constexpr __fields __fields_floating_point{
.__locale_specific_form_ = true,
.__type_ = true};
inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true};
-inline constexpr __fields __fields_pointer{.__type_ = true};
+inline constexpr __fields __fields_pointer{.__zero_padding_ = true, .__type_ = true};
# if _LIBCPP_STD_VER >= 23
inline constexpr __fields __fields_tuple{.__use_range_fill_ = true};
@@ -189,7 +189,8 @@ enum class _LIBCPP_ENUM_VIS __type : uint8_t {
__decimal,
__hexadecimal_lower_case,
__hexadecimal_upper_case,
- __pointer,
+ __pointer_lower_case,
+ __pointer_upper_case,
__char,
__hexfloat_lower_case,
__hexfloat_upper_case,
@@ -675,7 +676,10 @@ class _LIBCPP_TEMPLATE_VIS __parser {
__type_ = __type::__octal;
break;
case 'p':
- __type_ = __type::__pointer;
+ __type_ = __type::__pointer_lower_case;
+ break;
+ case 'P':
+ __type_ = __type::__pointer_upper_case;
break;
case 's':
__type_ = __type::__string;
@@ -840,7 +844,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_C
_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type) {
switch (__type) {
case __format_spec::__type::__default:
- case __format_spec::__type::__pointer:
+ case __format_spec::__type::__pointer_lower_case:
+ case __format_spec::__type::__pointer_upper_case:
break;
default:
diff --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
index 584ac2b2d8d109..2497bc8111f65d 100644
--- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
+++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
@@ -717,7 +717,9 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
// *** zero-padding ***
- check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+ check(SV("[0x0000]"), SV("{::06}"), input);
+ check(SV("[0x0000]"), SV("{::06p}"), input);
+ check(SV("[0X0000]"), SV("{::06P}"), input);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
@@ -726,7 +728,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
// *** type ***
- for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("p"))
+ for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("pP"))
check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
// ***** Both have a format-spec
diff --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h
index c798b3686fc689..19ef5874d64840 100644
--- a/libcxx/test/std/utilities/format/format.functions/format_tests.h
+++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h
@@ -37,9 +37,9 @@ case #T[0]:
break;
#if TEST_STD_VER > 20
- constexpr std::string_view types = "aAbBcdeEfFgGopsxX?";
+ constexpr std::string_view types = "aAbBcdeEfFgGopPsxX?";
#else
- constexpr std::string_view types = "aAbBcdeEfFgGopsxX";
+ constexpr std::string_view types = "aAbBcdeEfFgGopPsxX";
#endif
for (auto type : types) {
@@ -61,6 +61,7 @@ case #T[0]:
CASE(G)
CASE(o)
CASE(p)
+ CASE(P)
CASE(s)
CASE(x)
CASE(X)
@@ -2547,6 +2548,11 @@ void format_test_pointer(TestFunction check, ExceptionTest check_exception) {
check(SV("answer is '0x0:::'"), SV("answer is '{::<6}'"), P(nullptr));
check(SV("answer is ':0x0::'"), SV("answer is '{::^6}'"), P(nullptr));
+ // Test whether zero padding is ignored
+ check(SV("answer is ':::0x0'"), SV("answer is '{::>06}'"), P(nullptr));
+ check(SV("answer is '0x0:::'"), SV("answer is '{::<06}'"), P(nullptr));
+ check(SV("answer is ':0x0::'"), SV("answer is '{::^06}'"), P(nullptr));
+
// *** Sign ***
check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), P(nullptr));
check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), P(nullptr));
@@ -2556,7 +2562,9 @@ void format_test_pointer(TestFunction check, ExceptionTest check_exception) {
check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), P(nullptr));
// *** zero-padding ***
- check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), P(nullptr));
+ check(SV("answer is '0x0000'"), SV("answer is '{:06}'"), P(nullptr));
+ check(SV("answer is '0x0000'"), SV("answer is '{:06p}'"), P(nullptr));
+ check(SV("answer is '0X0000'"), SV("answer is '{:06P}'"), P(nullptr));
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), P(nullptr));
@@ -2565,7 +2573,7 @@ void format_test_pointer(TestFunction check, ExceptionTest check_exception) {
check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), P(nullptr));
// *** type ***
- for (const auto& fmt : invalid_types<CharT>("p"))
+ for (const auto& fmt : invalid_types<CharT>("pP"))
check_exception("The format-spec type has a type not supported for a pointer argument", fmt, P(nullptr));
}
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
index bbb49e2ed52767..671785f9698e3d 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
@@ -886,7 +886,9 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
// *** zero-padding ***
- check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+ check(SV("{0x0000}"), SV("{::06}"), input);
+ check(SV("{0x0000}"), SV("{::06p}"), input);
+ check(SV("{0X0000}"), SV("{::06P}"), input);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
@@ -895,7 +897,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
// *** type ***
- for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("p"))
+ for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("pP"))
check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
// ***** Both have a format-spec
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
index 57f1861fa92e2e..550450d8acb05a 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
@@ -700,7 +700,9 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
// *** zero-padding ***
- check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+ check(SV("[0x0000]"), SV("{::06}"), input);
+ check(SV("[0x0000]"), SV("{::06p}"), input);
+ check(SV("[0X0000]"), SV("{::06P}"), input);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
@@ -709,7 +711,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
// *** type ***
- for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("p"))
+ for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("pP"))
check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
// ***** Both have a format-spec
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 2c21f6cdd78ede..e649543934d6d7 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
@@ -67,7 +67,7 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
check(SV("__42: 99___"), SV("{:_^11m}"), input);
check(SV("__42, 99___"), SV("{:_^11n}"), input);
- for (CharT c : SV("aAbBcdeEfFgGopsxX?")) {
+ for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {
check_exception("The format-spec should consume the input or end with a '}'",
std::basic_string_view{STR("{:") + c + STR("}")},
input);
@@ -114,7 +114,7 @@ void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_excep
check(SV("__42: \"hello\"___"), SV("{:_^16m}"), input);
check(SV("__42, \"hello\"___"), SV("{:_^16n}"), input);
- for (CharT c : SV("aAbBcdeEfFgGopsxX?")) {
+ for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {
check_exception("The format-spec should consume the input or end with a '}'",
std::basic_string_view{STR("{:") + c + STR("}")},
input);
@@ -204,7 +204,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
check_exception("The format specifier m requires a pair or a two-element tuple", SV("{:m}"), input);
check(SV("__42___"), SV("{:_^7n}"), input);
- for (CharT c : SV("aAbBcdeEfFgGopsxX?")) {
+ for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {
check_exception("The format-spec should consume the input or end with a '}'",
std::basic_string_view{STR("{:") + c + STR("}")},
input);
@@ -253,7 +253,7 @@ void test_tuple_int_string_color(TestFunction check, ExceptionTest check_excepti
check_exception("The format specifier m requires a pair or a two-element tuple", SV("{:m}"), input);
check(SV("__42, \"hello\", \"red\"___"), SV("{:_^23n}"), input);
- for (CharT c : SV("aAbBcdeEfFgGopsxX?")) {
+ for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {
check_exception("The format-spec should consume the input or end with a '}'",
std::basic_string_view{STR("{:") + c + STR("}")},
input);
@@ -326,7 +326,7 @@ void test_nested(TestFunction check, ExceptionTest check_exception, Nested&& inp
check(SV("__42: (\"hello\", \"red\")___"), SV("{:_^25m}"), input);
check(SV("__42, (\"hello\", \"red\")___"), SV("{:_^25n}"), input);
- for (CharT c : SV("aAbBcdeEfFgGopsxX?")) {
+ for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {
check_exception("The format-spec should consume the input or end with a '}'",
std::basic_string_view{STR("{:") + c + STR("}")},
input);
diff --git a/libcxx/test/support/format.functions.common.h b/libcxx/test/support/format.functions.common.h
index e979a200b933df..656ac9996dff34 100644
--- a/libcxx/test/support/format.functions.common.h
+++ b/libcxx/test/support/format.functions.common.h
@@ -205,7 +205,7 @@ std::basic_string<CharT> get_colons() {
}
constexpr std::string_view get_format_types() {
- return "aAbBcdeEfFgGopsxX"
+ return "aAbBcdeEfFgGopPsxX"
#if TEST_STD_VER > 20
"?"
#endif
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 3f4ba0e7437614..759badf09ec011 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -462,7 +462,7 @@ def add_version_header(tc):
# "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
},
# Note these three papers are adopted at the June 2023 meeting and have sequential numbering
- # 202304 P2510R3 Formatting pointers
+ # 202304 P2510R3 Formatting pointers (Implemented)
# 202305 P2757R3 Type-checking format args
# 202306 P2637R3 Member Visit
"headers": ["format"],
More information about the libcxx-commits
mailing list