[PATCH,Fortran] -- Tidy up the BOZ rewrite

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH,Fortran] -- Tidy up the BOZ rewrite

Steve Kargl
The attach patch has been regression tested on x86_64-*-freebsd.

It does a number of things.

1) It tightens the adherence to F2018 Fortran standard.  For example,
   this program and execute with gfortran 9 and older.

   program foo
   integer i
   data i/z'40490adf'/         ! Explicit declaration
   data j/z'40490adf'/         ! Implicit typing
   integer :: k = z'40490adf'  ! Invalid F2018
   integer l /z'40490adf'/     ! Old-style initialization.  Invalid F2018.
   print *, i, j, k, l
   end program foo

% gfc9 -o z a.f90 && ./z
  1078528735  1078528735  1078528735  1078528735

With trunk, the lines marked as "Invalid F2018" will invoke error
messages.  The errors can be downgraded to warnings with the
-fallow-invalid-boz.

% gfcx -fallow-invalid-boz -o z a.f90 && ./z
a.f90:5:16:

    5 |   integer :: k = z'40490adf' ! Invalid F2018
      |                1
Warning: BOZ literal constant at (1) is neither a data-stmt-constant nor
an actual argument to INT, REAL, DBLE, or CMPLX intrinsic function
a.f90:6:24:

    6 |   integer l /z'40490adf'/    ! Old-style initialization. Invalid F2018.
      |                        1
Warning: BOZ at (1) cannot appear in an old-style initialization
  1078528735  1078528735  1078528735  1078528735

2) Mark Eggleston point out the that following invalid code would compile
   with my original patch while older versions of gfortran rejected the
   code.

   program foo
   character(4) i
   data i /z'40490adf'/
   logical j
   data j /z'40490adf'/
   print *, i, j
   end program foo

  This code now generates

% gfcx -c z a.f90
a.f90:5:21:

    5 |   data j /z'40490adf'/
      |                     1
Error: BOZ literal constant near (1) cannot be assigned to
a 'LOGICAL(4)' variable
a.f90:3:21:

    3 |   data i /z'40490adf'/
      |                     1
Error: BOZ literal constant near (1) cannot be assigned to
a 'CHARACTER(1)' variable

3) Mark also asked about allowing a BOZ in a rational expression.
   In particular, he has/had code with statements of the form
   "if (i < z'12334') then".  Under F2018, a BOZ cannot appear
   as an operand in an expression.  My original patch issued
   an error.

   This patch disallows a BOZ as an oprand to an unary operator.
   It disallows both operand of a binary operator to be BOZ.  If
   one operand is a BOZ, it is converted to the type and kind of
   the other operand.  Note, everthing is guarded with gfc_invalid_boz.
   For example,

   program foo
   integer i
   i = 42
   if (i < z'40490adf') print *, i
   end program foo

% gfcx -o z a.f90 && ./z
a.f90:4:9:

    4 |   if (i < z'40490adf') print *, i
      |         1
Error: BOZ literal constant near (1) cannot appear as an operand
of a rational operator
% gfcx -fallow-invalid-boz -o z a.f90 && ./z
a.f90:4:9:

    4 |   if (i < z'40490adf') print *, i
      |         1
Warning: BOZ literal constant near (1) cannot appear as an operand
of a rational operator
          42

OK to commit?

2019-08-08  Steven G. Kargl  <[hidden email]>

        * decl.c (match_old_style_init): Use a clearer error message.
        * expr.c (gfc_check_assign): Update BOZ checking to provide a stricter
        adherence to the Fortran standard.  Use gfc_invalid_boz () to
        relax errors into warnings.
        * gfortran.h (gfc_isym_id): Add new ids GFC_ISYM_DFLOAT,
        GFC_ISYM_FLOAT, GFC_ISYM_REALPART, and GFC_ISYM_SNGL
        * intrinsic.c (add_functions): Use new ids to split REAL generic into
        REAL, FLOAT, DFLOAT, SNGL, and REALPART generics.
        (gfc_intrinsic_func_interface): Allow new intrinsics in an
        initialization expression
        * resolve.c (resolve_operator): Deal with BOZ as operands.
        Use gfc_invalid_boz to allow for errors or warnings via the
        -fallow-invalid-boz option.  A BOZ cannot be an operand to an
        unary operator.  Both operands of a binary operator cannot be BOZ.
        For binary operators, convert a BOZ operand into the type and
        kind of the other operand for REAL or INTEGER operand.
        * trans-intrinsic.c: Use new ids to cause conversions to happen.

