https://gcc.gnu.org/g:9b7b6a4075cccfb7480a3a642ccdcb183625a2af
commit r16-7061-g9b7b6a4075cccfb7480a3a642ccdcb183625a2af Author: Jakub Jelinek <[email protected]> Date: Tue Jan 27 10:24:49 2026 +0100 c++: Implement CWG3153 - Immediate-escalating defaulted comparison The following patch implements the https://cplusplus.github.io/CWG/issues/3153.html core issue proposal. 2026-01-27 Jakub Jelinek <[email protected]> * cp-gimplify.cc (immediate_escalating_function_p): Implement CWG3153 - Immediate-escalating defaulted comparison. Don't check special_memfn_p for sfk_none for DECL_DEFAULTED_FNs. * decl.cc (grokfndecl): Similarly for initialized == SD_DEFAULTED fns. * g++.dg/reflect/cwg3153.C: New test. Diff: --- gcc/cp/cp-gimplify.cc | 5 ++-- gcc/cp/decl.cc | 8 +++--- gcc/testsuite/g++.dg/reflect/cwg3153.C | 51 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 30d6a07e376d..59e01c103fd4 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -502,10 +502,9 @@ immediate_escalating_function_p (tree fn) specifier */ if (LAMBDA_FUNCTION_P (fn)) return true; - /* -- a defaulted special member function that is not declared with the + /* -- a defaulted function that is not declared with the consteval specifier */ - special_function_kind sfk = special_memfn_p (fn); - if (sfk != sfk_none && DECL_DEFAULTED_FN (fn)) + if (DECL_DEFAULTED_FN (fn)) return true; /* -- a function that results from the instantiation of a templated entity defined with the constexpr specifier. */ diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 3bbc28c913d8..40a95eb15288 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -12679,10 +12679,10 @@ grokfndecl (tree ctype, if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl)) return NULL_TREE; - /* Don't call check_consteval_only_fn for defaulted special member - functions. Those are immediate-escalating functions but at this point - DECL_DEFAULTED_P has not been set. */ - if (initialized != SD_DEFAULTED || special_memfn_p (decl) == sfk_none) + /* Don't call check_consteval_only_fn for defaulted functions. Those are + immediate-escalating functions but at this point DECL_DEFAULTED_P has + not been set. */ + if (initialized != SD_DEFAULTED) check_consteval_only_fn (decl); if (ctype == NULL_TREE || check) diff --git a/gcc/testsuite/g++.dg/reflect/cwg3153.C b/gcc/testsuite/g++.dg/reflect/cwg3153.C new file mode 100644 index 000000000000..5f2b1fd665ff --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/cwg3153.C @@ -0,0 +1,51 @@ +// CWG3153 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include <compare> + +struct A { + decltype (^^::) a = ^^::; + consteval A () {} + bool operator== (const A &) const = default; // { dg-bogus "function of consteval-only type must be declared 'consteval'" } +}; + +template <typename T, T V> +struct B +{ + T b = V; + consteval B () {} + bool operator== (const B &) const = default; +}; + +struct C { + decltype (^^::) c= ^^::; + int d = 0; + consteval C () {} + consteval bool operator== (const C &x) const { return d == x.d; } + consteval auto operator<=> (const C &x) const { return d <=> x.d; } +}; + +struct D : public C { + int e = 0; + consteval D () {} + auto operator<=> (const D &) const = default; +}; + +consteval +{ + A a; + A b; + if (a != b) throw 1; + B <decltype (^^::), ^^::> c; + B <decltype (^^::), ^^::> d; + if (c != d) throw 2; + D e; + D f; + if (e != f) throw 3; + f.d = 2; + if (e >= f) throw 4; + f.d = 0; + f.e = -1; + if (e <= f) throw 5; +}
