https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117643

--- Comment #20 from anlauf at gcc dot gnu.org ---
(In reply to Jerry DeLisle from comment #19)
> (In reply to kargls from comment #17)
> > I suppose the error in check.cc(gfc_check_f_c_string) that starts
> > with
> > 
> >     if (string->ts.type != BT_CHARACTER
> >        || (string->ts.type == BT_CHARACTER
> >       && (string->ts.kind != 1 || string->ts.is_c_interop != 1)))
> >  
> > can be suppressed for (string.expr_type == EXPR_CONSTANT &&
> > string->ts.type == BT_CHARACTER && string->ts.kind == 1)

I am a little confused by the above logic.  So far I was under the
impression that a string->ts.kind != 1 cannot be interoperable.  There
is an existing PR (need to find it) that we illegally accept kind=4
for BIND(C) procedures.  E.g.

  subroutine sub (s) bind(c)
    character(kind=4,len=*), intent(in) :: s
  end

is silently accepted although it should not.  Of course we detect that
when passed as argument to F_C_STRING, but other might scratch their head
later when looking at the code...

> Of course after posting what I just did in Comment #18 I see Steve's comment
> in 17. Maybe I have my logic all wrong on the error message. I saw the kind
> = 1 and did not expect is_c_interop to be set since c_char_'string_constant'
> is equivalent to 1_'string_constant'.

Other compilers seem to print identical values for KIND(1_"a") and
KIND(c_char_"b"), as verified for NAG and Intel.

But we can check interoperability for variables (and in theory for functions
returning character).

So if I come from the other side, which code to accept and which to diagnose,
I tried:

  if (string->ts.type != BT_CHARACTER
      || string->ts.kind != 1
      || (string->expr_type == EXPR_VARIABLE && !string->ts.is_c_interop))

and threw it on:

  subroutine sub1 (s)
    character(*), intent(in) :: s
    print *, f_c_string (s)        ! detected
    print *, f_c_string (trim(s))  ! not detected
  end

  subroutine sub2 (s)
    character(kind=c_char,len=*), intent(in) :: s
    print *, f_c_string (s)        ! OK
    print *, f_c_string (trim(s))  ! OK
  end

I tried to extend to above conditions to
.. (string->expr_type == EXPR_VARIABLE || string->expr_type == EXPR_FUNCTION)
..
but it appears that TRIM() keeps only the kind parameter, and when the argument
is of kind C_CHAR the result string looses the interoperability attribute.

So we could ignore the issue with function results for the time being and
use the above variant of the logic in gfc_check_f_c_string.

The two separate testcase could also be combined into one file as they share
a lot of code but that's not really important.

What do you think?

Reply via email to