On Thu, Feb 12, 2026 at 12:19:57PM +0100, Jakub Jelinek wrote:
> Ah, you're right.
> 
> We don't have any API to return whether there are any viable candidates.
> I was looking into adding one, but realized that finish_call_expr
> does way too many things before calling build_new_function_call plus
> in some cases it calls build_op_call which does further stuff that
> would also need to be duplicated before we can reach to splice_viable.
> 
> So, instead of duplicating all of that I've added tf_any_viable (using
> an unused bit in tsubst_flags_t), which is then handled in
> perform_overload_resolution, build_new_function_call and build_op_call
> functions to return void_node instead of actually building any calls
> if there are any viable candidates (and keep returning error_mark_node
> if something earlier fails or there are no viable candidates).
> 
> The new testcase adds some extra new tests, e.g. struct with begin and
> end non-static data members (my reading is that in that case E.begin
> and E.end has been found, so we commit to iterating expansion stmt and
> fail unless e.g. they whould have class type and usable operator ()).
> 
> So far tested with
> GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make -j32 -k check-g++ 
> RUNTESTFLAGS="dg.exp='reflect/* expansion-stmt*'"

Bootstrapped/regtested successfully on x86_64-linux and i686-linux
after changing expansion-stmt30.C to be dg-do compile rather than
dg-do run.

> 2026-02-12  Jakub Jelinek  <[email protected]>
> 
>       * cp-tree.h: Implement proposed CWG 3123 resolution.
>       (enum tsubst_flags): Add tf_any_viable enumerator.  Indent all
>       comments the same.
>       * call.cc (perform_overload_resolution): For tf_any_viable
>       return the first candidate instead of doing tourney.
>       (build_new_function_call): For tf_any_viable return void_node
>       if any viable candidates are found rather than build_over_call.
>       (build_op_call): FOr tf_any_viable return void_node if any
>       viable candidates are found instead of calling tourney etc.
>       * parser.cc (cp_perform_range_for_lookup): Pass COMPLAIN to
>       cp_range_for_member_function calls.  If not tf_error, for
>       successful ADL if one or both of finish_call_expr calls returns
>       error_mark_node, retry with tf_any_viable.  If both begin and
>       end expressions have a viable candidate or when member lookup
>       found both begin and end members, return NULL_TREE rather than
>       error_mark_node even when both *begin and *end are error_mark_node.
>       (cp_range_for_member_function): Add COMPLAIN argument, pass it
>       down to finish_class_member_access_expr and finish_call_expr.
>       * pt.cc (finish_expansion_stmt): Use esk_iterating if
>       cp_perform_range_for_lookup returned something other than
>       error_mark_node or if both begin_expr and end_expr are not
>       error_mark_node.
> 
>       * g++.dg/cpp26/expansion-stmt29.C: New test.
>       * g++.dg/cpp26/expansion-stmt30.C: New test.

        Jakub

Reply via email to