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

Reply via email to