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.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * pt.c (type_unification_real): Accept a dependent result in
        template context.
---
 gcc/cp/pt.c                                |  9 ++++++++-
 gcc/testsuite/g++.dg/cpp0x/fntmpdefarg11.C | 15 +++++++++++++++
 gcc/cp/ChangeLog                           |  6 ++++++
 3 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/fntmpdefarg11.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0acc16d1b92..6c15419e9cc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg11.C 
b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg11.C
new file mode 100644
index 00000000000..86c8ea93f4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg11.C
@@ -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);
+}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2157496745e..09fb3f2935c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-03-20  Jason Merrill  <ja...@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  <mse...@redhat.com>
 
        PR tree-optimization/89688

base-commit: fcf9e045198f89f01e8a2e57724a8e6cc4d04cda
-- 
2.20.1

Reply via email to