diff mbox

[Fortran] PR61933 Inquire on Internal Units

Message ID 54BC91C0.7060700@charter.net
State New
Headers show

Commit Message

Jerry DeLisle Jan. 19, 2015, 5:10 a.m. UTC
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  <jvdelisle@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  <jvdelisle@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.

Comments

Jerry DeLisle Jan. 20, 2015, 2:32 a.m. UTC | #1
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  <jvdelisle@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  <jvdelisle@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.
Tobias Burnus Jan. 20, 2015, 7:29 a.m. UTC | #2
Hi Jerry, hi all,

sorry for the slow patch review. I also still want to review your other 
inquire patch.

Jerry DeLisle wrote:
> 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.
>

> Regression tested on x86-64 and Joost's case in the PR now works as 
> expected.
> OK for trunk?

Mostly OK, however, some remarks are below.

> 2015-01-18  Jerry DeLisle <jvdelisle@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 <jvdelisle@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.
[...]
> +  /* The unit number -2 is reserved.  No units can ever have this
> +     value.  It is used here to signal to the runtime library that the
> +     inquire unit number is outside the allowable range and so cannot
> +     exist.  It is needed when -fdefault-integer-8 is uesed.  */

I don't know where this number is used, but I really should be a 
#define; if it is shared with libgfortran, it belongs to libgfortran.h. 
You wrote that -1 is also reserved and used; is the -1 somewhere 
defined? [Disclaimer: I have only browsed the other patch and do not 
recall whether it add, handles or #defines -1 - or whether -1 is already 
defined somewhere.]

> +      /* UNIT numbers should be greater than zero.  */
> +      i = gfc_validate_kind (BT_INTEGER, 4, false);
> +      cond = build2_loc (input_location, LT_EXPR, boolean_type_node,
> +			      se.expr,
> +			      fold_convert (TREE_TYPE (se.expr),
> +			      integer_zero_node));
> +      gfc_trans_io_inquire_check (cond, var, &se.pre);
> +
> +      /* UNIT numbers should be less than the max.  */
> +      val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
> +      cond = build2_loc (input_location, GT_EXPR, boolean_type_node,
> +			      se.expr,
> +			      fold_convert (TREE_TYPE (se.expr), val));
> +      gfc_trans_io_inquire_check (cond, var, &se.pre);

The conditions could be combined with a 
fold_build2_loc(...,TRUTH_AND_EXPR,...).

Thanks for the patch!

Cheers,

Tobias
diff mbox

Patch

Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c	(revision 219703)
+++ gcc/fortran/trans-io.c	(working copy)
@@ -512,7 +512,37 @@  set_parameter_const (stmtblock_t *block, tree var,
    st_parameter_XXX structure.  This is a pass by value.  */
 
 static unsigned int
-set_parameter_value (stmtblock_t *block, bool has_iostat, tree var,
+set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
+		     gfc_expr *e)
+{
+  gfc_se se;
+  tree tmp;
+  gfc_st_parameter_field *p = &st_parameter_field[type];
+  tree dest_type = TREE_TYPE (p->field);
+
+  gfc_init_se (&se, NULL);
+  gfc_conv_expr_val (&se, e);
+
+  se.expr = convert (dest_type, se.expr);
+  gfc_add_block_to_block (block, &se.pre);
+
+  if (p->param_type == IOPARM_ptype_common)
+    var = fold_build3_loc (input_location, COMPONENT_REF,
+			   st_parameter[IOPARM_ptype_common].type,
+			   var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
+
+  tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
+			 p->field, NULL_TREE);
+  gfc_add_modify (block, tmp, se.expr);
+  return p->mask;
+}
+
+
+/* Similar to set_parameter_value except generate runtime
+   error checks.  */
+
+static unsigned int
+set_parameter_value_chk (stmtblock_t *block, bool has_iostat, tree var,
 		     enum iofield type, gfc_expr *e)
 {
   gfc_se se;
@@ -550,7 +580,6 @@  static unsigned int
       gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT,
 				  "Unit number in I/O statement too large",
 				  &se.pre);
-
     }
 
   se.expr = convert (dest_type, se.expr);
