public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* Request to improve docs: Fortran integer ranges vs. machine representation
@ 2024-01-26 13:44 Elias Toivanen
  2024-01-26 16:50 ` Steve Kargl
  0 siblings, 1 reply; 7+ messages in thread
From: Elias Toivanen @ 2024-01-26 13:44 UTC (permalink / raw)
  To: fortran

Hi,

I stumbled upon a Fortran quirk regarding the ranges for integers. The standard stipulates that the ranges be symmetric even though as we know two's complement signed integers have asymmetrical ranges, e.g. int8 kind can vary between -128 and 127.

This is sure to cause confusion as for example the following program does not compile:

```
program main
  use iso_fortran_env
  implicit none
  print *, -128_int8
end program
```

GFortran 13.2.0 provides the error message

Error: Integer too big for its kind at (1). This check can be disabled with the option '-fno-range-check'
 
While a workaround to disable the range check is provided, the error message is a bit misleading. For one, the number is too small for the int8 number model. For the second, it is not obvious to the lay why removing the kind literal leads to a clean compile.

Codewise the topic has been discussed in PRs 13490 and 17912, and I think the current implementation is correct. What could be improved are the pages https://gcc.gnu.org/bugs/ and the above error message. 

I would like to propose that the error message should hint more towards the root cause. Something along the lines of: 'Out of range integer for its selected kind at (1). This check can be disabled with the option '-fno-range-check'.

Secondly, I think this quirk could be a good candidate to the known bugs section of your website.

I tried to file a bug / craft a PR but access to your repos is a bit limited at this point, so I decided to write this message as my 2 cents. 

Anyway, thanks for your good work! I can also volunteer to help you with this or some other tasks. Haven't done it before but would be interesting to try it out.

--
Best regards / Ystävällisesti
Elias Toivanen
elias.a.toivanen@gmail.com



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 13:44 Request to improve docs: Fortran integer ranges vs. machine representation Elias Toivanen
@ 2024-01-26 16:50 ` Steve Kargl
  2024-01-26 20:23   ` FX Coudert
  0 siblings, 1 reply; 7+ messages in thread
From: Steve Kargl @ 2024-01-26 16:50 UTC (permalink / raw)
  To: Elias Toivanen; +Cc: fortran

On Fri, Jan 26, 2024 at 03:44:26PM +0200, Elias Toivanen wrote:
> 
> I stumbled upon a Fortran quirk regarding the ranges for integers.
> The standard stipulates that the ranges be symmetric even though
> as we know two's complement signed integers have asymmetrical
> ranges, e.g. int8 kind can vary between -128 and 127.

This is not quite true.  The model number for integer is symmetric,
but the machine representable does not need to be symmetric.

> 
> This is sure to cause confusion as for example the following
> program does not compile:
> 
> ```
> program main
>   use iso_fortran_env
>   implicit none
>   print *, -128_int8

This is a unary minus operator with an operand of 128.
gfortran does not have negative integers.

> end program
> ```
> 
> GFortran 13.2.0 provides the error message
> 
> Error: Integer too big for its kind at (1). This check can
> be disabled with the option '-fno-range-check'

which gives you this error because 128 is greater 127.

It is a little known fact, but you can force a symmetric
range with the -pedantic option.

-- 
Steve

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 16:50 ` Steve Kargl
@ 2024-01-26 20:23   ` FX Coudert
  2024-01-26 21:41     ` Steve Kargl
  0 siblings, 1 reply; 7+ messages in thread
From: FX Coudert @ 2024-01-26 20:23 UTC (permalink / raw)
  To: Steve Kargl; +Cc: Elias Toivanen, fortran


>>  print *, -128_int8
> 
> This is a unary minus operator with an operand of 128.
> gfortran does not have negative integers.

To be clear, it’s not gfortran, it’s the standard(s). It’s not exactly true either, because there is a "signed-int-literal-constant” which is allowed in some contexts:

- as real part or imaginary part of a complex literal constant
- as a data-stmt-constant
- in some edit descriptors (DT and P control-edit-desc)

This is, for example, legal code (and handled by gfortran as expected):

  use iso_fortran_env
  implicit none
  integer(int8) :: j
  data j /-128_int8/
  print *, j
  end

On the other hand, in your code, -128_int8 cannot be a literal constant, because integer literal constants cannot have a sign in Fortran. As Steve said, “-128_int8” in this context in Fortran is the minus unary operator applied to the integer literal constant 128_int8.

