https://gcc.gnu.org/g:3d000da53203c9f17b29dd9328d12dfcbe8d03aa
commit r16-5412-g3d000da53203c9f17b29dd9328d12dfcbe8d03aa Author: Jakub Jelinek <[email protected]> Date: Wed Nov 19 11:02:13 2025 +0100 c++, libstdc++: Implement CWG1670 and LWG4468 The following patch attempts to implement CWG1670 and related LWG4468. 2025-11-19 Jakub Jelinek <[email protected]> gcc/cp/ * parser.cc (cp_parser_conversion_type_id): Implement C++ DR1670 - auto as conversion-type-id. Pedwarn on conversion operators with placeholder return type. gcc/testsuite/ * g++.dg/DRs/dr1670-1.C: New test. * g++.dg/DRs/dr1670-2.C: New test. * g++.dg/DRs/dr1670-3.C: New test. * g++.dg/modules/auto-1_a.H: Use dg-options instead of dg-additional-options. * g++.dg/modules/auto-1_b.C: Likewise. * g++.dg/cpp1y/auto-fn12.C: Likewise. * g++.dg/cpp1y/auto-fn13.C: Add empty dg-options. * g++.dg/cpp1y/auto-fn22.C: Likewise. * g++.dg/cpp1y/constexpr-assert2.C: Likewise. * g++.dg/cpp1y/auto-fn44.C: Add dg-options -Wpedantic and expect further warnings. * g++.dg/cpp1y/auto-fn50.C: Likewise. * g++.dg/cpp0x/auto9.C: Expect two errors always rather than just for C++11. libstdc++-v3/ * include/std/type_traits (constant_wrapper conversion operator): Use decltype(value) instead of decltype(auto). Resolves LWG4468. Diff: --- gcc/cp/parser.cc | 11 ++++++++--- gcc/testsuite/g++.dg/DRs/dr1670-1.C | 9 +++++++++ gcc/testsuite/g++.dg/DRs/dr1670-2.C | 10 ++++++++++ gcc/testsuite/g++.dg/DRs/dr1670-3.C | 10 ++++++++++ gcc/testsuite/g++.dg/cpp0x/auto9.C | 4 ++-- gcc/testsuite/g++.dg/cpp1y/auto-fn12.C | 2 +- gcc/testsuite/g++.dg/cpp1y/auto-fn13.C | 1 + gcc/testsuite/g++.dg/cpp1y/auto-fn22.C | 1 + gcc/testsuite/g++.dg/cpp1y/auto-fn44.C | 5 +++-- gcc/testsuite/g++.dg/cpp1y/auto-fn50.C | 3 ++- gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C | 1 + gcc/testsuite/g++.dg/modules/auto-1_a.H | 2 +- gcc/testsuite/g++.dg/modules/auto-1_b.C | 2 +- libstdc++-v3/include/std/type_traits | 2 +- 14 files changed, 51 insertions(+), 12 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 06cba31ada67..dc26b10f39b9 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -18779,9 +18779,14 @@ cp_parser_conversion_type_id (cp_parser* parser) error ("invalid use of %<auto%> in conversion operator"); return error_mark_node; } - else if (template_parm_scope_p ()) - warning (0, "use of %<auto%> in member template " - "conversion operator can never be deduced"); + else + { + pedwarn (input_location, OPT_Wpedantic, + "invalid use of %<auto%> in conversion operator"); + if (template_parm_scope_p ()) + warning (0, "use of %<auto%> in member template " + "conversion operator can never be deduced"); + } } return type_specified; diff --git a/gcc/testsuite/g++.dg/DRs/dr1670-1.C b/gcc/testsuite/g++.dg/DRs/dr1670-1.C new file mode 100644 index 000000000000..1c8430a6558b --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr1670-1.C @@ -0,0 +1,9 @@ +// DR 1670 - auto as conversion-type-id +// { dg-do compile { target c++14 } } + +struct S { + operator auto () { return 0; } // { dg-error "invalid use of 'auto' in conversion operator" } +}; +struct T { + operator decltype (auto) () { return 0; } // { dg-error "invalid use of 'auto' in conversion operator" } +}; diff --git a/gcc/testsuite/g++.dg/DRs/dr1670-2.C b/gcc/testsuite/g++.dg/DRs/dr1670-2.C new file mode 100644 index 000000000000..570a04ad796d --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr1670-2.C @@ -0,0 +1,10 @@ +// DR 1670 - auto as conversion-type-id +// { dg-do compile { target c++14 } } +// { dg-options "-Wpedantic" } + +struct S { + operator auto () { return 0; } // { dg-warning "invalid use of 'auto' in conversion operator" } +}; +struct T { + operator decltype (auto) () { return 0; } // { dg-warning "invalid use of 'auto' in conversion operator" } +}; diff --git a/gcc/testsuite/g++.dg/DRs/dr1670-3.C b/gcc/testsuite/g++.dg/DRs/dr1670-3.C new file mode 100644 index 000000000000..9d1387572298 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr1670-3.C @@ -0,0 +1,10 @@ +// DR 1670 - auto as conversion-type-id +// { dg-do compile { target c++14 } } +// { dg-options "" } + +struct S { + operator auto () { return 0; } +}; +struct T { + operator decltype (auto) () { return 0; } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C index a3a6caf0a66f..2f4de051b012 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto9.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C @@ -15,8 +15,8 @@ const std::type_info &t2 = typeid (auto *); // { dg-error "auto" } struct A { - operator auto (); // { dg-error "auto" "" { target { ! c++14 } } } - operator auto *(); // { dg-error "auto" "" { target { ! c++14 } } } + operator auto (); // { dg-error "auto" } + operator auto *(); // { dg-error "auto" } }; struct A2 diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C index 98885799de98..1ee1755bd005 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C @@ -1,6 +1,6 @@ // { dg-do compile { target c++14 } } // { dg-final { scan-assembler "_ZN1AIiEcvDaEv" } } -// { dg-additional-options -fno-implicit-constexpr } +// { dg-options -fno-implicit-constexpr } template <class T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C index 96b4b0c64aad..bb4f3ca94ee9 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +// { dg-options "" } struct A { template <class T> diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C index b16a7644c0f8..68d8d853b3c3 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +// { dg-options "" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn44.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn44.C index e35215d64c7e..4439f47abf54 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn44.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn44.C @@ -1,11 +1,12 @@ // PR c++/79474 // { dg-do compile { target c++14 } } +// { dg-options "-Wpedantic" } struct Funject { - operator auto() { return +[](bool b) {return b;}; } + operator auto() { return +[](bool b) {return b;}; } // { dg-warning "invalid use of 'auto' in conversion operator" } operator auto() { return +[](bool b, bool, bool) {return b;}; } // { dg-error "cannot be overloaded" } -}; +}; // { dg-warning "invalid use of 'auto' in conversion operator" "" { target *-*-* } .-1 } Funject fun; auto bbb = fun(true); diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C index a2c7e40755b0..8a9010521ad8 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C @@ -1,10 +1,11 @@ // PR c++/84906 // { dg-do compile { target c++14 } } +// { dg-options "-Wpedantic" } extern "C" int puts(const char*); struct aa { - operator auto() { + operator auto() { // { dg-warning "invalid use of 'auto' in conversion operator" } puts("auto"); return false; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C index def05f5fb256..58f9a3113510 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C @@ -1,6 +1,7 @@ // PR c++/65985 // { dg-do compile { target c++14 } } // { dg-skip-if "requires hosted libstdc++ for cassert" { ! hostedlib } } +// { dg-options "" } #include <cassert> diff --git a/gcc/testsuite/g++.dg/modules/auto-1_a.H b/gcc/testsuite/g++.dg/modules/auto-1_a.H index 4d3bc77dbb1d..e9cbd00aceb7 100644 --- a/gcc/testsuite/g++.dg/modules/auto-1_a.H +++ b/gcc/testsuite/g++.dg/modules/auto-1_a.H @@ -1,4 +1,4 @@ -// { dg-additional-options -fmodule-header } +// { dg-options -fmodule-header } // { dg-module-cmi {} } #include "auto-1.h" diff --git a/gcc/testsuite/g++.dg/modules/auto-1_b.C b/gcc/testsuite/g++.dg/modules/auto-1_b.C index 96350662fed4..f6422339ae56 100644 --- a/gcc/testsuite/g++.dg/modules/auto-1_b.C +++ b/gcc/testsuite/g++.dg/modules/auto-1_b.C @@ -1,4 +1,4 @@ -// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" } +// { dg-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" } #include "auto-1.h" import "auto-1_a.H"; diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index d28b077398be..5c09fac86629 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -4682,7 +4682,7 @@ template<typename _Ret, typename _Fn, typename... _Args> } constexpr - operator decltype(auto)() const noexcept + operator decltype(value)() const noexcept { return value; } };
