[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