[libcxx-commits] [libcxx] [libc++][format] Fixes formatting code units as integers. (PR #73396)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 28 10:25:56 PST 2023


================
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+// 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
+// ADDITIONAL_COMPILE_FLAGS: -fsigned-char
+
+// <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:
+// The specializations
+//   template<> struct formatter<char, char>;
+//   template<> struct formatter<char, wchar_t>;
+//   template<> struct formatter<wchar_t, wchar_t>;
+
+// P2909R4 "Fix formatting of code units as integers (Dude, where’s my char?)"
+// changed the behaviour of char (and wchar_t) when their underlying type is signed.
+
+#include <format>
+#include <cassert>
+#include <concepts>
+#include <iterator>
+#include <type_traits>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+#include "assert_macros.h"
+#include "concat_macros.h"
+
+#define STR(S) MAKE_STRING(CharT, S)
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringT, class StringViewT, class ArgumentT>
+void test(StringT expected, StringViewT fmt, ArgumentT arg) {
+  using CharT    = typename StringT::value_type;
+  auto parse_ctx = std::basic_format_parse_context<CharT>(fmt);
+  std::formatter<ArgumentT, CharT> formatter;
+  static_assert(std::semiregular<decltype(formatter)>);
+
+  formatter.parse(parse_ctx);
+
+  StringT result;
+  auto out         = std::back_inserter(result);
+  using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
+
+  FormatCtxT format_ctx = test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
+  formatter.format(arg, format_ctx);
+  TEST_REQUIRE(result == expected,
+               TEST_WRITE_CONCATENATED(
+                   "\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", result, '\n'));
+}
+
+template <class CharT>
+void test() {
+  test(STR("\x00"), STR("}"), '\x00');
+  test(STR("a"), STR("}"), 'a');
+  test(STR("\x80"), STR("}"), '\x80');
+  test(STR("\xff"), STR("}"), '\xff');
+
+  test(STR("\x00"), STR("c}"), '\x00');
+  test(STR("a"), STR("c}"), 'a');
+  test(STR("\x80"), STR("c}"), '\x80');
+  test(STR("\xff"), STR("c}"), '\xff');
+
+#if TEST_STD_VER > 20
+  test(STR(R"('\u{0}')"), STR("?}"), '\x00');
+  test(STR("'a'"), STR("?}"), 'a');
+  if constexpr (std::same_as<CharT, char>) {
+    test(STR(R"('\x{80}')"), STR("?}"), '\x80');
+    test(STR(R"('\x{ff}')"), STR("?}"), '\xff');
+  }
+#  ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  else {
+    test(STR(R"('\u{80}')"), STR("?}"), '\x80');
+    test(STR("'\u00ff'"), STR("?}"), '\xff');
+  }
+#  endif // TEST_HAS_NO_WIDE_CHARACTERS
+#endif   // TEST_STD_VER > 20
+
+  test(STR("10000000"), STR("b}"), char(-128));
----------------
mordante wrote:

@ldionne These values are different, for the unsigned test I use non-negative values.

https://github.com/llvm/llvm-project/pull/73396


More information about the libcxx-commits mailing list