diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-03-08 11:58:49 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-03-12 10:06:57 +0000 |
commit | a21847acb8bb1101c15deef1b55d929e65c9ada4 (patch) | |
tree | 49c1bca60dca44eecf00366d19b886f2f0032452 | |
parent | bb83e83cada180cce650539ab6042aa57fed1caf (diff) | |
download | gcc-a21847acb8bb1101c15deef1b55d929e65c9ada4.zip gcc-a21847acb8bb1101c15deef1b55d929e65c9ada4.tar.gz gcc-a21847acb8bb1101c15deef1b55d929e65c9ada4.tar.bz2 |
libstdc++: Reject basic_format_parse_context::check_dynamic_spec<>(n)
LWG 4142 (approved in Wrocław, November 2024) made it ill-formed to call
basic_format_parse_context::check_dynamic_spec with an empty template
argument list.
This adds a static_assert to enforce that, and adjusts the tests.
libstdc++-v3/ChangeLog:
* include/std/format
(basic_format_parse_context::check_dynamic_spec): Require a
non-empty parameter pack, as per LWG 4142.
* testsuite/std/format/parse_ctx.cc: Remove call of
check_dynamic_spec with empty template argument list.
* testsuite/std/format/parse_ctx_neg.cc: Add dg-error to call of
check_dynamic_spec with empty template argument list.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r-- | libstdc++-v3/include/std/format | 3 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/format/parse_ctx.cc | 1 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/format/parse_ctx_neg.cc | 8 |
3 files changed, 9 insertions, 3 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index e7e0d2d..0d6cc7f 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -4338,6 +4338,9 @@ namespace __format constexpr void basic_format_parse_context<_CharT>::check_dynamic_spec(size_t __id) noexcept { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4142. check_dynamic_spec should require at least one type + static_assert(sizeof...(_Ts) >= 1); // This call enforces the Mandates: condition that _Ts contains valid // types and each type appears at most once. It could be a static_assert // but this way failures give better diagnostics, due to calling the diff --git a/libstdc++-v3/testsuite/std/format/parse_ctx.cc b/libstdc++-v3/testsuite/std/format/parse_ctx.cc index 88ffd77..b5dd7cd 100644 --- a/libstdc++-v3/testsuite/std/format/parse_ctx.cc +++ b/libstdc++-v3/testsuite/std/format/parse_ctx.cc @@ -491,7 +491,6 @@ test_dynamic_type_check() std::format_parse_context pc("{1}.{2}"); // None of these calls should do anything at runtime, only during consteval: - pc.check_dynamic_spec<>(0); pc.check_dynamic_spec<int, const char*>(0); pc.check_dynamic_spec_integral(0); pc.check_dynamic_spec_string(0); diff --git a/libstdc++-v3/testsuite/std/format/parse_ctx_neg.cc b/libstdc++-v3/testsuite/std/format/parse_ctx_neg.cc index f19107c..d83fd8c 100644 --- a/libstdc++-v3/testsuite/std/format/parse_ctx_neg.cc +++ b/libstdc++-v3/testsuite/std/format/parse_ctx_neg.cc @@ -12,8 +12,9 @@ test_invalid() pc.check_dynamic_spec<bool, char, int, unsigned, long long, unsigned long long, float, double, long double, const char*, std::string_view, const void*>(0); - // For some reason, an empty pack of types is valid: - pc.check_dynamic_spec<>(0); + + // LWG 4142. check_dynamic_spec should require at least one type + pc.check_dynamic_spec<>(0); // { dg-error "here" } pc.check_dynamic_spec<void>(0); // { dg-error "here" } // const void* is allowed, but void* is not @@ -25,6 +26,7 @@ test_invalid() pc.check_dynamic_spec<char8_t>(0); // { dg-error "here" } // std::string_view is allowed, but std::string is not pc.check_dynamic_spec<std::string>(0); // { dg-error "here" } + // The types in the pack must be unique. pc.check_dynamic_spec<int, bool, int>(0); // { dg-error "here" } std::wformat_parse_context wpc(L""); @@ -38,3 +40,5 @@ test_invalid() // Each failure above will point to a call to this non-constexpr function: // { dg-error "__invalid_dynamic_spec" "" { target *-*-* } 0 } +// Except the check_dynamic_spec<>(0) one for LWG 4142 which matches this: +// { dg-error "static assertion failed" "" { target *-*-* } 0 } |