Hi Yuao,

first, sorry for the belated reply. Besides other work, I blame the
Cauldron -> https://gcc.gnu.org/wiki/cauldron2025 ,
an internal company gathering, and the (virtual) OpenMP
specification meeting in the last week for not having done the
review.

Can you remind me (aka as 'ping' me) in a while for the two pending
sinpi patches? I first need to review some other patches first plus
make a bit progress on my own - but don't want that they fall through
the cracks.

Yuao Ma wrote:

On Mon, Sep 22, 2025 at 3:47 PM Tobias Burnus<[email protected]> wrote:
Thanks for the updated patch. Glancing at the code, I wondered about:

+  if (expr->ts.type == BT_CHARACTER && !gfc_is_proc_ptr_comp (expr))

Namely: Why are procedure-pointer components handled differently?
I must admit that I borrowed this code snippet from gfc_conv_variable.
I am unsure if gfc_is_proc_ptr_comp is appropriate here, so I included
it to keep them consistent.

Well, this does not explain why it is there forgfc_conv_variable, either. I thought that I should investigate, added a gfc_warning and run the testsuite. Result: It triggers for testcases that have the following pattern: type t procedure(deferred_len), pointer, nopass :: ppt end type t contains function deferred_len() character(len=:), allocatable :: deferred_len ... type(t) :: x x%ppt => deferred_len Here, the LHS is procedure pointer that is a component of a derived type. Before the code in question, we have at tree level: *(x.ppt) such that we need to remove the '*' via gfc_build_addr_expr → 'x.ppt'. * * * That was for convert_varable; however, early in convert_constant, there is: if (expr->expr_type != EXPR_CONSTANT) ... return; And I frankly fail how we could ever end up with a constant that is an procedure pointer. BTW: I tried the following but it calls convert_variable; I tried something else, but run into other issues → https://gcc.gnu.org/PR122278 ----------------------- implicit none (type, external) type t procedure(deferred_len), pointer, nopass :: ppt => null() end type t type(t), parameter :: pp = t() procedure(deferred_len), pointer :: x x => pp%ppt contains function deferred_len() character(len=:), allocatable :: deferred_len end end ---------------------- Thus, I wonder whether we should remove is as never-true condition (or with '!' always true). * * *

Thanks for providing those test cases! They helped me see the real
issue. The problem is that most of the existing character arguments
are handled directly within gfc_conv_string_parameter. This means even
when I reordered the expr types in gfc_conv_expr_reference, I was
still missing cases like the ones you found.
So, I've taken a different approach: for character types, I'm now
handling the cond-expr directly inside gfc_conv_string_parameter. This
involves recursively calling the function for both the lse and rse.
The failed test cases now work with this patch.

:-)


BTW: Using  "abc"(1:i) or str(i:5) similar substrings, it is possible
to combine a constant string or const-length variable with not knowing
the length address of the  in the expression - including also changing
the first character picked from the string.
I have tested "abc"(1:i) pattern in my latest patch and it works as expected.
Thanks!
PS: Sorry for the late reply! I had some urgent stuff come up that ate
most of my time. : (

Same issue for everyone …

* * *

+  /* TODO: support array for conditional expressions  */

Shouldn't this be, e.g.,
- TODO: support arrays in conditional expressions
- TODO: conditional expressions with arrays
- TODO: array support for/in conditional expressions
? 'support array' sounds as if you want to add an auxiliary
array for handling conditional expressions.

Not that it really matters as we hopefully can soon have some
array support and it is an internal comment, only :-)

* * *

Otherwise, LGTM.

Thanks for the patch!

Tobias

PS: I was a bit unsure whether the string-length evaluation
properly handles se.pre/se.post, but it does:

      D.4681 = x != 0B;
      if (D.4681)
        {
          D.4682 = f ();
          D.4683 = *D.4682;
          __builtin_free ((void *) D.4682);
...
..., D.4681 ? MAX_EXPR< ... D.4684>, 0> : 3

for

implicit none (type, external)
integer, allocatable :: x

print *, (allocated (x) ? "abcded"(1:f()) : "bar")
contains
function f()
 integer, allocatable :: f
 f = x
end
end

Reply via email to