diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -47,6 +47,7 @@
 - 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/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
--- 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|","Clang 17","|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
--- a/libcxx/docs/Status/FormatIssues.csv
+++ b/libcxx/docs/Status/FormatIssues.csv
@@ -14,7 +14,7 @@
 "`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","C++23","Mark de Wever","|Complete|", Clang 17
 "`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","C++23","Mark de Wever","|Complete|", Clang 17
 "`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|", Clang 17
 "`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
--- a/libcxx/docs/UsingLibcxx.rst
+++ b/libcxx/docs/UsingLibcxx.rst
@@ -536,6 +536,10 @@
 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
--- a/libcxx/include/__format/formatter_pointer.h
+++ b/libcxx/include/__format/formatter_pointer.h
@@ -43,11 +43,15 @@
   _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
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -152,7 +152,7 @@
     .__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};
@@ -190,7 +190,8 @@
   __decimal,
   __hexadecimal_lower_case,
   __hexadecimal_upper_case,
-  __pointer,
+  __pointer_lower_case,
+  __pointer_upper_case,
   __char,
   __hexfloat_lower_case,
   __hexfloat_upper_case,
@@ -676,7 +677,10 @@
       __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;
@@ -841,7 +845,8 @@
 _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/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h
--- 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 @@
   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(G)
       CASE(o)
       CASE(p)
+      CASE(P)
       CASE(s)
       CASE(x)
       CASE(X)
@@ -2547,6 +2548,11 @@
   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 @@
   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 @@
   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
--- 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 @@
   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 @@
   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
--- 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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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
--- a/libcxx/test/support/format.functions.common.h
+++ b/libcxx/test/support/format.functions.common.h
@@ -205,7 +205,7 @@
 }
 
 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
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -463,7 +463,7 @@
                 # "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 (Implemlemented)
             # 202305 P2757R3 Type-checking format args
             # 202306 P2637R3 Member Visit
             "headers": ["format"],