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.