On 07/23/2012 11:48 AM, Nasser M. Abbasi wrote
> It was using BOZ literals like this
>
> ----------------
> IMPLICIT NONE
> INTEGER, PARAMETER :: GL_CURRENT_BIT = z'00000001' ! 0x00000001
> END
> ---------------
>
> Which causes problem:
>
> gfortran -std=f2008 -c problem2.f90
> Error: Extension: BOZ literal at (1) outside a DATA statement and
> outside INT/REAL/DBLE/CMPLX
Yes, the "= z'00000001'" is a (common) vendor extension. However, the
error message is not fully correct as Fortran (at least Fortran 2008)
allows BOZ literals also at a few other intrinsics, e.g. to IAND, DBLE
or DSHIFTR.
> But since I used global substitution, it changed one place in the code
> where BOZ was used in a TRANSFER, like this:
>
> ---------------------
> USE, INTRINSIC :: ISO_C_BINDING
> IMPLICIT NONE
> INTEGER, PARAMETER :: GLbitfield=C_INT
> INTEGER(GLbitfield), PARAMETER :: GL_CURRENT_BIT = INT(z'00000001') !
> 0x00000001
> INTEGER(GLbitfield), PARAMETER :: GL_CLIENT_ALL_ATTRIB_BITS = &
> transfer(INT(z'ffffffff'),GL_CURRENT_BIT) ! 0xffffffff
> END
> ---------------------
The problem is that z'FFFFFFFF' doesn't match the bit pattern of a
positive integer of default kind. The standard states:
"If A is a boz-literal-constant, the value of the result is the value
whose bit sequence according to the model in 13.3 is the same as that of
A as modified by padding or truncation according to 13.3.3. The
interpretation of a bit sequence whose most significant bit is 1 is
processor dependent."
Here, gfortran doesn't know whether the overflow to negative values is
on purpose or accidental. As the error message states
Error: Arithmetic overflow converting INTEGER(8) to INTEGER(4) at (1).
This check can be disabled with the option -fno-range-check
you can simply use -fno-range-check to silence this error. One can argue
whether gfortran should print an error or not, but given that it shows
the flag to use, I think the current way can be accepted.
I am not sure that the error message is best suited for Fortran 2008,
but it makes sense for Fortran 95, where the BOZ matched the largest
supported integer values:
"If a data-statement-constant is a boz-literal-constant, the
corresponding object shall be of type integer. A data-stmt-constant that
is a boz-literal-constant is treated as if the constant were an
int-literalconstant with a kind-param that specifies the representation
method with the largest decimal exponent range supported by the processor."
By contrast, Fortran 2008 has (for DATA):
"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 (13.7.81) to type
integer with the kind type parameter of the variable.
As long as the bit pattern fits into a positive number of the integer
kind, everything is fine. The trouble only starts when it doesn't.
> So, I thought I need to find out what to use in place on INT, like
> LONG_INT?
Well, you can use INT(z'FFFFFFFF',kind=int64), however, you have to be
careful whether that leads the bitpattern, which you want
[INT(z'FFFFFFFF') is "-1", i.e. all bit set to one in an INT32
variable]. (Well, in practice is should be on most platforms.)
Thus, you should really consider to use INT and the flag -fno-range-check.
> When I removed the INT casting from the BOZ inside the TRANSFER, now
> it compiled ok. No warning about Arithmetic overflow and BOZ literal
> was allowed in this case.
Unless, I misread the standard, I believe it is just a bug in gfortran
that it does not print an error in that case. If some construct is
supported (for a newer standard or as vendor extension), it is
nontrivial to make sure that the compiler rejected it at all places
where it shouldn't be supported according the standard (or an older
version of the standard).
As only Fortran 2003 started to support BOZ in other places than for
integers in DATA, many compilers support BOZ at other places. It gets
rather hairy if BOZ are used for nonintegers, e.g.
real :: r = z'FFFFFFFF'
Should the bitpattern FFFFFFFF be assigned to "r"? Or should the BOZ be
regarded as integer - and then the integer be assigned? What if one has
r = z'FFFFFFFF' + 1
or
r = z'FFFFFFFF' + 1.0
I think that's rather muddy and should be avoided in favor of using
Fortran 2003/2008's INT/REAL/CMPLX.
In case of gfortran's vendor extension, BOZ are interpreted as listed at
+
I have now filled a gfortran bugreport to track the failing diagnosis
for TRANSFER:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54072
Tobias