This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Committed] PR fortran/54072 -- More fun with BOZ


On Thu, Aug 08, 2019 at 10:11:39AM +0100, Mark Eggleston wrote:
> 
> >> Comparisons with BOZ constants was allowed using 9.1 with
> >> -Wconversion-extra:
> >>
> >>       5 |         if (i4 .eq. z'1000') then
> >>         |            1
> >> Warning: Conversion from INTEGER(4) to INTEGER(16) at (1)
> >> [-Wconversion-extra]
> > This is the old behavior were a BOZ upon parsing is
> > immediately converted to an INTEGER with the widest decimal
> > range.  It is a holdover from when I made BOZ work in
> > accordance with the Fortran 95 standard, where a BOZ is
> > only allowed as a data-stmt-constant.  On your target, that
> > is INTEGER(16).  Because of that conversion, a BOZ could
> > be used anywhere an INTEGER can be used.
> 
> Other invalid BOZ usage is enable with -fallow-invalid-box, why not this?
> 
> This is from a test suite for a customer to check that gfortran supports 
> various legacy features. This feature is supported by all the compilers 
> they use including gfortran up to 9.1. This change will break legacy 
> code.

Because, I choose not to support invalid code.  One would need
to add a bunch of code to expr.c(simplify_intrinsic_op) to 
detect the BOZ usage and report an error or warning and then
do some conversion.  What does one do with

  if (z'12' .eq. z'4312')

Is this a hard error because both operands are BOZ?
Do you truncate the rhs operand or pad the lhs operand?
Do you simply convert these to INTEGER(16) and let the
compiler generate 128-bit integer code?

For the case

  if (i .eq. z'1234')  ! assuming i is integer

A conversion of the BOZ to the type and kind type of 'i' is possible.
Do we restrict the conversion to only rational operators?
Do we restrict the conversion to only integer comparisons?

What should this code do?

x = 4 * atan(1.) + 1
if (x .ge. z'40490FDB') print* , x
end

with gfortran 9, when compiled and executed it does not
produce output.

Should z'40490FDB' be converted to the type and kind of x?
In that case, gfortran-trunk would print out 4.14159...,
which is incompatiable with previous gfortran 9 and older. 
 
What should be done with unary operators?

i = - z'1234'  ! Assume i is integer.

The evaluation of the rhs is done first, and then assigned
to 'i' where possible conversion is done.

> Of course the best solution is to update their code i.e:
> 
> if (i4 .eq. int(z'1000',4)) then
> 
> I'll check whether the old behaviour is still required.

Yes, fixing the code would be preferred.

> >> Using trunk  with -fallow-invalid-boz comparison is not allowed:
> >>
> >>       5 |         if (i4 .eq. z'1000') then
> >>         |            1
> >> Error: Operands of comparison operator '.eq.' at (1) are INTEGER(4)/BOZ
> >>
> >> I would have expected a suitable warning about using the BOZ in an
> >> inappropriate place.
> > A BOZ cannot be an operand to a binary operator.
> >
> > Consider
> >
> > x = 1.0 + z'40490fdb'   ! Is this 4.14159.... or 1.07853005E+09
> >
> > y = z'40490fdb' + z'40490fbd' + 1. ! Is this 2*pi+1 or 2.15...E+09.
> >
> > Note, gfortran does left-to-right evaluation, but Fortran standard
> > does not require this ordering.  For 'x' it is possible to convert
> > op2 to the type of op1, which would give 4.1415....  That behavior
> > is different in comparison to the historical accident of 1.08E9.
> > For 'y', there is no valid conversion of op1 into op2.  In older
> > versions, the first addition is of 2 INTEGER(16).  The second
> > addition converts a INTEGER(16) to a REAL(4) and then adds.
> >
> >> DATA statements for logical and character variable compile but do not work:
> >>
> >> program test
> >>     character(4) :: c
> >>     data c / z'41424344' /
> >>     write(*, *) "'" // c // "'", transfer(c, 0_4)
> >> end program test
> >>
> >> Outputs:
> >>
> >>    ''           0
> >>
> >> program test
> >>     logical(4) b / z'00000001' /
> >>     write(*, *) b
> >> end program test
> >>
> >> Outputs:
> >>
> >>    F
> >  From the current Fortran working documenti, page 111:
> >
> >     If a data-stmt-constant is a boz-literal-constant, the corresponding
> >     variable shall be of type integer.  The boz-literal-constant is
> >     treated as if it were converted by the intrinsic function INT(16.9.100)
> >     to type integer with the kind type parameter of the variable.
> do have a link for the current workinng documentation it'll be useful.
> >
> > For the second program, I get
> >
> > gfcx -o z a.f90 && ./z
> > a.f90:8:26:
> >
> >      8 | logical(4) b / z'00000001' /
> >        |                          1
> > Error: BOZ at (1) cannot appear in an old-style initialization
> >
> > which to me is acceptable.
> 
> whoops, I added the wrong program, it should have had a DATA statement 
> in it...
> 
> program test
>     logical(4) b
>     data b / z'00000001' /
>     write(*, *) b
> end program test

Thanks,  I take a look at this.  It should be rejected.

-- 
Steve


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]