The following code fails silently in one case and segfaults in another. Presumably it should work, but if not it should probably be reported as an error (the up-cast case can cause hard-to-track bugs).
The problem is when casting up/down with interface pointers as commented in the following code. The class-inheritance based version is just there for comparison; it works fine.
/// Casting tests.
module casts.d;
import tango.io.Stdout;
interface I {
void method();
}
class C : I {
void method() {
Stdout ("C.method").newline;
}
}
class A {
void method() {
Stdout ("A.method").newline;
}
}
class B : A {
void method() {
Stdout ("B.method").newline;
}
}
void main () {
Stdout ("Interface upcasts:").newline;
C c = new C();
Stdout ("To I:").newline;
I i = cast(I) c;
i.method(); // works as it should
Stdout ("To I*:").newline;
I* ip = cast(I*) &c; // incorrect? no error/warning even with -w
ip.method(); // fails silently
Stdout ("Interface downcasts:").newline;
I* ip2 = &i;
ip2.method(); // works as expected
Stdout ("To C:").newline;
C c2 = cast(C) (*ip2);
c2.method(); // works as expected
/+ Compiles fine but segfaults when run:
Stdout ("To C*:").newline;
C* cp = cast(C*) ip2;
Stdout ("cp is null: "~ ((cp is null) ? "true" : "false")).newline;
cp.method(); // terminates with SIGSEGV - even though above line says (cp !is null)
+/
// The class examples all work with no problems:
Stdout ("Class upcasts:").newline;
B b = new B();
A a = cast(A) b;
A* ap = cast(A*) &b;
a.method(); // calls B.method as it should
ap.method(); // calls B.method, unlike interface example
Stdout ("Class downcasts:").newline;
B* bp = cast(B*) ap;
bp.method(); // calls B.method, unlike interface example
B b2 = cast(B) a;
b2.method(); // calls B.method as it should
}
Comment #1 by bugzilla — 2008-03-01T02:53:17Z
All pointer casts do is 'paint' a new type over the old one - no change in the bits ever occurs. To get the correct change in the bits for up/down inheritance casting, you have to cast the actual interface or class (which are reference types).
This is working as designed. It's not a bug.
You'll see exactly the same behavior in C++ when you do things like:
I* i;
C** pc = (C**)&i;