+2020-01-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/93400 - ICE with constrained friend.
+ * constraint.cc (maybe_substitute_reqs_for): New.
+ * decl.c (function_requirements_equivalent_p): Call it.
+ * pt.c (tsubst_friend_function): Only substitute
+ TEMPLATE_PARMS_CONSTRAINTS.
+ (tsubst_template_parms): Copy constraints.
+
2020-01-24 Jason Merrill <jason@redhat.com>
PR c++/93279 - ICE with lambda in member operator.
decl_constraints->remove (t);
}
+/* If DECL is a friend, substitute into REQS to produce requirements suitable
+ for declaration matching. */
+
+tree
+maybe_substitute_reqs_for (tree reqs, const_tree decl_)
+{
+ if (reqs == NULL_TREE)
+ return NULL_TREE;
+ tree decl = CONST_CAST_TREE (decl_);
+ tree result = STRIP_TEMPLATE (decl);
+ if (DECL_FRIEND_P (result))
+ {
+ tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl;
+ tree gargs = generic_targs_for (tmpl);
+ processing_template_decl_sentinel s;
+ if (uses_template_parms (gargs))
+ ++processing_template_decl;
+ reqs = tsubst_constraint (reqs, gargs,
+ tf_warning_or_error, NULL_TREE);
+ }
+ return reqs;
+}
+
/* Returns the template-head requires clause for the template
declaration T or NULL_TREE if none. */
extern tree current_template_constraints (void);
extern tree associate_classtype_constraints (tree);
extern tree build_constraints (tree, tree);
+extern tree maybe_substitute_reqs_for (tree, const_tree);
extern tree get_template_head_requirements (tree);
extern tree get_trailing_function_requirements (tree);
extern tree get_shorthand_constraints (tree);
tree reqs2 = get_trailing_function_requirements (oldfn);
if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE))
return false;
+ reqs1 = maybe_substitute_reqs_for (reqs1, newfn);
+ reqs2 = maybe_substitute_reqs_for (reqs2, oldfn);
return cp_tree_equal (reqs1, reqs2);
}
DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
- /* Attach the template requirements to the new declaration
- for declaration matching. We need to rebuild the requirements
- so that parameter levels match. */
- if (tree ci = get_constraints (decl))
- {
- tree parms = DECL_TEMPLATE_PARMS (new_friend);
- tree args = generic_targs_for (new_friend);
- tree treqs = tsubst_constraint (CI_TEMPLATE_REQS (ci), args,
- tf_warning_or_error, NULL_TREE);
- tree freqs = tsubst_constraint (CI_DECLARATOR_REQS (ci), args,
- tf_warning_or_error, NULL_TREE);
-
- /* Update the constraints -- these won't really be valid for
- checking, but that's not what we need them for. These ensure
- that the declared function can find the friend during
- declaration matching. */
- tree new_ci = get_constraints (new_friend);
- CI_TEMPLATE_REQS (new_ci) = treqs;
- CI_DECLARATOR_REQS (new_ci) = freqs;
-
- /* Also update the template parameter list. */
- TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
- }
+ /* Substitute TEMPLATE_PARMS_CONSTRAINTS so that parameter levels will
+ match in decls_match. */
+ tree parms = DECL_TEMPLATE_PARMS (new_friend);
+ tree treqs = TEMPLATE_PARMS_CONSTRAINTS (parms);
+ treqs = maybe_substitute_reqs_for (treqs, new_friend);
+ TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
}
/* The mangled name for the NEW_FRIEND is incorrect. The function
tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
- TMPL_ARGS_DEPTH (args)),
new_vec, NULL_TREE);
+ TEMPLATE_PARMS_CONSTRAINTS (*new_parms)
+ = TEMPLATE_PARMS_CONSTRAINTS (parms);
}
--processing_template_decl;
template <True U> struct B { int i = ++U::x; };
template <True U> void f() { ++U::x; }
+template <class U> void g() requires True<U> { ++U::x; }
template <class V> class C
{
template <True U> friend struct B;
template <True U> friend void f();
+ template <class U> friend void g() requires True<U>;
};
int main()
{
f<C<int>>();
+ g<C<int>>();
B<C<int>>();
}
--- /dev/null
+// PR c++/93400
+// { dg-do compile { target concepts } }
+
+template <typename> bool a = true;
+template <typename i> concept b = a<i>;
+template <int> struct f { template <b c> friend auto g(c, f); };
+auto d = f<1>{};
+auto e = f<0>{};
// { dg-do run { target c++2a } }
-// { dg-additional-options "-fconcepts-ts" }
template<class, class> constexpr bool is_same_v = false;
template<class T> constexpr bool is_same_v<T, T> = true;
template<class T, class U>
-concept bool Same = is_same_v<T, U>;
+concept Same = is_same_v<T, U>;
template<class T, class U>
-concept bool Diff = requires(T& t, U& u) { u - t; };
+concept Diff = requires(T& t, U& u) { u - t; };
template<class I, class S>
int distance(I, S) { return 0; }