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; }
   };

Reply via email to