https://gcc.gnu.org/g:0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf

commit r15-9549-g0be3dff1aadcc3e879f3d1ffd45d842ab0e0c0bf
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Apr 16 11:44:46 2025 +0100

    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.

Diff:
---
 libstdc++-v3/include/std/format                             |  5 ++++-
 libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc | 13 +++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 2668382c7edb..f3fd837897bd 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 000000000000..bf8619d3d276
--- /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 }

Reply via email to