/* Temporarily reduce by one the number of levels in the ARGLIST
so as to avoid comparing the last set of arguments. */
TREE_VEC_LENGTH (arglist)--;
- found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
+ /* We don't use COMPLAIN in the following call because this isn't
+ the immediate context of deduction. For instance, tf_partial
+ could be set here as we might be at the beginning of template
+ argument deduction when any explicitly specified template
+ arguments are substituted into the function type. tf_partial
+ could lead into trouble because we wouldn't find the partial
+ instantiation that might have been created outside tf_partial
+ context, because the levels of template parameters wouldn't
+ match, because in a tf_partial context, tsubst doesn't reduce
+ TEMPLATE_PARM_LEVEL. */
+ found = tsubst (gen_tmpl, arglist, tf_none, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
/* FOUND is either a proper class type, or an alias
template specialization. In the later case, it's a
--- /dev/null
+// PR c++/95888
+// { dg-do compile { target c++17 } }
+
+template <typename T> class A {
+ A(int, int);
+ template <typename> friend class A;
+ friend T;
+};
+
+template<typename U> struct B {
+ template<auto V> struct C {
+ A<B> begin() { return {1, 0}; }
+ };
+ template<auto Z, int *P = nullptr>
+ C<Z> fn();
+};
+
+int
+main ()
+{
+ B<int> b;
+ b.fn<1>().begin();
+}
--- /dev/null
+// PR c++/95888
+// { dg-do compile { target c++11 } }
+
+template <typename T> class A {
+ A(int, int);
+ template <typename> friend class A;
+ friend T;
+};
+
+template<typename U> struct B {
+ template<typename V> struct C {
+ A<B> begin() { return {1, 0}; }
+ };
+ template<typename Z, int *P = nullptr>
+ C<Z> fn();
+};
+
+int
+main ()
+{
+ B<int> b;
+ b.fn<int>().begin();
+}