ping

This PR has been marked as a regression, so I suppose we ought to get it fixed.

On 01/18/2015 09:10 PM, Jerry DeLisle wrote:
I reopened this PR to do some cleanup and to address a use case presented by
Joost in comment #7 of the subject PR.

The fundamental problem: if the variable containing the unit number in an
INQUIRE statement is of type KIND greater than 4 and the value is outside the
range of a KIND=4 we cannot test for it within the run-time library.  Unit
numbers are passed to the run-time in the IOPARM structures as a KIND=4. KIND=8
are cast into the KIND=4.  The test case gfortran.dg/negative_unit_int8.f
illustrates a case where a bogus unit number can get passed to the library.

To resolve this previously we built range checks in trans_io.c
(set_parameter_value) that tests the unit numbers and issues an error call to
the run-time library.  This is fine for all statements except INQUIRE which
should not give an error. However, we do want to identify such an out-of-range
unit number as not existing.

This patch changes this by renaming the previous set_parameter_value to
set_parameter_value_chk.  I then created a new version of set_parameter_value
that does no checking so that it can be used where generating errors is not
needed.  I have created two new functions which build code that tests for the
out of range cases specific to INQUIRE.  If a bad unit number is found, the UNIT
value in the IOPARM structure is set to -2, a new reserved value. (after this
patch we will have reserved values -3 thru -9 still available for future uses)

The definition of unit existence is adjusted to be any negative unit currently
connected having been created with NEWUNIT and all KIND=4 positive values.  A -2
indicating an invalid unit will, by default, return EXISTS=false.

The behind the scenes testing is never seen in user space as shown here with an
-fdump-tree-original example from the negative_unit_int8.f .

For non-INQUIRE cases:

     D.3384 = i;
     if (D.3384 < -2147483647)
       {
         _gfortran_generate_error (&dt_parm.0, 5005, &"Unit number in I/O
statement too small"
     [1]{lb: 1 sz: 1});
       }
     if (D.3384 > 2147483647)
       {
         _gfortran_generate_error (&dt_parm.0, 5005, &"Unit number in I/O
statement too large"
     [1]{lb: 1 sz: 1});
       }
     dt_parm.0.common.unit = (integer(kind=4)) D.3384;

For the new INQUIRE case:

     integer(kind=8) i;

--- snip ---

     inquire_parm.4.common.unit = (integer(kind=4)) i;<---notice the conversion
to kind=4 here
     D.3393 = i;
     if (D.3393 < 0)
       {
         inquire_parm.4.common.unit = -2;
       }
     if (D.3393 > 2147483647)
       {
         inquire_parm.4.common.unit = -2;
       }

When all is acceptable, common.unit is untouched and the normal assignment has
happened.  The users variable, in this case i, is untouched as well because of
the temporary D.3393.  The IOPARM stucture is also temporary and not used again.

The patch updates the test case mentioned above.

Regression tested on x86-64 and Joost's case in the PR now works as expected.

OK for trunk?

Regards,

Jerry


2015-01-18  Jerry DeLisle  <jvdeli...@gcc.gnu.org>

     PR fortran/61933
     * trans-io.c (set_parameter_value): Delete use of has_iostat.
     Redefine to not generate any runtime error check calls.
     (set_parameter_value_chk): Rename of the former
     set_parameter_value with the runtimr error checks and fix
     whitespace. (gfc_trans_io_inquire_check): New function that
     builds a runtime conditional block to set the INQUIRE
     common parameter block unit number to -2 when unit numbers
     exceed positive KIND=4 limits. (set_parameter_value_inquire):
     New function that builds the conditional expressions and calls
     gfc_trans_io_inquire_check. (gfc_trans_open): Whitespace.  For
     unit, use the renamed set_parameter_value_chk.
     (gfc_trans_close): Likewise use renamed function.
     (build_filepos): Whitespace and use renamed function.
     (gfc_trans_inquire): Whitespace and for unit use
     set_parameter_value and set_parameter_value_inquire.
     (gfc_trans_wait): Remove p->iostat from call to
     set_parameter_value. Use new set_parameter_value_chk for unit.
     (build_dt): Use the new set_parameter_value without p->iostat
     and fix whitespace. Use set_parameter_value_chk for unit.

2015-01-18  Jerry DeLisle  <jvdeli...@gcc.gnu.org>

     PR libgfortran/61933
     * io/inquire.c (inquire_via_unit): Set existing to true for
     any negative unit that is currently connected and any positive
     units within range of KIND=4 value.  The unit value for any out
     of range case that may occur if the user is using a KIND=8 will
     have been set to -2 which is reserved and can never be opened,
     and therefore the unit does not exist.

Reply via email to