Hi Tobias, On Tue, Sep 16, 2025 at 5:11 PM Tobias Burnus <tbur...@baylibre.com> wrote: > PS: Already with the current code, we may run into the issue of passing > an actual argument like '(cond ? "abc" : "cdfg")' to 'class(*)' – and I > am not sure whether we handle this correctly or not.
That is a great test case, and I apologize for not testing against the cond-arg part. The current patch doesn't work well with cond-arg, whether or not class(*) is involved. To avoid introducing new ICE, I'll hold off on this patch until we can properly use character types in both cond-expr and cond-arg. Part of the root of the problem seems to be here: https://github.com/gcc-mirror/gcc/blob/857c742e7bb8b24a05180e1cfee62efa417a48fe/gcc/fortran/trans-expr.cc#L10652. When the expression's type is found to be a character, it uses gfc_conv_string_parameter and returns immediately. Handling EXPR_CONDITIONAL first would solve part of the issue, allowing two character variables to be passed without a problem. However, passing two STRING_CST still causes an ICE, failing in fold_convert_loc within GIMPLE. I'm currently investigating why this is happening. > > For BT_DERIVED: > > (i) The type needs to be the same – or compatible ('SEQUENCE' attribute) > > I was referring to: "7.5.2.4 Determination of derived types": > > "Data entities also have the same type if they are declared with > reference to different derived-type definitions that specify the same > type name, all have the SEQUENCE attribute or all have the BIND attribute." > > But as they need to have the same name, it is formally correct, but has > no practical effect for checking. > > Thus, feel free to ignore this mumbling. > > * * * > > > (ii) If there are kind arguments, it needs to be the same. > > gfortran names parameterized derived types (PDT) as > 'Pdt' + type name + '_<kindvalue> – thus for > 'type t(x); integer, kind :: x' – the names associated > with type(t(x=5)) and type(t(6)) are 'Pdtt_5' and 'Pdtt_6', > respectively. - Which implies a name check. > > However, it seems as if the simplest is to call: > gfc_compare_types and use gfc_typename in the diagnostic. > > As discussed before, I think rejecting BT_CLASS for now > makes sense, but there is no reason why BT_DERIVED including > PDT can't be enabled. > > > type t(kind,dim) > integer, kind :: kind = 4, dim = 10 > real(kind=kind) :: array(dim) > end type t > ... > type(t(8)) :: x > type(t(dim=10)) :: y > type(t(8,24)) :: z > > would be a use for the *kind type parameter* ('kind'); The kind is > known at compile time and, hence, does not actually need to be stored > in the type. The 'len' type parameter also exists. > > * * * > > BT_CLASS: > > As the declare type needs to be the same, > > subroutine sub(var, var2) > type(t) :: var > class(t) :: var2 > ... (cond ? var : var2) > > seems to be fine – and would be accepted by the gfc_compare_types > check. But there are presumably further adjustments required, > Including, possibly the optimization whether BT_CLASS should > be converted to BT_DERIVED or BT_DERIVED to BT_CLASS, depending > how the conditional-expr / conditional-arg is used. Erring on > BT_CLASS is probably best, but having some optimizations might > still make sense, at least when used as dummy argument. > > * * * > > And regarding procedure/procedure pointers: > > While 'actual-arg' (R1524) permits procedure-name and proc-component-ref, > the 'conditional-arg' constitutent, i.e. 'consequent-arg' (R1528) only > permits 'expr' or 'variable' - i.e. no procedures are permitted > > * * * > > Talking about NIL, I noticed that (cond ? .nil. : .nil.) is invalid, > cf. first sentence of: > > C1540 At least one consequent in a conditional-arg shall be a consequent-arg. > If the corresponding dummy argument is not optional, .NIL. shall not appear. > I'm on the same page. When we ship cond-arg with nil, I think we need to ensure the following diagnostics are supported: 1: Reject (cond ? nil : nil) This case is straightforward and has already been implemented. We should reject any cond-expr where both branches are nil. 2: Disallow nil for Non-Optional Dummy Arguments If a dummy argument isn't declared with the OPTIONAL attribute, nil shouldn't be allowed as an actual argument. I think the ideal place for this check is in compare_actual_formal, where we can raise an error if the formal argument lacks the OPTIONAL attribute and the actual argument is nil. The challenge is figuring out how to store the information that an inner cond-expr contains a nil branch. I haven't found a clean solution yet. Perhaps adding a new field to the AST could work? You previously mentioned using do_not_resolve_again to move the check to the optional checking part. Could you elaborate more on this? 3: Restrict nil only in cond-arg nil shouldn't appear in a regular cond-expr outside of an argument list. The problem is differentiating between when gfc_resolve_expr is resolving a function argument versus an ordinary expression. The former is called from resolve_actual_arglist, but I haven't found a way to distinguish between these two contexts yet. > > PS: Sorry, previous patch review email was written in a bit of a rush as I > had a series of meetings afterwards. > > PPS: If you dislike the gfc_typename output: This is a known problem, but > not that trivial to be fixed as gfc_typename returns a 'const char*', > i.e. dynamic memory allocation is not possible. On the other hand, adding > kind values to type names might quickly exceed the available length for > symbol names - not only for the diagnostic but also internally. For the > latter, the idea to use the string pool as used for 'tree' by the middle > end, was discussed. For now, the hope is that any sensible program does > not exceed this. > For now, just use it – but eventually it should be improved ... > Thanks for the detailed write-up! I'll refer to them carefully when I work on the relevant part. Best regards, Yuao