Hello,

The attached patch fixes the subject bug by adding checks for ';' it specific
places to avoid eating them and/or giving false errors.

New test case provided.

Regression tested on X86_64_linux_gnu. Also compares with flang-new.

Ok for trunk and I think gcc-15?

Regards,

Jerry
commit bb9a09fb431bf8e5debf88952725b8d79dfc226c
Author: Jerry DeLisle <jvdeli...@gcc.gnu.org>
Date:   Tue Aug 5 12:10:24 2025 -0700

    Fortran: Fix runtime bogus diagnostic with ';'
    
            PR libfortran/121234
    
    libgfortran/ChangeLog:
    
            * io/list_read.c (read_character): Add checks to bypass eating
            semicolons when reading strings with decimal mode 'point'
            (list_formatted_read_scalar): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/pr121234.f90: New test.

diff --git a/gcc/testsuite/gfortran.dg/pr121234.f90 b/gcc/testsuite/gfortran.dg/pr121234.f90
new file mode 100644
index 00000000000..8eb1af534cb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr121234.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! PR121234 Bogus diagnostic on READ of string with semicolon.
+  character(12) buffer,a
+  a = 'xxxxxxxxxx'
+  buffer="33;44"
+  read(buffer,*) a
+  if (a .ne. "33;44") stop 1
+  a = 'xxxxxxxxxx'
+  buffer="  ;;33 ,44 "
+  read(buffer,*,decimal="comma") a
+  if (a .ne. 'xxxxxxxxxx') stop 2 ! A null read
+  a = 'xxxxxxxxxx'
+  buffer="  ;;33 ,44 "
+  read(buffer,*,decimal="point") a
+  if (a .ne. ';;33') stop 3 ! Spaces are delimiting
+  a = 'xxxxxxxxxx'
+  buffer=";;33;,44 "
+  read(buffer,*) a
+  if (a .ne. ';;33;') stop 4 ! Comma is delimiting
+  a = 'xxxxxxxxxx'
+  buffer=";;33;44;; "
+  read(buffer,*) a
+  if (a .ne. ';;33;44;;') stop 5 ! Space is delimiting
+  a = 'xxxxxxxxxx'
+  buffer=";;33;44;;;.7"
+  read(buffer,*) a
+  if (a .ne. ';;33;44;;;.7') stop 6 ! Space is delimiting
+end
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index 83124b50756..7c22f61e5a7 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -1262,6 +1262,11 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
 
   if ((c = next_char (dtp)) == EOF)
     goto eof;
+  if (c == ';')
+    {
+      push_char (dtp, c);
+      goto get_string;
+    }
   switch (c)
     {
     CASE_DIGITS:
@@ -1294,6 +1299,13 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
   for (;;)
     {
       c = next_char (dtp);
+
+      if (c == ';')
+	{
+	  push_char (dtp, c);
+	  goto get_string;
+	}
+
       switch (c)
 	{
 	CASE_DIGITS:
@@ -1323,6 +1335,13 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
 
   if ((c = next_char (dtp)) == EOF)
     goto eof;
+
+  if (c == ';')
+    {
+      push_char (dtp, c);
+      goto get_string;
+    }
+
   switch (c)
     {
     CASE_SEPARATORS:
@@ -1346,6 +1365,13 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
     {
       if ((c = next_char (dtp)) == EOF)
 	goto done_eof;
+
+      if (c == ';')
+	{
+	  push_char (dtp, c);
+	  continue;
+	}
+
       switch (c)
 	{
 	case '"':
@@ -2275,6 +2301,8 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
 	}
       if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
 	c = '.';
+      if (c == ';' && dtp->u.p.current_unit->decimal_status == DECIMAL_POINT)
+	unget_char (dtp, c);
       else if (is_separator (c))
 	{
 	  /* Found a null value.  */

Reply via email to