Le 27/07/2025 à 11:37, Yuao Ma a écrit :
On 7/27/2025 5:19 PM, Mikael Morin wrote:
+gfc_charlen_type
+string_split (gfc_charlen_type stringlen, const CHARTYPE *string,
+          gfc_charlen_type setlen, const CHARTYPE *set,
+          gfc_charlen_type pos, GFC_LOGICAL_4 back)
+{
+  gfc_charlen_type i, j;
+
+  if (!back)
+    {
+      if (pos > stringlen)
+    runtime_error ("If BACK is present with the value false, the value of "
+               "POS shall be in the range [0, LEN (STRING)]");
+
The condition doesn't check pos >= 0; I think the case pos < 0 doesn't work.

The variable pos is an unsigned type, so checking for < 0 is unnecessary. (I was not initially aware of this, but the compiler warning alerted me.)

Mmmh, good point.  But POS is a user variable, so a signed type originally.
Can you check the following:

   integer(kind=1) :: my_pos = -1
   character(len=300) :: my_str = ""
   call split(my_str, " ", my_pos)

Is it rejected at runtime?
I expect the unsigned conversion to convert -1 to 255 and then the call would be (wrongly) accepted.


Yes, it's rejected at runtime. The trick lies in how the pos is handled: it's first converted to gfc_charlen_type (an unsigned long long). So, even if kind=1 and the input is -1, it wraps around to a very large positive value (specifically, ULLONG_MAX - 1). This value far exceeds 300, leading to a runtime error.

+  pos_for_call = fold_convert (gfc_charlen_type_node, pos);


Ok, according to the dump the conversion is to integer(kind=8) which is signed. Anyway, I think it works for any sensible case.

So the case above is rejected, but now the value of pos printed is not what the user specified.
This is what I get:

Fortran runtime error: If BACK is present with the value false, the value of POS shall be in the range [0, LEN (STRING)], where POS = 18446744073709551615 and LEN (STRING) = 300


Another thing I noticed:
+  gfc_add_expr_to_block (&block, call);
+  gfc_add_modify (&block, pos, fold_convert (TREE_TYPE (pos), call));

You are using the call twice; this results in two calls to the function split in the dump:

  _gfortran_string_split (300, &my_str, 1, &" "[1]{lb: 1 sz: 1}, 
(integer(kind=8)) my_pos, 0);
  my_pos = (integer(kind=1)) _gfortran_string_split (300, &my_str, 1, &" 
"[1]{lb: 1 sz: 1}, (integer(kind=8)) my_pos, 0);




Reply via email to