This restores limited support debug (esaped) output for string when literal
encoding is non-unicode, by allowing strings that contains only printable
ASCII characters and standard defined escapes (expanded with nul (\0)).
This covers common use-cases, while still preserving flexibility to provide
proper handling for escaping of encodingspecific characters.
libstdc++-v3/ChangeLog:
* include/std/format (__format::__write_escaped_ascii): Mark as
_GLIBCXX_CONSTEXPR_FORMAT and reject at compile time string
containing charcters other than printable ASCII and standard
escapes.
* testsuite/std/format/debug.cc: Test basic_escapes and \0
at compile-time.
* testsuite/std/format/debug_nonunicode_neg.cc: New test.
---
Sending v2 that addresses handling program using non-unicode literal
encoding linking with libstdc++. I am starting to lean more into
this solution, in combination with accepting later format-string
additions as extension being better direction.
Tested on x86_64-linux. OK for trunk?
libstdc++-v3/include/std/format | 22 ++++++++++++++++++-
libstdc++-v3/testsuite/std/format/debug.cc | 18 +++++++++++++--
.../std/format/debug_nonunicode_neg.cc | 18 +++++++++++++++
3 files changed, 55 insertions(+), 3 deletions(-)
create mode 100644 libstdc++-v3/testsuite/std/format/debug_nonunicode_neg.cc
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index fe0f611b833..b75aaa6df51 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1116,12 +1116,32 @@ namespace __format
}
template<typename _CharT, typename _Out>
- _Out
+ _GLIBCXX_CONSTEXPR_FORMAT _Out
__write_escaped_ascii(_Out __out,
basic_string_view<_CharT> __str,
_Term_char __term)
{
using _Str_view = basic_string_view<_CharT>;
+ if consteval {
+ // As set of the escaped characters depends on the encoding, for
+ // compile time allow only printable ASCII and standard escapes.
+ constexpr _Str_view __supported(_GLIBCXX_WIDEN(
+ "ABCDEFGHIJKLMNOPQRSTUWXYZ"
+ "abdeefghijklmnopqrstuwzyz"
+ " !#$%&'()*+-./:;<=>?[]^_{|}~"
+ "0123456789" "\t\n\r\\\"\'\0"
+ ), 95);
+ if (__str.find_first_not_of(__supported) != _Str_view::npos)
+#if __has_builtin(__builtin_constexpr_diag)
+ __builtin_constexpr_diag (2, "",
+ "debug ouput for non-unicode literal
encoding "
+ "supports only printable ASCII characters
and "
+ "standard escapes at compile time");
+#else
+ __asm__("");
+#endif
+ }
+
auto __first = __str.begin();
auto const __last = __str.end();
while (__first != __last)
diff --git a/libstdc++-v3/testsuite/std/format/debug.cc
b/libstdc++-v3/testsuite/std/format/debug.cc
index 01bb9074ba7..959822b2182 100644
--- a/libstdc++-v3/testsuite/std/format/debug.cc
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -75,6 +75,13 @@ test_basic_escapes()
VERIFY( res == WIDEN(R"("'")") );
res = fdebug(apos[0]);
VERIFY( res == WIDEN(R"('\'')") );
+
+ // This is not standard escape, but still supported at compile time.
+ const std::basic_string<CharT> null(WIDEN("\0"), 1);
+ res = fdebug(null);
+ VERIFY( res == WIDEN(R"("\u{0}")") );
+ res = fdebug(null[0]);
+ VERIFY( res == WIDEN(R"('\u{0}')") );
}
template<typename CharT>
@@ -831,6 +838,14 @@ test_all()
{
test_basic_escapes<char>();
test_basic_escapes<wchar_t>();
+
+#ifndef UNICODE_ENC
+ // For non-unicode literal encoding debug output only supports
+ // printable ASCII and standard escapes at compile time
+ if (std::is_constant_evaluated())
+ return true;
+#endif
+
test_ascii_escapes<char>();
test_ascii_escapes<wchar_t>();
test_extended_ascii<char>();
@@ -857,8 +872,7 @@ test_all()
return true;
}
-#if defined(__glibcxx_constexpr_format) && defined(UNICODE_ENC)
-// Deboug ouput is supported only for unicode literal encoding
+#ifdef __glibcxx_constexpr_format
static_assert(test_all());
#endif
diff --git a/libstdc++-v3/testsuite/std/format/debug_nonunicode_neg.cc
b/libstdc++-v3/testsuite/std/format/debug_nonunicode_neg.cc
new file mode 100644
index 00000000000..1d7b8743f31
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/debug_nonunicode_neg.cc
@@ -0,0 +1,18 @@
+// { dg-options "-fexec-charset=ISO8859-1" }
+// { dg-do compile { target c++26 } }
+// { dg-require-effective-target cxx11_abi }
+
+#include <format>
+
+constexpr bool
+test_format(std::string_view str)
+{
+ (void)std::format("{:?}", str);
+ return true;
+}
+
+static_assert(test_format("\x10")); // { dg-error "in 'constexpr' expansion
of" }
+static_assert(test_format("Åëÿ")); // { dg-error "in 'constexpr' expansion of"
}
+
+// { dg-prune-output "debug ouput for non-unicode literal encoding supports
only" }
+
--
2.54.0