gnu/gcc/dfe38eb88b4e69be691e3495038d292edff77f36 fortran: ICE or wrong-code for ASSOCIATE selector that is a type-bound user-defined operator
Three related bugs prevented ASSOCIATE selectors that are type-bound
user-defined operator expressions from compiling correctly.
Bug 1 (class.cc): find_typebound_proc_uop returned NULL immediately when
the derived type has no f2k_derived namespace, bypassing the parent-type
inheritance walk. This caused inherited UDOs to be silently not found.
Fix: set root = NULL and let the loop reach the parent type instead.
Bug 2 (resolve.cc): resolve_typebound_procedures called resolve_symbol on
the parent type only after an early return that fires when the derived type
has no direct type-bound bindings. This left parent-type bindings
unresolved when searched via gfc_find_typebound_user_op.
Fix: move resolve_symbol(super_type) before the early return.
Bug 3 (match.cc): match_association_list did not handle ASSOCIATE selectors
of the form .uop. expr or the nested case .uop2. (.uop1. expr). When the
selector's type was BT_UNKNOWN at parse time the name of the associate
variable was left untyped, producing a "Syntax error in expression" ICE in
the body of the ASSOCIATE construct.
Add three helpers before match_association_list:
- resolve_assoc_operand: attempts gfc_resolve_expr on EXPR_FUNCTION
operands and falls back to gfc_find_dt_in_generic for constructor calls
whose argument types are not yet known.
- infer_typebound_uop_type: reads the return type of a type-bound UDO
directly from specific_st->n.tb->u.specific->n.sym without calling
gfc_resolve_symbol, avoiding a resolve_symbol_called race condition.
- extend_assoc_op: walks the expression tree bottom-up, propagating
types through INTRINSIC_PARENTHESES wrappers before calling the two
helpers above on each INTRINSIC_USER node.
When the selector is an INTRINSIC_USER EXPR_OP with BT_UNKNOWN type,
call extend_assoc_op on the operands, then gfc_extend_expr (errors
suppressed). Accept the result when gfc_extend_expr returns MATCH_YES or
when it returns MATCH_ERROR but has already converted the node to
EXPR_COMPCALL with a known type (the full resolution pass finishes it).
Assisted-by: Claude Sonnet 4.6
PR fortran/125528
gcc/fortran/ChangeLog:
* class.cc (find_typebound_proc_uop): Set root = NULL instead of
returning NULL when derived type lacks f2k_derived, so parent-type
type-bound procedures and operators are still found via inheritance.
* match.cc (resolve_assoc_operand): New helper.
(infer_typebound_uop_type): New helper.
(extend_assoc_op): New helper.
(match_association_list): Handle ASSOCIATE selectors that are
type-bound user-defined operator expressions, including nested cases.
* resolve.cc (resolve_typebound_procedures): Move resolve_symbol
call for the parent type before the early return so inherited
type-bound bindings are resolved even when the child type has none
of its own.
gcc/testsuite/ChangeLog:
* gfortran.dg/associate_80.f90: New test.
(cherry picked from commit 6340639219bb2d1816c94e5de76ec3642453bcb2)
4 files changed