When resolving the address of a template-id, we need to drop functions
whose associated constraints are not satisfied, as per [over.over]. We
do so in resolve_address_of_overloaded_function, but not in
resolve_overloaded_unification or resolve_nondeduced_context, which
seems like an oversight.
gcc/cp/ChangeLog:
* pt.c (resolve_overloaded_unification): Drop functions with
unsatisfied constraints.
(resolve_nondeduced_context): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-fn5.C: New test.
* g++.dg/concepts/fn8.C: Generalize dg-error directive to accept
"no matching function ..." diagnostic.
* g++.dg/cpp2a/concepts-fn1.C: Likewise.
* g++.dg/cpp2a/concepts-ts2.C: Likewise.
* g++.dg/cpp2a/concepts-ts3.C: Likewise.
&& !any_dependent_template_arguments_p (subargs))
{
fn = instantiate_template (fn, subargs, tf_none);
+ if (!constraints_satisfied_p (fn))
+ continue;
if (undeduced_auto_decl (fn))
{
/* Instantiate the function to deduce its return type. */
badfn = fn;
badargs = subargs;
}
- else if (elem && (!goodfn || !decls_match (goodfn, elem)))
+ else if (elem && (!goodfn || !decls_match (goodfn, elem))
+ && constraints_satisfied_p (elem))
{
goodfn = elem;
++good;
void g(T x) { }
int main () {
- g(&f<int>); // { dg-error "no matches" }
+ g(&f<int>); // { dg-error "no match" }
}
void driver_3 ()
{
g(&ok<int>);
- g(&err<int>); // { dg-error "no matches" }
+ g(&err<int>); // { dg-error "no match" }
}
--- /dev/null
+// Verify we check associated constraints when resolving the address of a
+// template-id.
+// { dg-do compile { target c++20 } }
+
+void id(auto) { }
+
+template <typename>
+int f() { return 0; }
+
+template <typename T> requires requires { T::fail(); }
+auto f() { T::fail(); }
+
+int main() {
+ using U = decltype(&f<int>);
+ (void)&f<int>;
+ id(&f<int>);
+}
void driver_3 ()
{
g(&ok<int>);
- g(&err<int>); // { dg-error "no matches" }
+ g(&err<int>); // { dg-error "no match" }
}
void driver_3 ()
{
g(&ok<int>);
- g(&err<int>); // { dg-error "no matches" }
+ g(&err<int>); // { dg-error "no match" }
}