@@ -568,6 +597,78 @@  static unsigned int
 }
 
 
+/* Set the unit number in the inquire parameter block to -2.  */
+
+static void
+gfc_trans_io_inquire_check (tree cond, tree var, stmtblock_t * pblock)
+{
+  stmtblock_t block;
+  tree body;
+
+  gfc_start_block (&block);
+
+  /* The unit number -2 is reserved.  No units can ever have this
+     value.  It is used here to signal to the runtime library that the
+     inquire unit number is outside the allowable range and so cannot
+     exist.  It is needed when -fdefault-integer-8 is uesed.  */
+
+  set_parameter_const (&block, var, IOPARM_common_unit, -2);
+
+  body = gfc_finish_block (&block);
+
+  var = build3_v (COND_EXPR, cond, body, build_empty_stmt (input_location));
+  gfc_add_expr_to_block (pblock, var);
+}
+
+
+/* Build code to check the unit range if KIND=8 is used.  Similar to
+   set_parameter_value_chk but we do not generate error calls for
+   inquire statements.  */
+
+static unsigned int
+set_parameter_value_inquire (stmtblock_t *block, tree var,
+			     enum iofield type, gfc_expr *e)
+{
+  gfc_se se;
+  gfc_st_parameter_field *p = &st_parameter_field[type];
+  tree dest_type = TREE_TYPE (p->field);
+
+  gfc_init_se (&se, NULL);
+  gfc_conv_expr_val (&se, e);
+
+  /* If we're inquiring on a UNIT number, we need to check to make
+     sure it exists for larger than kind = 4.  */
+  if (type == IOPARM_common_unit && e->ts.kind > 4)
+    {
+      tree cond, val;
+      int i;
+
+      /* Don't evaluate the UNIT number multiple times.  */
+      se.expr = gfc_evaluate_now (se.expr, &se.pre);
+
+      /* UNIT numbers should be greater than zero.  */
+      i = gfc_validate_kind (BT_INTEGER, 4, false);
+      cond = build2_loc (input_location, LT_EXPR, boolean_type_node,
+			      se.expr,
+			      fold_convert (TREE_TYPE (se.expr),
+			      integer_zero_node));
+      gfc_trans_io_inquire_check (cond, var, &se.pre);
+
+      /* UNIT numbers should be less than the max.  */
+      val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
+      cond = build2_loc (input_location, GT_EXPR, boolean_type_node,
+			      se.expr,
+			      fold_convert (TREE_TYPE (se.expr), val));
+      gfc_trans_io_inquire_check (cond, var, &se.pre);
+    }
+
+  se.expr = convert (dest_type, se.expr);
+  gfc_add_block_to_block (block, &se.pre);
+
+  return p->mask;
+}
+
+
 /* Generate code to store a non-string I/O parameter into the
    st_parameter_XXX structure.  This is pass by reference.  */
 
@@ -978,7 +1079,7 @@  gfc_trans_open (gfc_code * code)
     mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
 
   if (p->recl)
-    mask |= set_parameter_value (&block, p->iostat, var, IOPARM_open_recl_in,
+    mask |= set_parameter_value (&block, var, IOPARM_open_recl_in,
 				 p->recl);
 
   if (p->blank)
@@ -1029,7 +1130,7 @@  gfc_trans_open (gfc_code * code)
   set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
   if (p->unit)
-    set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit);
+    set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
   else
     set_parameter_const (&block, var, IOPARM_common_unit, 0);
 
@@ -1082,7 +1183,7 @@  gfc_trans_close (gfc_code * code)
   set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
   if (p->unit)
-    set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit);
+    set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
   else
     set_parameter_const (&block, var, IOPARM_common_unit, 0);
 
@@ -1124,8 +1225,8 @@  build_filepos (tree function, gfc_code * code)
 			p->iomsg);
 
   if (p->iostat)
-    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
-			       p->iostat);
+    mask |= set_parameter_ref (&block, &post_block, var,
+			       IOPARM_common_iostat, p->iostat);
 
   if (p->err)
     mask |= IOPARM_common_err;
