[libcxx-commits] [libcxx] faacf8b - [libc++][format] Addresses LWG3833.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Mar 4 04:53:44 PST 2023


Author: Mark de Wever
Date: 2023-03-04T13:53:38+01:00
New Revision: faacf8bca33716a07c74a4996e87df1bc673d7ea

URL: https://github.com/llvm/llvm-project/commit/faacf8bca33716a07c74a4996e87df1bc673d7ea
DIFF: https://github.com/llvm/llvm-project/commit/faacf8bca33716a07c74a4996e87df1bc673d7ea.diff

LOG: [libc++][format] Addresses LWG3833.

  LWG3833 Remove specialization template<size_t N> struct formatter<const charT[N], charT>

Depends on D143845

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D143850

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes.rst
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/include/__format/formatter_string.h
    libcxx/include/__format/range_default_formatter.h

Removed: 
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 50f7ef58395e9..549efe727f2ce 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -64,6 +64,12 @@ Deprecations and Removals
 - The headers ``<experimental/algorithm>`` and ``<experimental/functional>`` have been removed, since all the contents
   have been implemented in namespace ``std`` for at least two releases.
 
+- The formatter specialization ``template<size_t N> struct formatter<const charT[N], charT>``
+  has been removed. Since libc++'s format library was marked experimental there
+  is no backwards compatibility option. This specialization has been removed
+  from the Standard since it was never used, the proper specialization to use
+  instead is ``template<size_t N> struct formatter<charT[N], charT>``.
+
 Upcoming Deprecations and Removals
 ----------------------------------
 

diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 1635613be418d..324643b96a816 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -289,7 +289,7 @@
 "`3810 <https://wg21.link/LWG3810>`__","CTAD for ``std::basic_format_args``","February 2023","|Complete|","17.0","|format|"
 "`3827 <https://wg21.link/LWG3827>`__","Deprecate ``<stdalign.h>`` and ``<stdbool.h>`` macros","February 2023","","",""
 "`3828 <https://wg21.link/LWG3828>`__","Sync ``intmax_t`` and ``uintmax_t`` with C2x","February 2023","","",""
-"`3833 <https://wg21.link/LWG3833>`__","Remove specialization ``template<size_t N> struct formatter<const charT[N], charT>``","February 2023","","","|format|"
+"`3833 <https://wg21.link/LWG3833>`__","Remove specialization ``template<size_t N> struct formatter<const charT[N], charT>``","February 2023","|Complete|","17.0","|format|"
 "`3836 <https://wg21.link/LWG3836>`__","``std::expected<bool, E1>`` conversion constructor ``expected(const expected<U, G>&)`` should take precedence over ``expected(U&&)`` with operator ``bool``","February 2023","","",""
 "`3843 <https://wg21.link/LWG3843>`__","``std::expected<T,E>::value() &`` assumes ``E`` is copy constructible","February 2023","","",""
 "`3847 <https://wg21.link/LWG3847>`__","``ranges::to`` can still return views","February 2023","","","|ranges|"

diff  --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h
index 8e880ce6e8f03..e11708d8e28cc 100644
--- a/libcxx/include/__format/formatter_string.h
+++ b/libcxx/include/__format/formatter_string.h
@@ -115,17 +115,6 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT[_Size],
   }
 };
 
-// Formatter const char[].
-template <__fmt_char_type _CharT, size_t _Size>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT[_Size], _CharT>
-    : public __formatter_string<_CharT> {
-  using _Base = __formatter_string<_CharT>;
-
-  _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) {
-    return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx);
-  }
-};
-
 // Formatter std::string.
 template <__fmt_char_type _CharT, class _Traits, class _Allocator>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>

diff  --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h
index b8fe4d2e294d2..136ff063d0697 100644
--- a/libcxx/include/__format/range_default_formatter.h
+++ b/libcxx/include/__format/range_default_formatter.h
@@ -83,23 +83,6 @@ inline constexpr range_format format_kind<_Rp> = [] {
     return range_format::sequence;
 }();
 
