During function template argument deduction, when we encounter a non-template parameter with a type that depends on other parameters, we want to check whether substituting in the arguments we already have causes a substitution failure. Since we might not have all the arguments yet, we need to do this with processing_template_decl set. tsubst_copy_and_build wasn't dealing well with a call to a .* expression in that context; outside of a template, that shows up as an OFFSET_REF, but within a template it's DOTSTAR_EXPR.
Tested x86_64-pc-linux-gnu, applying to trunk and 8.
commit 7704d0c55fb91ff619ff5487fec643490608d8d7 Author: Jason Merrill <ja...@redhat.com> Date: Tue May 22 15:32:27 2018 -0400 PR c++/85866 - error with .* in default template arg. * pt.c (tsubst_copy_and_build): Handle partial instantiation. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 81de633b1ee..0b04770e123 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18433,7 +18433,9 @@ tsubst_copy_and_build (tree t, /* Unsupported internal function with arguments. */ gcc_unreachable (); } - else if (TREE_CODE (function) == OFFSET_REF) + else if (TREE_CODE (function) == OFFSET_REF + || TREE_CODE (function) == DOTSTAR_EXPR + || TREE_CODE (function) == MEMBER_REF) ret = build_offset_ref_call_from_tree (function, &call_args, complain); else if (TREE_CODE (function) == COMPONENT_REF) diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg9.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg9.C new file mode 100644 index 00000000000..833049c6de3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg9.C @@ -0,0 +1,29 @@ +// PR c++/85866 +// { dg-do compile { target c++11 } } + +template<typename _Tp, typename _Up = _Tp&&> +_Up +__declval(int); + +template<typename _Tp> +_Tp +__declval(long); + +template<typename _Tp> +auto declval() noexcept -> decltype(__declval<_Tp>(0)); + +template<typename...> +using void_t = void; + +template<typename U, typename V, + void_t<decltype ( (declval<U>().*declval<V>()) () ) + >* = nullptr> +void boom(){} + +struct Foo { + void bar(){} +}; + +int main() { + boom<Foo, decltype(&Foo::bar)>(); +}