Prof. A Olowofoyeku (The African Chief) wrote:
On 20 Mar 2001, at 0:51, Frank Heckenbach wrote:
[...]
??? How should the compiler know? I mean, the object type of a pointer at runtime is a matter of runtime.
I think what's meant is if the types involved are not ancestors of each other, i.e. in `foo [ia]s bar' if foo is of declared type ^baz, and neither bar is derived from baz or vice versa, then the compiler can know that the check is wrong.
There's another trivial case when bar is an ancestor of baz. In this case, the check is always true. I don't know what Delphi does in this case, but I think GPC should at least give a warning, like it does when comparing an unsigned value >= 0.
The interesting case, of course, is when baz is an ancestor of bar, and this requires a runtime check.
This little program shows how Delphi would handle it;
uses classes;
type f1 = class (TStringList) Procedure foo; virtual; end; type f2 = class (f1) Procedure bar; virtual; end;
procedure f1.foo; begin end; procedure f2.bar; begin end;
var h1 : f1; h2 : f2; begin h1 := f1.create; h2 := f2.create;
{--- these all return TRUE ---}
And should all give a warning (in GPC) because it's clear at compile time that they're true, and therefore the checks are either superfluous or not what the programmer means...
Writeln (h1 is f1); Writeln (h2 is f2); Writeln (h2 is f1); Writeln (h1 is TStringList); Writeln (h2 is TStrings); Writeln (h2 is TObject); Writeln (h1 is TStrings); Writeln (h1 is TObject);
{--- this returns FALSE ---} Writeln (h1 is f2);
That's the interesting case because h1 could (at runtime) be an f2.
{--- these three each cause a compile-time error ---}
Makes sense.
Writeln (h2 is TCollection); Writeln (h2 is TList); Writeln (h2 is TComponent);
{----} h1.free; h2.free; end.
Frank