With range checking on, FPC does not compile that.
That demonstrates that FPC is mixing apples and oranges. Range checking isn't meant to change the compile time data type of a variable. It's purpose is to tell the compiler to generate code to verify that a _variable_ is in the specified range at _run time_ not compile time (since it obviously cannot do it at compile time when a variable is used). Pascal's strong type checking is neither associated nor dependent in any way on any runtime feature, such as range checking.
In a definition such as:
and in any range definition in Pascal, the lower and upper bounds are known and they limit the acceptable values of the underlying type, which the compiler is forced to _assume_. In this particular example, it is forced to assume the underlying type is: integer.
now, in a statement such as:
that's, first and foremost, a data type violation. No correctly implemented Pascal compiler would compile that. Range checking is not necessary for the compiler to determine there is a data type violation there. That is as incorrect as
Now when using a variable instead of a constant, in a statement such as:
var
AnIndex : integer;
..
..
AnArray[AnIndex]
the type of AnIndex is assignment compatible with the compiler _assumed_ type of the range, therefore, the statement is perfectly valid. Of course, when using a variable, the compiler does not have enough information at compile time to enforce the range boundaries. That's when range checking comes into play, when enabled the compiler can generate code to verify that the variable, in addition to being assignment compatible - which it checked at compile time against the _assumed_ underlying type of the range - holds a value that is in the range.
The crucial thing to understand is that, in no way does that change the code that is generated. The compiler generates the
same code to calculate what address the expression refers to and, when range checking is enabled, it also generates code to enforce the range boundaries. The claim that the code is erroneous when using a variable is
false but it is true when using a constant that is not in the range yet, FPC compiles it, that by itself is a compiler bug.
In that specific case, FPC compiles code which is erroneous (AnArray[-5]) and generates erroneous code for a valid Pascal statement (AnArray[AnIndex]).
Doesn't just simply fall into the category of undefined behavior? As in: cannot be relied upon in any specific way, because the output is not defined?
The claim that there is something undefined is yet another instance of mixing apples and oranges. The
result, when the variable is not in the range is undefined but, there is nothing undefined as far as code generation is concerned.
An example will make this clearer
var
AShortInt : shortint;
AnInteger, AnotherInteger : integer;
begin
AnInteger := 240;
AnotherInteger := 240;
AShortInt := AnInteger + AnotherInteger;
etc
The statement
AShortInt := AnInteger + AnotherInteger;
isn't wrong/erroneous or invalid in any way. The compiler generates code to add the two variables AnInteger + AnotherInteger and stores the result in AShortInt. The one thing that is legitimately undefined is what the
result is going to be since the sum causes an overflow but, ensuring there is no overflow is the programmer's responsibility, not the compiler's and, much less a justification for the compiler to get "creative" and truncate the values stored in AnInteger and AnotherInteger to force the result to fit in a shortint.
When overflow checking is off, the result will be whatever bit pattern is generated by the sum truncated to a shortint but, the compiler
does not generate different code when overflow checking is on. It simply
adds instructions to verify that the
result is in the range of the variable and, it does so
only if the programmer requests it.
That's exactly what it should do - and rather unfortunately isn't doing - when indexing an array with a variable.
When variables are used to access memory, it is the programmer's responsibility to ensure that those references point to the location they are supposed to reference. It is most definitely not the compiler's prerogative to mutilate variables to force-fit references in a range it
incorrectly determined.
Unfortunately, nothing short of a miracle is going to cause that bug to be corrected. Maybe the way to have it fixed is go to church or Lourdes.