User account creation filtered due to spam.

Bug 26766 - [F2003] Recursive I/O still (again) broken
Summary: [F2003] Recursive I/O still (again) broken
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Jerry DeLisle
URL:
Keywords:
Depends on:
Blocks: 20585
  Show dependency treegraph
 
Reported: 2006-03-20 08:50 UTC by Harald Anlauf
Modified: 2006-04-17 04:38 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-03-24 02:06:36


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Harald Anlauf 2006-03-20 08:50:59 UTC
Hi,

I just checked recursive I/O which was addressed in PR 19352.
It is declared resolved, but still fails with this example:

program gfcbug32
  implicit none
  character (len=4) :: str
  write (str, '(a)')  foo (-1)
  write (*,*) "Test 1:", str
  write (str, '(a)')  foo (1234)
  write (*,*) "Test 2:", str

contains

  function foo (i) result (s)
    integer, intent(in) :: i
    character (len=4)   :: s
    if (i < 0) then
       s = "1234"
    else
       ! Internal I/O, allowed recursive in f2003, see section 9.11
       write (s, '(i4.4)') i
    end if
  end function foo

end program gfcbug32


I get:

At line 6 of file gfcbug32.f90
Fortran runtime error: End of record
 Test 1:1234

Cheers,
-ha
Comment 1 Andrew Pinski 2006-03-20 17:20:50 UTC
Confirmed.
Comment 2 Jerry DeLisle 2006-03-21 06:05:29 UTC
Looking at -fdump-tree-original, should the internal unit descriptors in foo and in main have the same value?  

foo (__result, .__result, i)
{
  if (*i < 0)
    {
      _gfortran_copy_string (4, __result, 4, "1234");
    }
  else
    {
      {
        struct __st_parameter_dt dt_parm.0;

        dt_parm.0.common.filename = "pr26766.f90";
        dt_parm.0.common.line = 15;
        dt_parm.0.internal_unit = (char *) __result;
        dt_parm.0.internal_unit_len = 4;
        dt_parm.0.internal_unit_desc = 0B;    <------ here -------
        dt_parm.0.common.unit = 0;
        dt_parm.0.format = "(i4.4)";
        dt_parm.0.format_len = 6;
        dt_parm.0.common.flags = 20480;
        _gfortran_st_write (&dt_parm.0);
        _gfortran_transfer_integer (&dt_parm.0, (int4 *) i, 4);
        _gfortran_st_write_done (&dt_parm.0);
      }
    }


MAIN__ ()
{
  char str[1:4];
  static void foo (char[1:4] &, int4, int4 &);

  _gfortran_set_std (70, 127, 0);
  {
    struct __st_parameter_dt dt_parm.1;

    dt_parm.1.common.filename = "pr26766.f90";
    dt_parm.1.common.line = 4;
    dt_parm.1.internal_unit = &str;
    dt_parm.1.internal_unit_len = 4;
    dt_parm.1.internal_unit_desc = 0B;   <------ and Here -------
    dt_parm.1.common.unit = 0;
    dt_parm.1.format = "(a)";
    dt_parm.1.format_len = 3;
    dt_parm.1.common.flags = 20480;
    _gfortran_st_write (&dt_parm.1);
    {
      char str.2[4];
      int4 C.906 = 1234;

      foo ((char[1:4] *) &str.2, 4, &C.906);
      _gfortran_transfer_character (&dt_parm.1, (char[1:4] *) &str.2, 4);
    }
    _gfortran_st_write_done (&dt_parm.1);
  }
}


Comment 3 Jerry DeLisle 2006-03-24 02:06:36 UTC
I think I have a fix for this.  The internal_unit is a single static variable declared in unit.c.  So when we have recursive calls to internal IO we are stepping on our own feet.

The dtp structure also contains a unit structure.  If we use this structure instead, there will be an independent internal unit for each internal string or character array we do I/O with.

I will see if I can work up a patch in the next few weeks.

Comment 4 patchapp@dberlin.org 2006-04-07 04:00:16 UTC
Subject: Bug number PR26766

A patch for this bug has been added to the patch tracker.
The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-04/msg00249.html
Comment 5 Jerry DeLisle 2006-04-13 06:25:08 UTC
Subject: Bug 26766

Author: jvdelisle
Date: Thu Apr 13 06:24:58 2006
New Revision: 112914

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=112914
Log:
2006-04-12  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/26766
	* io/io.h: Add bit to identify associated unit as internal.
	* io/unit.c (get_external_unit): Renamed the find_unit_1 function to
	reflect the external unit functionality vs internal unit.
	(get_internal_unit): New function to allocate and initialize an internal
	unit structure.
	(get_unit): Use get_internal_unit and get_external_unit.
	(is_internal_unit): Revised to use new bit added in io.h.
	* io/transfer.c (data_transfer_init): Fix line width.
	(st_read_done): Free memory allocated for internal unit.
	(st_write_done): Add test to only flush and truncate when not an
	internal unit.  Free memory allocated for internal unit.

Modified:
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c

Comment 6 Jerry DeLisle 2006-04-13 06:30:16 UTC
Subject: Bug 26766

Author: jvdelisle
Date: Thu Apr 13 06:30:04 2006
New Revision: 112915

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=112915
Log:
2006-04-12  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/26766
	* gfortran.dg/write_recursive.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/write_recursive.f90
Modified:
    trunk/gcc/testsuite/ChangeLog

Comment 7 Jerry DeLisle 2006-04-17 04:31:23 UTC
Subject: Bug 26766

Author: jvdelisle
Date: Mon Apr 17 04:31:18 2006
New Revision: 113002

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113002
Log:
2006-04-16  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/26766
	* io/io.h: Add bit to identify associated unit as internal.
	* io/unit.c (get_external_unit): Renamed the find_unit_1 function to
	reflect the external unit functionality vs internal unit.
	(get_internal_unit): New function to allocate and initialize an internal
	unit structure.
	(get_unit): Use get_internal_unit and get_external_unit.
	(is_internal_unit): Revised to use new bit added in io.h.
	* io/transfer.c (data_transfer_init): Fix line width.
	(st_read_done): Free memory allocated for internal unit.
	(st_write_done): Add test to only flush and truncate when not an
	internal unit.  Free memory allocated for internal unit.

Modified:
    branches/gcc-4_1-branch/libgfortran/ChangeLog
    branches/gcc-4_1-branch/libgfortran/io/io.h
    branches/gcc-4_1-branch/libgfortran/io/transfer.c
    branches/gcc-4_1-branch/libgfortran/io/unit.c

Comment 8 Jerry DeLisle 2006-04-17 04:34:05 UTC
Subject: Bug 26766

Author: jvdelisle
Date: Mon Apr 17 04:33:59 2006
New Revision: 113003

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113003
Log:
2006-04-16  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/26766
	* gfortran.dg/write_recursive.f90: New test.

Added:
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/write_recursive.f90
Modified:
    branches/gcc-4_1-branch/gcc/testsuite/ChangeLog

Comment 9 Jerry DeLisle 2006-04-17 04:38:03 UTC
Fixed on 4.1 and trunk