2019-08-08  Steven G. Kargl  <[hidden email]>

        * gfortran.dg/boz_8.f90: Adjust error messages.
        * gfortran.dg/nan_4.f90: Ditto.
        * gfortran.dg/boz_1.f90: Add -fallow-invalid-boz to dg-options,
        and test for warnings.
        * gfortran.dg/boz_3.f90: Ditto.
        * gfortran.dg/boz_4.f90: Ditto.
        * gfortran.dg/dec_structure_6.f90: Ditto.
        * gfortran.dg/ibits.f90: Ditto.

--
Steve

son_of_boz.diff (18K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Thomas König

Steve,
> Error: BOZ literal constant near (1) cannot appear as an operand
> of a rational operator
> % gfcx -fallow-invalid-boz -o z a.f90 && ./z
> a.f90:4:9:

I don‘t have time right now to look at this in detail, just one nit:
>    4 |   if (i < z'40490adf') print *, i
>      |         1
> Warning: BOZ literal constant near (1) cannot appear as an operand
> of a rational operator

Should this be „relational“ or „comparison“, maybe?

Regards

Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Mark Eggleston
In reply to this post by Steve Kargl
Steve,

In gcc/fortran/resolve.c

@@ -3939,6 +3947,16 @@ resolve_operator (gfc_expr *e)
    op2 = e->value.op.op2;
    dual_locus_error = false;
 
+  /* op1 and op2 cannot both be BOZ.  */
+  if (op1 && op1->ts.type == BT_BOZ
+      && op2 && op2->ts.type == BT_BOZ)
+    {
+      gfc_error ("Operands at %L and %L cannot appears as operands of "
+ "binary operator %qs", &op1->where, &op2->where,
+ gfc_op2string (e->value.op.op));
+      return false;
+    }
+
    if ((op1 && op1->expr_type == EXPR_NULL)
        || (op2 && op2->expr_type == EXPR_NULL))
      {


The error message should be:

+      gfc_error ("Operands at %L and %L cannot appear as operands of "
+ "binary operator %qs", &op1->where, &op2->where,
+ gfc_op2string (e->value.op.op));

i.e. appear instead of appears

regards,
Mark
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Mark Eggleston
In reply to this post by Steve Kargl
Steve,

In gcc/fortran/resolve.c

@@ -3939,6 +3947,16 @@ resolve_operator (gfc_expr *e)
    op2 = e->value.op.op2;
    dual_locus_error = false;

+  /* op1 and op2 cannot both be BOZ.  */
+  if (op1 && op1->ts.type == BT_BOZ
+      && op2 && op2->ts.type == BT_BOZ)
+    {
+      gfc_error ("Operands at %L and %L cannot appears as operands of "
+         "binary operator %qs", &op1->where, &op2->where,
+         gfc_op2string (e->value.op.op));
+      return false;
+    }
+
    if ((op1 && op1->expr_type == EXPR_NULL)
        || (op2 && op2->expr_type == EXPR_NULL))
      {


The error message should be:

+      gfc_error ("Operands at %L and %L cannot appear as operands of "
+         "binary operator %qs", &op1->where, &op2->where,
+         gfc_op2string (e->value.op.op));

i.e. appear instead of appears

regards,
Mark

--

https://www.codethink.co.uk/privacy.html

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Steve Kargl
In reply to this post by Thomas König
On Fri, Aug 09, 2019 at 07:48:23AM +0200, Thomas König wrote:

>
> Steve,
> > Error: BOZ literal constant near (1) cannot appear as an operand
> > of a rational operator
> > % gfcx -fallow-invalid-boz -o z a.f90 && ./z
> > a.f90:4:9:
>
> I don‘t have time right now to look at this in detail, just one nit:
> >    4 |   if (i < z'40490adf') print *, i
> >      |         1
> > Warning: BOZ literal constant near (1) cannot appear as an operand
> > of a rational operator
>
> Should this be „relational“ or „comparison“, maybe?
>

It's rational.  From 18-007r1.pdf

10.1.5.5 Relational intrinsic operations
10.1.5.5.1 Interpretation of relational intrinsic operations

--
Steve
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Steve Kargl
In reply to this post by Mark Eggleston
On Fri, Aug 09, 2019 at 11:17:34AM +0100, Mark Eggleston wrote:
>
> The error message should be:
>
> +      gfc_error ("Operands at %L and %L cannot appear as operands of "
> +         "binary operator %qs", &op1->where, &op2->where,
> +         gfc_op2string (e->value.op.op));
>

Thanks.  I think I caught those yesterday as I reduced
the diff into the ChangeLog entry, but I'll check again.

--
Steve
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Thomas Koenig-6
In reply to this post by Steve Kargl
Hi Steve,

> OK to commit?

OK with

%s/rational/relational/g

and with Mark's nit.

Thanks a lot for going down that road.  I like the approach of
-fallow-invalid-boz to downgrade the error to a warning, which
then cannot be turned off.

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Steve Kargl
On Sat, Aug 10, 2019 at 07:29:10PM +0200, Thomas Koenig wrote:

> Hi Steve,
>
> > OK to commit?
>
> OK with
>
> %s/rational/relational/g
>
> and with Mark's nit.
>
> Thanks a lot for going down that road.  I like the approach of
> -fallow-invalid-boz to downgrade the error to a warning, which
> then cannot be turned off.
>

Thanks, I'll double check spelling.  Not one of my stronger abilitie.

You can turn off the warning with -w, but that turns off
all warnings. :-)  I suspect we'll get a PR or two to
provide an option to turn off the warning.

I think part of the rework that others will appreciate is
one no longer needs to use -fno-range-check.

--
Steve
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Manfred Schwarb
In reply to this post by Steve Kargl
Steve,

Am 09.08.19 um 01:10 schrieb Steve Kargl:

> The attach patch has been regression tested on x86_64-*-freebsd.
>
> It does a number of things.
>
> 1) It tightens the adherence to F2018 Fortran standard.  For example,
>    this program and execute with gfortran 9 and older.
>
>    program foo
>    integer i
>    data i/z'40490adf'/         ! Explicit declaration
>    data j/z'40490adf'/         ! Implicit typing
>    integer :: k = z'40490adf'  ! Invalid F2018
>    integer l /z'40490adf'/     ! Old-style initialization.  Invalid F2018.
>    print *, i, j, k, l
>    end program foo
>

Thanks for doing this.
Documentation seems not yet to be adapted, though:

>   Furthermore, GNU Fortran allows using BOZ literal constants outside
>DATA statements and the four intrinsic functions allowed by Fortran
>2003.  In DATA statements, in direct assignments, where the right-hand
>side only contains a BOZ literal constant, and for old-style
>initializers of the form 'integer i /o'0173'/', the constant is
>transferred as if 'TRANSFER' had been used; for 'COMPLEX' numbers, only
>the real part is initialized unless 'CMPLX' is used.  In all other
>cases, the BOZ literal constant is converted to an 'INTEGER' value with
>the largest decimal representation.  This value is then converted
>numerically to the type and kind of the variable in question.  (For
>instance, 'real :: r = b'0000001' + 1' initializes 'r' with '2.0'.)  As
>different compilers implement the extension differently, one should be
>careful when doing bitwise initialization of non-integer variables.

This whole paragraph seems to be wrong now and only valid for "-fallow-invalid-boz".

Further, I wonder whether it would be in order to give an hint to -fallow-invalid-boz
when spitting out error messages about invalid BOZ usage.
At the moment the user has no idea about the existence of this option.

Thanks,
Manfred
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH,Fortran] -- Tidy up the BOZ rewrite

Steve Kargl
On Sun, Sep 01, 2019 at 02:36:44PM +0200, Manfred Schwarb wrote:

> Steve,
>
> Am 09.08.19 um 01:10 schrieb Steve Kargl:
> > The attach patch has been regression tested on x86_64-*-freebsd.
> >
> > It does a number of things.
> >
> > 1) It tightens the adherence to F2018 Fortran standard.  For example,
> >    this program and execute with gfortran 9 and older.
> >
> >    program foo
> >    integer i
> >    data i/z'40490adf'/         ! Explicit declaration
> >    data j/z'40490adf'/         ! Implicit typing
> >    integer :: k = z'40490adf'  ! Invalid F2018
> >    integer l /z'40490adf'/     ! Old-style initialization.  Invalid F2018.
> >    print *, i, j, k, l
> >    end program foo
> >
>
> Thanks for doing this.
> Documentation seems not yet to be adapted, though:
>

See revision 275364.


Others (including lurkers on the the fortran@) can make any refinements
he or she wishes.

--
Steve