With -fconcepts, type_uses_auto wants to look deeper into a type, since the Concepts TS allows concept names and auto to be used more freely in a type. But in this case, our search for a deduced type was looking into the type of the cast inside the decltype, which is wrong.
It turned out that for_each_template_parm_r didn't handle DECLTYPE_TYPE at all, and then cp_walk_subtrees walked into its operand. Fixed by clearing *walk_subtrees whether or not we explicitly walk the operand. We also don't want to look at non-deduced contexts when considering whether a type needs deducing. Tested x86_64-pc-linux-gnu, applying to trunk and 8.
commit 716725435749074db5f5e7ef70b8950331e8315d Author: Jason Merrill <ja...@redhat.com> Date: Tue May 8 17:39:10 2018 -0400 PR c++/85706 - class deduction under decltype * pt.c (for_each_template_parm_r): Handle DECLTYPE_TYPE. Clear *walk_subtrees whether or not we walked into the operand. (type_uses_auto): Only look at deduced contexts. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c604f46f742..180dfd6861c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -9829,6 +9829,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) break; case TYPEOF_TYPE: + case DECLTYPE_TYPE: case UNDERLYING_TYPE: if (pfd->include_nondeduced_p && for_each_template_parm (TYPE_VALUES_RAW (t), fn, data, @@ -9836,6 +9837,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) pfd->include_nondeduced_p, pfd->any_fn)) return error_mark_node; + *walk_subtrees = false; break; case FUNCTION_DECL: @@ -26862,7 +26864,7 @@ type_uses_auto (tree type) them. */ if (uses_template_parms (type)) return for_each_template_parm (type, is_auto_r, /*data*/NULL, - /*visited*/NULL, /*nondeduced*/true); + /*visited*/NULL, /*nondeduced*/false); else return NULL_TREE; } diff --git a/gcc/testsuite/g++.dg/concepts/class-deduction2.C b/gcc/testsuite/g++.dg/concepts/class-deduction2.C new file mode 100644 index 00000000000..286e59a5039 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/class-deduction2.C @@ -0,0 +1,9 @@ +// PR c++/85706 +// { dg-additional-options "-std=c++17 -fconcepts" } + +template<class T> struct S { + S(T); +}; + +template<class = void> +auto f() -> decltype(S(42)); // error