@@ -1133,7 +1234,8 @@  build_filepos (tree function, gfc_code * code)
   set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
   if (p->unit)
-    set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit);
+    set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit,
+			     p->unit);
   else
     set_parameter_const (&block, var, IOPARM_common_unit, 0);
 
@@ -1225,10 +1327,8 @@  gfc_trans_inquire (gfc_code * code)
 			p->file);
 
   if (p->exist)
-    {
-      mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
+    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
 				 p->exist);
-    }
 
   if (p->opened)
     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
@@ -1360,7 +1460,10 @@  gfc_trans_inquire (gfc_code * code)
   set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
   if (p->unit)
-    set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit);
+    {
+      set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
+      set_parameter_value_inquire (&block, var, IOPARM_common_unit, p->unit);
+    }
   else
     set_parameter_const (&block, var, IOPARM_common_unit, 0);
 
@@ -1407,12 +1510,12 @@  gfc_trans_wait (gfc_code * code)
     mask |= IOPARM_common_err;
 
   if (p->id)
-    mask |= set_parameter_value (&block, p->iostat, var, IOPARM_wait_id, p->id);
+    mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id);
 
   set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
   if (p->unit)
-    set_parameter_value (&block, p->iostat, var, IOPARM_common_unit, p->unit);
+    set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
 
   tmp = gfc_build_addr_expr (NULL_TREE, var);
   tmp = build_call_expr_loc (input_location,
@@ -1706,12 +1809,11 @@  build_dt (tree function, gfc_code * code)
 				   IOPARM_dt_id, dt->id);
 
       if (dt->pos)
-	mask |= set_parameter_value (&block, dt->iostat, var, IOPARM_dt_pos,
-				     dt->pos);
+	mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos);
 
       if (dt->asynchronous)
-	mask |= set_string (&block, &post_block, var, IOPARM_dt_asynchronous,
-			    dt->asynchronous);
+	mask |= set_string (&block, &post_block, var,
+			    IOPARM_dt_asynchronous, dt->asynchronous);
 
       if (dt->blank)
 	mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
@@ -1738,8 +1840,7 @@  build_dt (tree function, gfc_code * code)
 			    dt->sign);
 
       if (dt->rec)
-	mask |= set_parameter_value (&block, dt->iostat, var, IOPARM_dt_rec,
-				     dt->rec);
+	mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
 
       if (dt->advance)
 	mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
@@ -1791,8 +1892,8 @@  build_dt (tree function, gfc_code * code)
 	set_parameter_const (&block, var, IOPARM_common_flags, mask);
 
       if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
-	set_parameter_value (&block, dt->iostat, var, IOPARM_common_unit,
-			     dt->io_unit);
+	set_parameter_value_chk (&block, dt->iostat, var,
+				 IOPARM_common_unit, dt->io_unit);
     }
   else
     set_parameter_const (&block, var, IOPARM_common_flags, mask);
Index: gcc/testsuite/gfortran.dg/negative_unit_int8.f
===================================================================
--- gcc/testsuite/gfortran.dg/negative_unit_int8.f	(revision 219703)
+++ gcc/testsuite/gfortran.dg/negative_unit_int8.f	(working copy)
@@ -30,6 +30,6 @@ 
 ! This one is nasty
       inquire (unit=i, exist=l, iostat=i)
       if (l) call abort
-      if (i.ne.ERROR_BAD_UNIT) call abort
+      if (i.ne.0) call abort
 
       end
Index: libgfortran/io/inquire.c
===================================================================
--- libgfortran/io/inquire.c	(revision 219703)
+++ libgfortran/io/inquire.c	(working copy)
@@ -45,7 +45,8 @@  inquire_via_unit (st_parameter_inquire *iqp, gfc_u
     generate_error (&iqp->common, LIBERROR_INQUIRE_INTERNAL_UNIT, NULL);
 
   if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
-    *iqp->exist = (u != NULL);
+    *iqp->exist = (u != NULL) || (iqp->common.unit >= 0 	 
+		   && iqp->common.unit <= GFC_INTEGER_4_HUGE);
 
   if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
     *iqp->opened = (u != NULL);