We current output this:

    4 |   j = -128_int8
      |               1
Error: Integer too big for its kind at (1). This check can be disabled with the option '-fno-range-check’

I think the only better output we could give is to make it clear what the integer value is, either by underlining it (but we don’t have a framework to do that right now) or by outputting the value in the message (?).


Best,
FX




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 20:23   ` FX Coudert
@ 2024-01-26 21:41     ` Steve Kargl
  2024-01-26 22:38       ` FX Coudert
  0 siblings, 1 reply; 7+ messages in thread
From: Steve Kargl @ 2024-01-26 21:41 UTC (permalink / raw)
  To: FX Coudert; +Cc: Elias Toivanen, fortran

On Fri, Jan 26, 2024 at 09:23:56PM +0100, FX Coudert wrote:
> 
> This is, for example, legal code (and handled by gfortran as expected):
> 
>   use iso_fortran_env
>   implicit none
>   integer(int8) :: j
>   data j /-128_int8/
>   print *, j
>   end
> 

Interesting example.

% gfcx -o z a.f90 &&  ./z
 -128
% gfcx -o z -pedantic a.f90 && ./z
a.f90:5:20:

    5 |   data j /-128_int8/
      |                    1
Error: Integer too big for its kind at (1). This check can be disabled with the option ‘-fno-range-check’
% gfcx -o z -pedantic -fno-range-check a.f90 && ./z
a.f90:5:20:

    5 |   data j /-128_int8/
      |                    1
Error: Integer too big for its kind at (1). This check can be disabled with the option ‘-fno-range-check’

:-)

-- 
Steve

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 21:41     ` Steve Kargl
@ 2024-01-26 22:38       ` FX Coudert
  2024-01-27  2:19         ` Steve Kargl
  2024-01-28 10:18         ` Elias Toivanen
  0 siblings, 2 replies; 7+ messages in thread
From: FX Coudert @ 2024-01-26 22:38 UTC (permalink / raw)
  To: Steve Kargl; +Cc: Elias Toivanen, fortran

> Interesting example.
> 
> % gfcx -o z a.f90 &&  ./z
> -128
> % gfcx -o z -pedantic a.f90 && ./z
> a.f90:5:20:
> 
>    5 |   data j /-128_int8/
>      |                    1
> Error: Integer too big for its kind at (1). This check can be disabled with the option ‘-fno-range-check’

That qualifies as a compiler bug, I think. Our documentation for -pedantic states: “Issue warnings for uses of extensions to Fortran.” and "Valid Fortran programs should compile properly with or without this option.”

The same is true of the following, which is also valid Fortran since 95 :

 use iso_fortran_env
 implicit none
 complex, parameter :: z = (-128_int8, -128_int8)
 print *, z
 end

Right now it fails to compile with -pedantic.

Or are they illegal because of how the range should be be symmetric? I can’t quite find the language in the standard for that, actually. To me, they’re valid signed-int-literal-constant.

FX


PS: I’m going to ignore the cases of the P and DT edit descriptors, because they’re not allowed to have a kind value, and therefore the corner cases occur for values too big to be actually relevant to anything.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 22:38       ` FX Coudert
@ 2024-01-27  2:19         ` Steve Kargl
  2024-01-28 10:18         ` Elias Toivanen
  1 sibling, 0 replies; 7+ messages in thread
From: Steve Kargl @ 2024-01-27  2:19 UTC (permalink / raw)
  To: FX Coudert; +Cc: Elias Toivanen, fortran

On Fri, Jan 26, 2024 at 11:38:01PM +0100, FX Coudert wrote:
> > Interesting example.
> > 
> > % gfcx -o z a.f90 &&  ./z
> > -128
> > % gfcx -o z -pedantic a.f90 && ./z
> > a.f90:5:20:
> > 
> >    5 |   data j /-128_int8/
> >      |                    1
> > Error: Integer too big for its kind at (1). This check can be disabled with the option ‘-fno-range-check’
> 
> That qualifies as a compiler bug, I think. Our documentation for -pedantic states: “Issue warnings for uses of extensions to Fortran.” and "Valid Fortran programs should compile properly with or without this option.”
> 
> The same is true of the following, which is also valid Fortran since 95 :
> 
>  use iso_fortran_env
>  implicit none
>  complex, parameter :: z = (-128_int8, -128_int8)
>  print *, z
>  end
> 
> Right now it fails to compile with -pedantic.
> 
> Or are they illegal because of how the range should be be symmetric? I can’t quite find the language in the standard for that, actually. To me, they’re valid signed-int-literal-constant.
> 

