Without the patch below, an attempted namelist write to an unformatted file -
which is prohibited by the standard - would generate the following runtime 
error:

At line 12 of file pr95195.f90 (unit = 10, file = 'test.dat')
Fortran runtime error: End of record

followed by some backtrace.  The patch attempts to generate an error pointing
the user to the real issue.

Regtested on x86_64-pc-linux-gnu.

OK for master?

Thanks,
Harald


PR libfortran/95195 - improve runtime error for namelist i/o to unformatted file

        Namelist input/output to unformatted files is prohibited.
        Generate useful runtime errors instead instead of misleading ones.

libgfortran/

2020-05-24  Harald Anlauf  <anl...@gmx.de>

        PR fortran/95195
        * io/transfer.c (finalize_transfer): Generate runtime error for
        namelist input/output to unformatted file.

gcc/testsuite/

2020-05-24  Harald Anlauf  <anl...@gmx.de>

        PR fortran/95195
        * gfortran.dg/namelist_97.f90: New test.

diff --git a/gcc/testsuite/gfortran.dg/namelist_97.f90 b/gcc/testsuite/gfortran.dg/namelist_97.f90
new file mode 100644
index 00000000000..4907e46b46a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/namelist_97.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! { dg-output "At line 12 .*" }
+! { dg-shouldfail "Fortran runtime error: Namelist formatting .* FORM='UNFORMATTED'" }
+!
+! PR95195 - improve runtime error when writing a namelist to an unformatted file
+
+program test
+  character(len=11) :: my_form = 'unformatted'
+  integer           :: i = 1, j = 2, k = 3
+  namelist /nml1/ i, j, k
+  open  (unit=10, file='test.dat', form=my_form)
+  write (unit=10, nml=nml1)
+  close (unit=10, status='delete')
+end program test
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index b8db47dbff9..d071c1ce915 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -4123,6 +4123,14 @@ finalize_transfer (st_parameter_dt *dtp)
   if ((dtp->u.p.ionml != NULL)
       && (cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0)
     {
+       if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
+	 {
+	   generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
+			   "Namelist formatting for unit connected "
+			   "with FORM='UNFORMATTED");
+	   return;
+	 }
+
        dtp->u.p.namelist_mode = 1;
        if ((cf & IOPARM_DT_NAMELIST_READ_MODE) != 0)
 	 namelist_read (dtp);

Reply via email to