c++: Fix return type deduction during satisfaction

During satisfaction that's entered through the three-parameter version
of satisfy_declaration_constraints, current_function_decl gets set to
the dependent DECL_TEMPLATE_RESULT for sake of access checking.  This
makes the predicate in_template_function return true during satisfaction
from this entrypoint, which in turn makes calls to mark_used exit early
before it does its full processing.  This leads to us accepting the
invalid testcase below due to mark_used never attempting to deduce the
return type of A::foo() and detecting failure thereof.

It seems wrong for in_template_function to be true during instantiation
or during satisfaction, so this patch makes in_template_function inspect
the less volatile cfun->decl instead of current_function_decl.

gcc/cp/ChangeLog:

	* pt.c (in_template_function): Inspect cfun->decl instead of
	current_function_decl.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-requires23.C: New test.
This commit is contained in:
Patrick Palka 2020-12-15 12:10:26 -05:00
parent 30c41abc41
commit 35317db051
2 changed files with 13 additions and 2 deletions

View file

@ -10805,14 +10805,16 @@ uses_template_parms (tree t)
return dependent_p;
}
/* Returns true iff current_function_decl is an incompletely instantiated
/* Returns true iff we're processing an incompletely instantiated function
template. Useful instead of processing_template_decl because the latter
is set to 0 during instantiate_non_dependent_expr. */
bool
in_template_function (void)
{
tree fn = current_function_decl;
/* Inspect the less volatile cfun->decl instead of current_function_decl;
the latter might get set for e.g. access checking during satisfaction. */
tree fn = cfun ? cfun->decl : NULL_TREE;
bool ret;
++processing_template_decl;
ret = (fn && DECL_LANG_SPECIFIC (fn)

View file

@ -0,0 +1,9 @@
// { dg-do compile { target c++20 } }
// Verify f<A>'s associated constraints evaluate to false due
// to return type deduction failure for A::foo().
template <class T> concept fooable = requires { T::foo(0); };
template <fooable T> int f ();
struct A { static auto *foo(auto); };
int a = f<A>(); // { dg-error "no match" }