From: Jakub Jelinek Date: Wed, 19 Nov 2025 10:02:13 +0000 (+0100) Subject: c++, libstdc++: Implement CWG1670 and LWG4468 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d000da53203c9f17b29dd9328d12dfcbe8d03aa;p=thirdparty%2Fgcc.git c++, libstdc++: Implement CWG1670 and LWG4468 The following patch attempts to implement CWG1670 and related LWG4468. 2025-11-19 Jakub Jelinek 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 --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 06cba31ada6..dc26b10f39b 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 % in conversion operator"); return error_mark_node; } - else if (template_parm_scope_p ()) - warning (0, "use of % in member template " - "conversion operator can never be deduced"); + else + { + pedwarn (input_location, OPT_Wpedantic, + "invalid use of % in conversion operator"); + if (template_parm_scope_p ()) + warning (0, "use of % 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 00000000000..1c8430a6558 --- /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 00000000000..570a04ad796 --- /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 00000000000..9d138757229 --- /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 a3a6caf0a66..2f4de051b01 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 98885799de9..1ee1755bd00 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 struct A { diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn13.C index 96b4b0c64aa..bb4f3ca94ee 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 diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C index b16a7644c0f..68d8d853b3c 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 e35215d64c7..4439f47abf5 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 a2c7e40755b..8a9010521ad 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 def05f5fb25..58f9a311351 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 diff --git a/gcc/testsuite/g++.dg/modules/auto-1_a.H b/gcc/testsuite/g++.dg/modules/auto-1_a.H index 4d3bc77dbb1..e9cbd00aceb 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 96350662fed..f6422339ae5 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 d28b077398b..5c09fac8662 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -4682,7 +4682,7 @@ template } constexpr - operator decltype(auto)() const noexcept + operator decltype(value)() const noexcept { return value; } };