Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/16?
-- >8 --
In r16-5967-gbae0ed69e1862a we removed the mark_used logic from
resolve_nondeduced_context under the rationale that it should be the
callers' responsiblity to mark it. Resolving a template-id overload
shouldn't constitute an ODR-used on its own, and callers would have to
call mark_used anyway to uniformaly handle all overloads, including
non-template-id ones.
Removing this logic 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.
We could adjust callers to call mark_used before inspecting TREE_TYPE,
but I think it's reasonable to expect that the (successful) result of
resolve_nondeduced_context always has a resolved function type. To
that end this patch restores the mark_used call, but ensures it's
always done in an unevaluated context and quietly so that its only
effect is to resolve the function type. (Note we do this same technique
in the Reflection implementation, see resolve_type_of_reflected_decl).
PR c++/126406
PR c++/119343
gcc/cp/ChangeLog:
* pt.cc (resolve_nondeduced_context): Restore mark_used call
but always do it quietly and in an unevaluated context.
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.
---
gcc/cp/pt.cc | 5 +++++
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, 44 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/cond2a.C
create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn67.C
create mode 100644 gcc/testsuite/g++.dg/cpp1z/noexcept-type29.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6a081b838e06..3605c2ea8b93 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25653,6 +25653,11 @@ resolve_nondeduced_context (tree orig_expr,
tsubst_flags_t complain)
}
if (good == 1)
{
+ /* Ensure the selected function's type is fully resolved. */
+ ++cp_unevaluated_operand;
+ mark_used (goodfn, tf_none);
+ --cp_unevaluated_operand;
+
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..20ff86459c3d
--- /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..c620b180fc83
--- /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);
--
2.55.0.424.g13c7afec21