Type casts (was: Dynamic array sizes

Frank Heckenbach frank at g-n-u.de
Sun Mar 9 07:45:30 CET 2003


CBFalconer wrote:

> > > You can test
> > > yourself easily. While writing such a test, I ran into an internal
> > > compiler error.
> > >
> > > program zero;
> > > type int64 = integer( 64);
> > > var r: double; l: int64;
> > > begin
> > >    l:= 0;
> > >    int64( r):=l;
> > >    writeln( 'r = ', r);
> > >    r:= -1;
> > >    double( l):= r;
> > >    writeln( 'l = ', l)
> > > end.
> > >
> > > [G4:~/gnu/testgpc/adriaan] adriaan% gpc -o zero zero.pas
> > > zero.pas: In main program:
> > > zero.pas:1: Internal compiler error in convert_move, at expr.c:507
> > > Please submit a full bug report,
> > > with preprocessed source if appropriate.
> > > See <URL:http://www.gnu-pascal.de/todo.html> for instructions.
> > 
> > Thanks for the report (adriaan1.pas).
> > 
> > BTW, the test is questionable itself. It assumes 64 bit doubles
> > which is true for IEEE, but not guaranteed at all for other formats.
> > So better use `SizeOf' etc.
> 
> Besides, shouldn't that be:
> 
>  begin
>  l := 0;
>  r := double(l);
>  writeln('r = ', r);
>  r := -1;
>  l := int64(r);
>  writeln('l = ', l)
>  end.
> 
> i.e. the transform is applied to the right hand side.  I would
> expect an error such as 'taking the address of an expression' with
> the original.

Actually, assigning is not the same as taking the address (you can
assign to register variables, but not take their address). But
that's beside the point.

The type-cast model GPC follows (or rather, aims to) is the one of
BP (the only one I know) which is as follows:

- Expressions can be cast between ordinal and pointer types. In this
  case, the result of the type-cast is no "lvalue" (can't be
  assigned to etc.), and the ordinal value (extended to pointers) is
  preserved.

- "Lvalues" (the BP manual speaks of variable type casts here, but
  in fact it allows it also for things like `foo^', i.e. any lvalue)
  can be cast to a type whose size matches. (Of course, this is a
  portability issue, which BP doesn't care about, so it's up to the
  user to make sure that the size matches, e.g. casting something of
  type `Foo' to `array [1 .. SizeOf (Foo)] of Byte', or in the
  example above using `BitSizeOf (Double)' instead of 64.) In this
  case, the bit pattern is preserved, and the result is also an
  lvalue, i.e. can be used on both sides of an assignment etc.

There are cases where both kinds of type-casts are applicable, e.g.:

  var a: ^Foo;
  [...]
  WriteLn (PtrInt (a))  { `LongInt' in BP }

"Fortunately", in these cases both are equivalent, since the same
ordinal values correspond to the same bit patterns in all ordinal
types and pointers in BP (and also GPC).

Now, GPC doesn't quite follow this model so far, but I think that's
bugs which should be fixed. E.g.:

- It crashes on some type casts, which the original mail was about.

- It allows value type casts from ordinal to real types. At first
  sight, this might seem useful in case you want to use an integer
  in a place where a real is expected and no automatic conversion is
  performed (rather few cases).

  However, there's a conflict:

  var a: Integer;
  [...]
  WriteLn (ShortReal (a))

  If `Integer' and `ShortReal' have the same size (as on IA32), this
  could be either a value or a variable type casts, but the results
  are different.

  So BP's restriction to only ordinal and pointer types seems quite
  reasonably, and I'd like to forbid the other case in GPC as well
  (no objections I hope ;-). In the few cases where such a
  conversion is needed, there are alternatives such as adding `0.0'
  or assigning to a temporary variable of real type.

- It allows some more dubious casts which I'll also forbid.

Frank

-- 
Frank Heckenbach, frank at g-n-u.de, http://fjf.gnu.de/, 7977168E
GPC To-Do list, latest features, fixed bugs:
http://www.gnu-pascal.de/todo.html
GPC download signing key: 51FF C1F0 1A77 C6C2 4482  4DDC 117A 9773 7F88 1707




More information about the Gpc mailing list