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
