Invalid use of BOZ

Invalid use of BOZ

Consider the following example:

  PROGRAM tb 
  USE ISO_FORTRAN_ENV
!
  INTEGER(KIND=INT8) :: values(1:3)
!
  values = INT( [ z'11', z'22', z'33'] , KIND=INT8)  ! <<problem line
  write(*,*) values
!
  STOP
  END PROGRAM tb
!

The compiler complains with a warning "warning #6473: Fortran 2015 does not allow boz constant in this context. [Z'11']" similar for the others. The use of BOZ as an argument for the elemental INT function is allowed since Fortran 2003. Therefore, I do not see what I am doing wrong. Any idea? (Compiled with 18.0.0.24)

Robert

24 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I guess the array is constructed as a temp of default integer and then the INT function is applied. In that case the first step is not standard conforming use of BOZ.  The clumsier form below is OK.

        integer(8) :: values(3)
        values = [ int(z'11',8), int(z'22',8), int(z'33',8) ]

 

Gfortran 7.1.1 on Linux takes in the original program without complaints. The compiled program works fine.

First of all, you would have had to compile the program with standards checking on to see this warning. mecej4, did you do that for gfortran?

The use of BOZ constants in array constructors is NOT standard-conforming. Yes, you can have a boz-literal-constant as the argument to INT, but that's not what is being done here. The standard does not allow a BOZ constant to appear in an array constructor. Intel Fortran applies its own rules for what a BOZ constant means in this context.

Steve (aka "Doctor Fortran") - Retired from Intel

Quote:

Steve Lionel (Ret.) wrote:

.. The standard does not allow a BOZ constant to appear in an array constructor. ..

Steve,

As the next convenor of WG5 and given your connections with J3, can the Fortran community request you to follow up on this and have the next standard (tentatively called Fortran 2020 per your earlier communique) extend the meaning of BOZ literals in a manner that will allow its use in array constructors?

Meaning you and other committee members must have seen this matter brought up on this forum and elsewhere that the Fortran community world-wide should be able to hope the committee working on Fortran 2020 will be self-driving and know enough on how to proceed without requirng an explicit proposal and use case(s) e,g., an option can be to extend the meaning of BOZ literals to an explicit type-spec that can be included in an array constructor.

Or, is that the committee will still need a proposal and use case(s) and all that even for this and otherwise it will not get worked on?

Thanks,

Quote:

Steve Lionel (Ret.) wrote:

..you would have had to compile the program with standards checking on to see this warning..

 The standard does not allow a BOZ constant to appear in an array constructor.. 

Steve and anyone from Intel Fortran team and any gfortran developer volunteers who might be reading this:

Please consider the simple code below:

   use, intrinsic :: iso_fortran_env, only : int8, int16

   blk1: block

      integer(kind=int16) :: values(3)

      values = [ integer(kind=int16) :: z'80', z'81', z'82' ]

      print *, "values = ", values

   end block blk1

   blk2: block

      integer(kind=int8) :: values(3)

      values = [ integer(kind=int8) :: z'80', z'81', z'82' ]

      print *, "values = ", values

   end block blk2

   blk3: block

      integer(kind=int16) :: values(3)

      values = [ integer(kind=int8) :: z'80', z'81', z'82' ]

      print *, "values = ", values

   end block blk3

   blk4: block

      integer(kind=int8) :: values(3)

      values = [ integer(kind=int16) :: z'80', z'81', z'82' ]

      print *, "values = ", values

   end block blk4

end
  1. Steve, it will be most useful if the above code were to be standard-conforming once Fortran 2020 is published!  As you know, it is not at present - current standard does not allow the use of BOZ literals in array constructors unfortunately.
  2. gfortran team: with -std=... compiler option, no standard warning is issued with above code.  But kudos to you for providing error diagnostics with the arithmetic overflow.
  3. Intel Fortran team: with above code, Intel compiler issues the standard warning but no warnings about possible arithmetic overflow on lines 17, 27, and 37.  It will be very useful for coders if Intel Parallel Studio had an option somewhere, perhaps with Intel Inspector even if not with the Fortran compiler, where users can be alerted about the arithmetic overflow at least when the users request they be informed (e.g., when some option is turned on)

I would have difficulty supporting a proposal to extend use of BOZ constants into array constructors. When you specify a type-spec in the constructor, that says that each ac-value is converted to that type. Since BOZ constants, by themselves, have no type, conversion has no meaning.

