diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-04-16 11:44:46 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-04-17 10:11:49 +0100 |
commit | 0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf (patch) | |
tree | 1facd4082095571d34617162467309ab24248a18 | |
parent | 22fe83d6fc9f59311241c981bcad58b61e2056d4 (diff) | |
download | gcc-0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf.zip gcc-0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf.tar.gz gcc-0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf.tar.bz2 |
libstdc++: Do not use 'not' alternative token in <format>
This fixes:
FAIL: 17_intro/headers/c++1998/operator_names.cc -std=gnu++23 (test for excess errors)
FAIL: 17_intro/headers/c++1998/operator_names.cc -std=gnu++26 (test for excess errors)
The purpose of 'not defined<format_kind<R>>' is to be ill-formed (as
required by [format.range.fmtkind]) and to give an error that includes
the string "not defined<format_kind<R>>". That was intended to tell you
that format_kind<R> is not defined, just like it says!
But user code can use -fno-operator-names so we can't use 'not' here,
and "! defined" in the diagnostic doesn't seem as user-friendly. It also
raises questions about whether it was intended to be the preprocessor
token 'defined' (it's not) or where 'defined' is defined (it's not).
Replace it with __primary_template_not_defined<format_kind<R>> and a
comment, which seems to give a fairly clear diagnostic with both GCC and
Clang. The diagnostic now looks like:
.../include/c++/15.0.1/format:5165:7: error: use of 'std::format_kind<int>' before deduction of 'auto'
5165 | format_kind<_Rg> // you can specialize this for non-const input ranges
| ^~~~~~~~~~~~~~~~
.../include/c++/15.0.1/format:5164:35: error: '__primary_template_not_defined' was not declared in this scope
5164 | __primary_template_not_defined(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
5165 | format_kind<_Rg> // you can specialize this for non-const input ranges
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5166 | );
| ~
libstdc++-v3/ChangeLog:
* include/std/format (format_kind): Do not use 'not'
alternative token to make the primary template ill-formed. Use
the undeclared identifier __primary_template_not_defined and a
comment that will appear in diagnostics.
* testsuite/std/format/ranges/format_kind_neg.cc: New test.
-rw-r--r-- | libstdc++-v3/include/std/format | 5 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc | 13 |
2 files changed, 17 insertions, 1 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 2668382..f3fd837 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -5160,7 +5160,10 @@ namespace __format /// @cond undocumented template<typename _Rg> - constexpr auto format_kind = not defined(format_kind<_Rg>); + constexpr auto format_kind = + __primary_template_not_defined( + format_kind<_Rg> // you can specialize this for non-const input ranges + ); template<typename _Tp> consteval range_format diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc new file mode 100644 index 0000000..bf8619d --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc @@ -0,0 +1,13 @@ +// { dg-do compile { target c++23 } } + +// C++23 22.14.7.1 [format.range.fmtkind] p1: A program that instantiates +// the primary template of format_kind is ill-formed. + +#include <format> + +template<auto> struct Tester { }; + +Tester<std::format_kind<const int(&)[1]>> t; // { dg-error "here" } + +// { dg-error "use of 'std::format_kind" "" { target *-*-* } 0 } +// { dg-error "primary_template_not_defined" "" { target *-*-* } 0 } |