-// This is a non-standard work-around to fix instantiation of
-//   formatter<const _CharT[N], _CharT>
-// const _CharT[N] satisfies the ranges::input_range concept.
-// remove_cvref_t<const _CharT[N]> is _CharT[N] so it does not satisfy the
-// requirement of the above specialization. Instead it will instantiate the
-// primary template, which is ill-formed.
-//
-// An alternative solution is to remove the offending formatter.
-//
-// https://godbolt.org/z/bqjhhaexx
-//
-// The removal is proposed in LWG3833, but use the work-around until the issue
-// has been adopted.
-// TODO FMT Implement LWG3833.
-template <class _CharT, size_t N>
-inline constexpr range_format format_kind<const _CharT[N]> = range_format::disabled;
-
 template <range_format _Kp, ranges::input_range _Rp, class _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter;
 

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
deleted file mode 100644
index 815bd449b9792..0000000000000
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-//===----------------------------------------------------------------------===//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-// UNSUPPORTED: libcpp-has-no-incomplete-format
-// TODO FMT Evaluate gcc-12 status
-// UNSUPPORTED: gcc-12
-
-// <format>
-
-// C++23 the formatter is a debug-enabled specialization.
-// [format.formatter.spec]:
-// Each header that declares the template `formatter` provides the following
-// enabled specializations:
-// For each `charT`, the string type specializations
-//   template<size_t N> struct formatter<const charT[N], charT>;
-
-#include <format>
-#include <cassert>
-#include <concepts>
-#include <iterator>
-#include <type_traits>
-
-#include "test_format_context.h"
-#include "test_macros.h"
-#include "make_string.h"
-
-#define STR(S) MAKE_STRING(CharT, S)
-#define SV(S) MAKE_STRING_VIEW(CharT, S)
-#define CSTR(S) MAKE_CSTRING(CharT, S)
-
-// This is based on the method found in
-// clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-cxx20.cpp
-template <size_t N>
-struct Tester {
-  // This is not part of the real test, but is used the deduce the size of the input.
-  constexpr Tester(const char (&r)[N]) { __builtin_memcpy(text, r, N); }
-  char text[N];
-
-  // The size of the array shouldn't include the NUL character.
-  static const size_t size = N - 1;
-
-  template <class CharT>
-  void test(const std::basic_string<CharT>& expected,
-            const std::basic_string_view<CharT>& fmt) const {
-    using Str = const CharT[size];
-    std::basic_format_parse_context<CharT> parse_ctx{fmt};
-    std::formatter<Str, CharT> formatter;
-    static_assert(std::semiregular<decltype(formatter)>);
-
-    auto it = formatter.parse(parse_ctx);
-    assert(it == fmt.end() - (!fmt.empty() && fmt.back() == '}'));
-
-    std::basic_string<CharT> result;
-    auto out = std::back_inserter(result);
-    using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
-
-    std::basic_string<CharT> buffer{text, text + N};
-    // Note not too found of this hack
-    Str* data = reinterpret_cast<Str*>(buffer.c_str());
-
-    FormatCtxT format_ctx =
-        test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(*data));
-    formatter.format(*data, format_ctx);
-    assert(result == expected);
-  }
-
-  template <class CharT>
-  void test_termination_condition(const std::basic_string<CharT>& expected,
-                                  const std::basic_string<CharT>& f) const {
-    // The format-spec is valid if completely consumed or terminates at a '}'.
-    // The valid inputs all end with a '}'. The test is executed twice:
-    // - first with the terminating '}',
-    // - second consuming the entire input.
-    std::basic_string_view<CharT> fmt{f};
-    assert(fmt.back() == CharT('}') && "Pre-condition failure");
-
-    test(expected, fmt);
-    fmt.remove_suffix(1);
-    test(expected, fmt);
-  }
-};
-
-template <size_t N>
-Tester(const char (&)[N]) -> Tester<N>;
-
-template <Tester t, class CharT>
-void test_helper_wrapper(std::basic_string<CharT> expected,
-                         std::basic_string<CharT> fmt) {
-  t.test_termination_condition(expected, fmt);
-}
-
-#if TEST_STD_VER > 20
-template <class CharT>
-constexpr bool test_set_debug_format() {
-  std::formatter<const CharT[1], CharT> formatter;
-  LIBCPP_ASSERT(formatter.__parser_.__type_ == std::__format_spec::__type::__default);
-
-  formatter.set_debug_format();
-  LIBCPP_ASSERT(formatter.__parser_.__type_ == std::__format_spec::__type::__debug);
-
-  std::basic_string_view fmt = SV("s}");
-  std::basic_format_parse_context<CharT> parse_ctx{fmt};
-  formatter.parse(parse_ctx);
-  LIBCPP_ASSERT(formatter.__parser_.__type_ == std::__format_spec::__type::__string);
-
-  formatter.set_debug_format();
-  LIBCPP_ASSERT(formatter.__parser_.__type_ == std::__format_spec::__type::__debug);
-
-  return true;
-}
-#endif
-template <class CharT>
-void test_array() {
-  test_helper_wrapper<" azAZ09,./<>?">(STR(" azAZ09,./<>?"), STR("}"));
-
-  std::basic_string<CharT> s(CSTR("abc\0abc"), 7);
-  test_helper_wrapper<"abc\0abc">(s, STR("}"));
-
-  test_helper_wrapper<"world">(STR("world"), STR("}"));
-  test_helper_wrapper<"world">(STR("world"), STR("_>}"));
-
-  test_helper_wrapper<"world">(STR("   world"), STR(">8}"));
-  test_helper_wrapper<"world">(STR("___world"), STR("_>8}"));
-  test_helper_wrapper<"world">(STR("_world__"), STR("_^8}"));
-  test_helper_wrapper<"world">(STR("world___"), STR("_<8}"));
-
-  test_helper_wrapper<"world">(STR("world"), STR(".5}"));
-  test_helper_wrapper<"universe">(STR("unive"), STR(".5}"));
-
-  test_helper_wrapper<"world">(STR("%world%"), STR("%^7.7}"));
-  test_helper_wrapper<"universe">(STR("univers"), STR("%^7.7}"));
-
-#if TEST_STD_VER > 20
-  test_set_debug_format<CharT>();
-  static_assert(test_set_debug_format<CharT>());
-#endif
-}
-
-int main(int, char**) {
-  test_array<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test_array<wchar_t>();
-#endif
-
-  return 0;
-}


        


More information about the libcxx-commits mailing list