You can already use INT (or the other allowed intrinsic functions) with BOZ constants for each ac-value, and this makes the meaning unambiguous. Yes, I know this is wordier, but how often does one actually need to do something like this? 

My view of this proposal is that it is "syntactic sugar" - another way of specifying something you can already do in the language. I'm generally not in favor of such. For F2020, we're trying to limit the new features and I can't see this one as being worth the time and resources.

Steve (aka "Doctor Fortran") - Retired from Intel

FortranFan,

Why do you presume line 17 ought to warn of integer overflow?

IMHO z'80' (or z'FF') are one byte (two nibble) entities without sign. i.e. are not intended to be interpreted as either signed or unsigned. It is only later, when used in a stored variable of some type specified, do the bits (may) have signage significance.

Jim Dempsey

Quote:

jimdempseyatthecove wrote:

.. Why do you presume line 17 ought to warn of integer overflow? ..

@Jim,

When I suggested the toolset being able to generate some warnings, I meant in a general sense of being able to help the coders that something is goung out of range.  The warnings can help code reviewers notice situations that can result in unexpected behavior.  As you would know, in the case of Intel Fortran, the values will "wrap around" (to -128, -127, etc. in the case of code in Quote #6) which can also problematic with coded algorithms.   Not everyone, especially some of the younger folks, know about this.  In a team I work with, there was a siutation not too long ago where a young engineer didn't realize the BOZ literal used in a hashing algorithm was out of range for the kind selected for the integer.  There was no warning and it was near-miss, happenchance the problem got noticed before it was too late. 

FF,

Due to Fortran not having unsigned types, it may be quite reasonable for me to program some device (some system API) using hex numbers represented as BOZ literals. To have the compiler warn me half the time is a bit annoying.

>>Not everyone, especially some of the younger folks, know about this.  In a team I work with, there was a siutation not too long ago where a young engineer didn't realize the BOZ literal used in a hashing algorithm was out of range for the kind selected for the integer.

Then possibly the compiler should offer -warn:noobprogrammer, or something like (or -warn:lint) that catches not only this but as many pitfalls as it can find. A particularly nasty one is using an index variable that is integer(4) on an array that has a size that is too large to be properly indexed with integer(4).

Jim Dempsey

LOL  -warn:noobprogrammer

-warn:usage exists. Over the years I had suggested adding various types of questionable practices to it, though not much had been done to date.

BOZ literals are typeless - it would make no sense to provide overflow warnings for them as long as the number of 1 bits in the value didn't exceed the bit size of the thing they were being used for/defining.

Steve (aka "Doctor Fortran") - Retired from Intel

Quote:

jimdempseyatthecove wrote:

.. reasonable for me to program some device (some system API) using hex numbers represented as BOZ literals. To have the compiler warn me half the time is a bit annoying. ..

@Jim,

If there is anyone whom I would expect to work with HEX numbers represented as BOZ literals and integer variables correctly in their code, it would be you.  So I don't understand your latest comments.

In the highly unlikely event Intel Fortran team follows up on my suggestion in Quote #6, why do you suppose any warnings will pop up in any of your actual code?

What is that "half the time" the compiler is going to warn you that you will find "a bit annoying"?

Can you post a line or two of your use of BOZ literal from any of your codes where you think the compiler will raise a warning should my suggestion get followed?

 

Quote:

Steve Lionel (Ret.) wrote:

.. BOZ literals are typeless - it would make no sense to provide overflow warnings for them as long as the number of 1 bits in the value didn't exceed the bit size of the thing they were being used for/defining.

Steve,

Where was it suggested a warning be issued about BOZ literals?

Jim asked specifically about line 17 of the code shown in Quote #6 where I suggested a warning from a suitable toolset in Intel Parallel Studio, perhaps the Intel Fortran compiler itself:

  • Did you notice the integer kind in the type specification in the array constructor and the integer kind of the variable on the left hand side of the assignment vis-a-vis the BOZ literals used in the code on that line 17?
  • Did you notice the corresponding situation on line 7 for which I did not suggest any warning?

Dear contributers,

thanks for the replies. My conclusion at the moment is that the original code (#1) is not standard conforming and, therefore, the warning is correct. (By the way, gfortran with -Wall don't give a warning, not to mention an error.)

Nevertheless I feel uncomfortable with the situation. The scalar case

INTEGER(KIND=INT8) :: value

value = INT(z'11', KIND=INT8)

works fine, but if we want to exploit the elemental property of the INT function it gets wrong. Therefore, I support the request of FortranFan (#5) to have this inconsistency removed in the next standard.

(Needless to say that an introduction of UNsigned integers can help a lot in this regard!)

Again, thank you all.

Robert

 

@#16

It is a consistency not an inconsistency! Do we gain much by having a set of additional syntax rules added to Fortran?

There are so many other ways you can do it. If you were using 1 byte BOZ literals all over the place you could save typing by creating a module that defined 256 default integer parameters  called Z00 >> ZFF, not that I am suggesting doing that but it is simpler than changing the language!

One quirk of the Intel Fortran compilers that makes it harder to detect code that is non-conforming is the tolerance given to placebo compiler options, i.e., options that have no meaning and no effect at all, with the user under the delusion that the option she/he used caused some desired checking to happen. Some of these options had some functionality years ago in an old version of IFort, but have no effect now, and no warning is given when they are used.

Take the /stand option, which is relevant to the current thread. IFort-16 accepts /stand:-323, /stand:f1871, /standard:1929, /fstand:88 and /stand:f2020, all without complaint! The years I used match (i) death of Alexander the Great, (ii) Franco-Prussian War, (iii) Crash of Wall Street, (iv) the stillborn successor to Fortran-77, and (v) the year in which FortranFan's wishes will come true.

The current compiler, 18.0, does better, warning "ignoring unknown option '/stand:88'". However, users of the older versions should beware of placebo options, nor would I be surprised if the current compiler is found to swallow other placebo options than the ones that I have tried.

When you have a bad headache, if you take a placebo analgesic, wait an hour with no relief, take another pill, wait another hour, and then you find that you had taken CaCO3 pills, would you appreciate the joke?

/stand:f2020 must be the hind-sight version.

Jim Dempsey

Quote:

Robert van Amerongen wrote:

.. if we want to exploit the elemental property of the INT function it gets wrong. Therefore, I support the request of FortranFan (#5) to have this inconsistency removed in the next standard...

@Robert,

Thank you for your feedback and support.

Current Fortran standard has the following constraint and this is what makes the code in your original post to be non-conforming:

C4102 (R463) A boz-literal-constant shall appear only as a data-stmt-constant in a DATA statement,
             or where explicitly allowed in subclause 13.7 as an actual argument of an intrinsic procedure 

So you will note it is standard-conforming to use a DATA statement with BOZ literals for your 'values' array.  However, as you would know, DATA statement imparts the implicit SAVE attribute to the variable and therefore one has to be very careful with its use.  Also, if your use case will require the DATA statement to appear among other executable statements, such use is now marked as obsolescent in the Fortran standard and therefore with /stand compiler option, you might trade in one warning for another.

   use, intrinsic :: iso_fortran_env, only : int8

   integer(kind=int8) :: values(3)

   data values / z'11', z'22', z'33' /

   print *, "values = ", values

end

No errors or warnings with /stand as well as /warn:all during compilation of this code and upon execution, you will get:

 values =  17 34 51

But if the standard supports above syntax with a DATA statement and separately, it offers array constructors and type-spec options with them, it should be fairly straightforward to improve upon the (C4102) constraint in a way that will provide the 'syntactic sugar' for the coders.  The funny thing is Intel Fortran, gfortran, and several other compilers already provide the facility, it's only the standard that does not support it yet.  Meaning, you can take the following code and try it with Intel Fortran compiler, gfortran and others and report here how they work!

   use, intrinsic :: iso_fortran_env, only : int8

   integer(kind=int8) :: values(3)

   values = [ integer(kind=int8) :: z'11', z'22', z'33' ]

   print *, "values = ", values

end

But it's unfortunate the standard constrains the above array constructor syntax to be non-conforming, for both Intel Fortran and gfortran accept it and upon execution, the output is:

 values =  17 34 51

Note there is a somewhat similar analogy with length-type parameter of variables, a canonical example being the array constructor syntax for arrays of CHARACTER variables.  Luckily the standard allows the following now:

   character(len=10) :: values(2)

   values = [ character(len=10) :: 'Hello', 'World!' ]

   print *, "values = ", values
   print *, "len(values) = ", len(values), "; expected is 10"

end

Upon execution,

 values = Hello     World!
 len(values) =  10 ; expected is 10

What I was suggesting to Steve in Quote #6 is nothing new, its been discussed elsewhere online and others have agreed it will be useful (e.g., in hashing algorithms and other applications involving data encryption where named constant arrays of numbers represented in HEX can be involved) and that it is an organic extension to the Fortran language syntax.  It's a minor, almost trivial revision to the standard which will be fully consistent with other aspects involving array constructors in the standard, as illustrated above.  It's too bad and a real shame some make it appear as if it is not worth the effort.

FortranFan,

You expressed an issue with entering in hex, say for hash table, and having the hex being assumed by the programmer as unsigned, but by the execution statements as being signed. And that this is fraught with potential problems with a noob programmer coding such a hash table. A simple (though maybe abstruse) solution would be to IXOR a BOZ literal comprising of the sign bit upon entry.

IOR(z'ff', z'80') ! largest uint8 becomes largest int8 (z'7F' or 127)
IOR(z'00',z'80') ! smallest uint8 becomes smallest int8 (Z'80' or -128)

Then you would not need the convoluted nested IF statements to perform unsigned range checking.

Jim Dempsey

Quote:

jimdempseyatthecove wrote:

.. You expressed an issue with entering in hex, say for hash table, and having the hex being assumed by the programmer as unsigned, but by the execution statements as being signed.  ..

@Jim,

No, that is not what I meant, not at all.  

You will notice from the Fortran standard constraint shown in Quote #19, a BOZ literal can only appear in Fortran code in a DATA statement or as an actual argument to certain INTRINSIC procedures (subclause 13.7 in Fortran 2008 standard) e.g., INT,.  In either of these instances it goes on to *define* something, usually an integer variable.  The warning I was suggesting to the Intel Fortran has to do with this process of defining, as to what happens when the bit size of what is getting defined is insufficient for the BOZ literal and Intel Fortran then does its own thing.

Consider the following simple example:

   use, intrinsic :: iso_fortran_env, only : IK => int8

   integer(kind=IK) :: foo

   foo = int( Z"101", kind=kind(foo) )

   print "(3g0,z0)", "foo = ", foo, "; in hex = ", foo

end

Upon compilation, no errors or warnings are generated and upon execution, the program works differently than the coder had expected, not having realized the IK kind for the integer variable is improper - see below:

xx>ifort /warn:all /stand p.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 18.0.0.124 Build 20170811
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.11.25508.2
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

xx>p.exe
foo = 1; in hex = 1

You will notice this example uses a HEX literal '101' that is out-of-range for the variable 'foo' it is used to define; note foo is an integer of kind IK that points to INT8.  The fact Intel Fortran compiler does its own bits manipulation here without alerting the coder is what is bothersome.

This is the issue I would like Intel Fortran team to address, that extending some help to coders when they make a mistake, like in the exanple above, will be useful, at least when they ask for such help in the form of a suitable compiler option (/warn:xx) or with other code-analyzer tools in the Intel Studio package.

Just a comment for those who might make assumptions - BOZ constants are allowed as arguments to selected intrinsics only. If the description of the intrinsic says what it means for a BOZ argument, then it's ok, otherwise it is not.

The list of allowed intrinsics, if I get this correct, is: BGE, BGT, BLE, BLT, CMPLX (X or Y), DBLE, DSHIFTL (I or J), DSHIFTR (I or J), IAND, IEOR, INT (A), IOR, MERGE_BITS, REAL (A).

Steve (aka "Doctor Fortran") - Retired from Intel

Andrew_4619 (#16) is right if he states that there are many other means to solve the problem. FortranFan (#19) give one of these: the data statement. I stil prefer the original code in my post (#1), but I am afraid that this will not appear in any standard in the future. It is as it is.

Thanks for the contributions.

Robert

While I agree that Z"101" should be flagged as out of range for an integer(1), Z"81" should not (nor Z"FF" or any hex less than Z"FF").

When a programmer uses a debugger and views an integer as Hex, or uses a Hex calculator, there are no "negative" numbers. Enter -3 and the display shows FFFFFFFFFFFFFFFD.

I do not think that Fortran should go out of its way as having oddball behavior.

Jim Dempsey

Leave a Comment

Please sign in to add a comment. Not a member? Join today