Symmetry comes from the definition of a model integer number
in 16.3.3 "Bit sequences as arguments to INT and REAL".  If
'i' and 'j' are INTEGER(1), then this leads to something like
'j = abs(i)' being comforming except if 'i = -128'.

As far as literal constants, one has from Fortran 2023 p. 66

R707 signed-int-literal-constant  is [ sign ] int-literal-constant
R708 int-literal-constant         is digit-string [ _ kind-param ]
R709 kind-param                   is digit-string

R710 signed-digit-string  is [ sign ] digit-string
R711 digit-string         is digit [ digit ] ...
R712 sign                 is +
                          or -

I cannot find in the Standard any statement about the conversion
of a digit-string to an internal representation.  I suspect it
depends on the path through the compiler.  In assignments, the
signed-digit-string is likely handled as a unary operator and
operand. 

-- 
Steve

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Request to improve docs: Fortran integer ranges vs. machine representation
  2024-01-26 22:38       ` FX Coudert
  2024-01-27  2:19         ` Steve Kargl
@ 2024-01-28 10:18         ` Elias Toivanen
  1 sibling, 0 replies; 7+ messages in thread
From: Elias Toivanen @ 2024-01-28 10:18 UTC (permalink / raw)
  To: FX Coudert; +Cc: Steve Kargl, fortran

Guys, it's unproductive to discuss GFortran internals or the nuances of the standard with an end-user like me ;-)

AFAIK, the implementation is compliant and correct. My angle here was completely different. The question is whether this aspect of Fortran leads to confusion and subsequently to duplicate bug reports and other such noise, which is away from your precious time. If so, the way the error messages are worded and the way your docs are written play a crucial role in mitigating the issue.

Enabling the `-pedantic` flag in myself, in the listing (primary.cc:286 <http://primary.cc:286/>) 

```
if (gfc_range_check (e) != ARITH_OK)
    {
      gfc_error ("Integer too big for its kind at %C. This check can be "
		 "disabled with the option %<-fno-range-check%>");

      gfc_free_expr (e);
      return MATCH_ERROR;
    }
```

the if-block will be entered for any of the current and future error codes, while the error message only talks about the magnitude of the input.

If on the other hand you deem that working on this is not worth the effort, the issue is naturally resolved. 


--
Best regards / Ystävällisesti
Elias Toivanen
elias.a.toivanen@gmail.com


> On 27. Jan 2024, at 0.38, FX Coudert <fxcoudert@gmail.com> wrote:
> 
>> Interesting example.
>> 
>> % gfcx -o z a.f90 &&  ./z
>> -128
>> % gfcx -o z -pedantic a.f90 && ./z
>> a.f90:5:20:
>> 
>>   5 |   data j /-128_int8/
>>     |                    1
>> Error: Integer too big for its kind at (1). This check can be disabled with the option ‘-fno-range-check’
> 
> That qualifies as a compiler bug, I think. Our documentation for -pedantic states: “Issue warnings for uses of extensions to Fortran.” and "Valid Fortran programs should compile properly with or without this option.”
> 
> The same is true of the following, which is also valid Fortran since 95 :
> 
> use iso_fortran_env
> implicit none
> complex, parameter :: z = (-128_int8, -128_int8)
> print *, z
> end
> 
> Right now it fails to compile with -pedantic.
> 
> Or are they illegal because of how the range should be be symmetric? I can’t quite find the language in the standard for that, actually. To me, they’re valid signed-int-literal-constant.
> 
> FX
> 
> 
> PS: I’m going to ignore the cases of the P and DT edit descriptors, because they’re not allowed to have a kind value, and therefore the corner cases occur for values too big to be actually relevant to anything.



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-01-28 10:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-26 13:44 Request to improve docs: Fortran integer ranges vs. machine representation Elias Toivanen
2024-01-26 16:50 ` Steve Kargl
2024-01-26 20:23   ` FX Coudert
2024-01-26 21:41     ` Steve Kargl
2024-01-26 22:38       ` FX Coudert
2024-01-27  2:19         ` Steve Kargl
2024-01-28 10:18         ` Elias Toivanen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).