PR c++/87480 - decltype of member access in default template arg

The issue here is that declval<T>().d is considered instantiation-dependent
within a template, as the access to 'd' might depend on the particular
specialization.  But when we're deducing template arguments for a call, we
know that the call and the arguments are non-dependent, so we can do the
substitution as though we aren't in a template.  Which strictly speaking we
aren't, since the default argument is considered a separate definition.

	* pt.c (type_unification_real): Accept a dependent result in
	template context.

From-SVN: r269826
This commit is contained in:
Jason Merrill 2019-03-20 16:31:40 -04:00 committed by Jason Merrill
parent 3ad7fed1cc
commit 292a8bbb27
3 changed files with 29 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2019-03-20 Jason Merrill <jason@redhat.com>
PR c++/87480 - decltype of member access in default template arg
* pt.c (type_unification_real): Accept a dependent result in
template context.
2019-03-19 Martin Sebor <msebor@redhat.com>
PR tree-optimization/89688

View File

@ -21005,8 +21005,15 @@ type_unification_real (tree tparms,
}
else
{
/* Even if the call is happening in template context, getting
here means it's non-dependent, and a default argument is
considered a separate definition under [temp.decls], so we can
do this substitution without processing_template_decl. This
is important if the default argument contains something that
might be instantiation-dependent like access (87480). */
processing_template_decl_sentinel s;
tree substed = NULL_TREE;
if (saw_undeduced == 1 && processing_template_decl == 0)
if (saw_undeduced == 1)
{
/* First instatiate in template context, in case we still
depend on undeduced template parameters. */

View File

@ -0,0 +1,15 @@
// PR c++/87480
// { dg-do compile { target c++11 } }
template<typename T> T&& declval();
template <typename T, typename = decltype(declval<T>().d)> void f(T) { }
struct A {
double d;
};
template <typename>
void j(A& a) {
f(a);
}