[gcc r16-9470] c++: resolvedness of resolve_nondeduced_context result [PR126406]

Patrick Palka via Gcc-cvs <[email protected]> Fri, 31 Jul 2026 02:40:43 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8491b800473971ba1c03e74866273cb8dcaa5edc

commit r16-9470-g8491b800473971ba1c03e74866273cb8dcaa5edc
Author: Patrick Palka <[email protected]>
Date:   Thu Jul 30 21:18:38 2026 -0400

    c++: resolvedness of resolve_nondeduced_context result [PR126406]
    
    In r16-5967-gbae0ed69e1862a we removed the mark_used call from
    resolve_nondeduced_context under the rationale that it should be
    the caller's responsiblity to mark_used.
    
    Removing the call however now means that resolve_nondeduced_context
    could return a specialization whose type is not yet fully resolved
    (i.e. has an uninstantiated noexcept or undeduced return type), and
    callers that immediately inspect TREE_TYPE of the result (such as
    standard_conversion and build_conditional_expr) now misbehave.
    
    In light of such callers, this patch reverts r16-5967; it's not
    necessary to fix PR119343 because after r16-6276 convert_to_void
    now properly propagates an error_mark_node result from
    resolve_nondeduced_context.
    
            PR c++/126406
            PR c++/119343
    
    gcc/cp/ChangeLog:
    
            * pt.cc (resolve_nondeduced_context): Revert r16-5967 change.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/cond2a.C: New test.
            * g++.dg/cpp1y/auto-fn67.C: New test.
            * g++.dg/cpp1z/noexcept-type29.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>
    (cherry picked from commit e873aac49eb2b58ae18e05f4150826278bdbb3cb)

Diff:
---
 gcc/cp/pt.cc                                 |  2 ++
 gcc/testsuite/g++.dg/cpp0x/cond2a.C          | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/cpp1y/auto-fn67.C       | 11 +++++++++++
 gcc/testsuite/g++.dg/cpp1z/noexcept-type29.C | 11 +++++++++++
 4 files changed, 41 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 9d3a972e3002..dd578bef0bb3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25452,6 +25452,8 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
 	}
       if (good == 1)
 	{
+	  if (!mark_used (goodfn, complain) && !(complain & tf_error))
+	    return error_mark_node;
 	  expr = goodfn;
 	  if (baselink)
 	    expr = build_baselink (BASELINK_BINFO (baselink),
diff --git a/gcc/testsuite/g++.dg/cpp0x/cond2a.C b/gcc/testsuite/g++.dg/cpp0x/cond2a.C
new file mode 100644
index 000000000000..a42e198291b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/cond2a.C
@@ -0,0 +1,17 @@
+// PR c++/126406
+// { dg-do compile { target c++14 } }
+// A version of cond2.C where f has a deduced return type
+// and g is instantiated.
+
+bool b;
+
+template < class T > auto f ()
+{
+}
+
+template < class T > auto g () -> decltype (b ? f < int > : throw 0)
+{
+  return b ? f<int> : throw 0;
+}
+
+using type = decltype(g<int>());
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn67.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn67.C
new file mode 100644
index 000000000000..82d74441feec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn67.C
@@ -0,0 +1,11 @@
+// PR c++/126406
+// { dg-do compile { target c++14 } }
+
+template<class T> auto g(T) { }
+static_assert(g<int>, "");
+
+template<class T>
+struct B {
+  static auto g(T) { }
+};
+static_assert(B<int>::g, "");
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type29.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type29.C
new file mode 100644
index 000000000000..51bf87c85fa5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type29.C
@@ -0,0 +1,11 @@
+// PR c++/126406
+// { dg-do compile { target c++11 } }
+
+template<class T> void f(T) noexcept(noexcept(T())) { }
+static_assert(f<int>, "");
+
+template<class T>
+struct A {
+  static void f(T) noexcept(noexcept(T())) { }
+};
+static_assert(A<int>::f, "");