+/* A subroutine of duplicate_decls. Emits a diagnostic when newdecl
+ ambiguates olddecl. Returns true if an error occurs. */
+
+static bool
+duplicate_function_template_decls (tree newdecl, tree olddecl)
+{
+
+ tree newres = DECL_TEMPLATE_RESULT (newdecl);
+ tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+ /* Function template declarations can be differentiated by parameter
+ and return type. */
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (oldres)),
+ TYPE_ARG_TYPES (TREE_TYPE (newres)))
+ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+ TREE_TYPE (TREE_TYPE (olddecl))))
+ {
+ /* ... and also by their template-heads and requires-clauses. */
+ if (template_heads_equivalent_p (newdecl, olddecl)
+ && function_requirements_equivalent_p (newres, oldres))
+ {
+ error ("ambiguating new declaration %q+#D", newdecl);
+ inform (DECL_SOURCE_LOCATION (olddecl),
+ "old declaration %q#D", olddecl);
+ return true;
+ }
+
+ /* FIXME: The types are the same but the are differences
+ in either the template heads or function requirements.
+ We should be able to diagnose a set of common errors
+ stemming from these declarations. For example:
+
+ template<typename T> requires C void f(...);
+ template<typename T> void f(...) requires C;
+
+ These are functionally equivalent but not equivalent. */
+ }
+
+ return false;
+}
+