On Mon, 14 Oct 2024, Jason Merrill wrote:

> Tested x86_64-pc-linux-gnu, applying to trunk.
> 
> -- 8< --
> 
> CWG2918 changes deduction from an overload set for the case where multiple
> candidates succeed and have the same type; previously this made the overload
> set a non-deduced context, now it succeeds since the result is consistent
> between the candidates.
> 
> This is needed for cases of overloading based on requirements, where we want
> to choose the most constrained overload.  I also needed to adjust
> resolve_address_of_overloaded_function accordingly; we already handled the
> comparison for template candidates in most_specialized_instantiation, but
> need to also do the comparison for non-template candidates such as member
> functions of a class template.
> 
>       CWG 2918 (proposed)
> 
> gcc/cp/ChangeLog:
> 
>       * cp-tree.h (most_constrained_function): Declare..
>       * class.cc (resolve_address_of_overloaded_function): Call it.
>       * pt.cc (get_template_for_ordering): Handle list from
>       resolve_address_of_overloaded_function.
>       (most_constrained_function): No longer static.
>       (resolve_overloaded_unification): Always compare type rather
>       than decl.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/DRs/dr2918.C: New test.
> ---
>  gcc/cp/cp-tree.h                  |  1 +
>  gcc/cp/class.cc                   | 13 ++++++++++---
>  gcc/cp/pt.cc                      | 18 ++++++++++++++----
>  gcc/testsuite/g++.dg/DRs/dr2918.C | 11 +++++++++++
>  4 files changed, 36 insertions(+), 7 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/DRs/dr2918.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index dc153a97dc4..94ee550bd9c 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7593,6 +7593,7 @@ extern int template_args_equal                  (tree, 
> tree);
>  extern tree maybe_process_partial_specialization (tree);
>  extern tree most_specialized_instantiation   (tree);
>  extern tree most_specialized_partial_spec       (tree, tsubst_flags_t, bool 
> = false);
> +extern tree most_constrained_function                (tree);
>  extern void print_candidates                 (tree);
>  extern void instantiate_pending_templates    (int);
>  extern tree tsubst_default_argument          (tree, int, tree, tree,
> diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
> index 646072d4f20..8c39bb4a76b 100644
> --- a/gcc/cp/class.cc
> +++ b/gcc/cp/class.cc
> @@ -8896,11 +8896,18 @@ resolve_address_of_overloaded_function (tree 
> target_type,
>         tree match = most_specialized_instantiation (matches);
>  
>         if (match != error_mark_node)
> -         matches = tree_cons (TREE_PURPOSE (match),
> -                              NULL_TREE,
> -                              NULL_TREE);
> +         {
> +           matches = match;
> +           TREE_CHAIN (match) = NULL_TREE;
> +         }
>       }
>      }
> +  else if (flag_concepts && TREE_CHAIN (matches))
> +    if (tree match = most_constrained_function (matches))
> +      {
> +     matches = match;
> +     TREE_CHAIN (match) = NULL_TREE;
> +      }
>  
>    /* Now we should have exactly one function in MATCHES.  */
>    if (matches == NULL_TREE)
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 03a1144765b..c0a37a51cba 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -2071,6 +2071,10 @@ get_template_for_ordering (tree list)
>  {
>    gcc_assert (TREE_CODE (list) == TREE_LIST);
>    tree f = TREE_VALUE (list);
> +  if (f == NULL_TREE)
> +    /* Also handle a list from resolve_address_of_overloaded_function with 
> the
> +       function in TREE_PURPOSE.  */
> +    f = TREE_PURPOSE (list);
>    if (tree ti = DECL_TEMPLATE_INFO (f))
>      return TI_TEMPLATE (ti);
>    return f;
> @@ -2084,7 +2088,7 @@ get_template_for_ordering (tree list)
>  
>     Note that we don't compare constraints on the functions
>     themselves, but rather those of their templates. */
> -static tree
> +tree
>  most_constrained_function (tree candidates)
>  {
>    // Try to find the best candidate in a first pass.
> @@ -23865,11 +23869,14 @@ resolve_overloaded_unification (tree tparms,
>       tree fn = *iter;
>       if (flag_noexcept_type)
>         maybe_instantiate_noexcept (fn, tf_none);
> -     if (try_one_overload (tparms, targs, tempargs, parm, TREE_TYPE (fn),
> +     if (TREE_CODE (fn) == FUNCTION_DECL && !constraints_satisfied_p (fn))
> +       continue;

FWIW this seems to also fix PR80637 (in which we weren't discarding
functions with unsatisfied constraints when resolving &A<int>::f).

> +     tree elem = TREE_TYPE (fn);
> +     if (try_one_overload (tparms, targs, tempargs, parm, elem,
>                             strict, sub_strict, addr_p, explain_p)
> -         && (!goodfn || !decls_match (goodfn, fn)))
> +         && (!goodfn || !same_type_p (goodfn, elem)))
>         {
> -         goodfn = fn;
> +         goodfn = elem;
>           ++good;
>         }
>        }
> @@ -23879,6 +23886,9 @@ resolve_overloaded_unification (tree tparms,
>       overloaded functions does not contain function templates and at most
>       one of a set of overloaded functions provides a unique match.
>  
> +     CWG2918 allows multiple functions to match if they all have the same 
> type,
> +     so that we can choose the most constrained later.
> +
>       So if we found multiple possibilities, we return success but don't
>       deduce anything.  */
>  
> diff --git a/gcc/testsuite/g++.dg/DRs/dr2918.C 
> b/gcc/testsuite/g++.dg/DRs/dr2918.C
> new file mode 100644
> index 00000000000..982ced71f1f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/DRs/dr2918.C
> @@ -0,0 +1,11 @@
> +// CWG 2918 makes this OK
> +// { dg-do compile { target c++20 } }
> +
> +template<bool B> struct X {
> +  static void f(short) requires B; // #1
> +  static void f(short);                 // #2
> +};
> +void test() {
> +  auto x = &X<true>::f;              // OK, deduces void(*)(short), selects 
> #1
> +  auto y = &X<false>::f;     // OK, deduces void(*)(short), selects #2
> +}
> 
> base-commit: fa04a1713b54bdc4c7b686c88117c9c46043ec73
> -- 
> 2.47.0
> 
> 

Reply via email to