On Tue, Mar 11, 2025 at 10:14 PM Jonathan Wakely <jwak...@redhat.com> wrote:
> 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. > --- > > Tested x86_64-linux. > LGTM > > libstdc++-v3/include/std/format | 3 +++ > libstdc++-v3/testsuite/std/format/parse_ctx.cc | 1 - > 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 e7e0d2d142b..0d6cc7f6bef 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 88ffd77debe..b5dd7cdba78 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 f19107c886f..d83fd8c7a7b 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 } > -- > 2.48.1 > >