www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1563] New: dynamic cast is not always performed

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1563

           Summary: dynamic cast is not always performed
           Product: D
           Version: 1.022
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: davidl 126.com


class A{}
class B:A{}
class C:B{}
void main()
{
  A a = new B;
  C c = cast(C)cast(void*)a;
  c = cast(C)c;
  assert(c is null);  // assertion failure
  c = cast(C)cast(A)cast(void*)c;       // workaround
  assert(c is null);  
}

the problem here is we don't distinguish the dynamic cast with the none dynamic
one.
For dynamic cast, it should always perform the check. And people should use
non-dynamic cast whenever it's possible. Only use dynamic cast only when we're
well informed it *requiring* a dynamic cast.
A warning is appreciated on this if the compiler is going to optimize the
dynamic cast away. And a corresponding option for this warning would be nice.
something like : -WCastToItself


-- 
Oct 09 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to d-bugmail puremagic.com,

 http://d.puremagic.com/issues/show_bug.cgi?id=1563
 
 Summary: dynamic cast is not always performed
 Product: D
 Version: 1.022
 Platform: PC
 OS/Version: Windows
 Status: NEW
 Severity: normal
 Priority: P2
 Component: DMD
 AssignedTo: bugzilla digitalmars.com
 ReportedBy: davidl 126.com
 class A{}
 class B:A{}
 class C:B{}
 void main()
 {
 A a = new B;
 C c = cast(C)cast(void*)a;
 c = cast(C)c;
 assert(c is null);  // assertion failure
 c = cast(C)cast(A)cast(void*)c;       // workaround
 assert(c is null);
 }

it looks to me like the bug is that "cast(ClassType)voidPt" doesn't check the type. I think that assuming that something of type C actually is of type C should be allowed. The guards should be at the original assignment. OTOH that makes things with unions fun.
Oct 09 2007
prev sibling next sibling parent reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1563





------- Comment #2 from wbaxter gmail.com  2007-10-09 22:02 -------
(In reply to comment #1)
 Reply to d-bugmail puremagic.com,
 
 http://d.puremagic.com/issues/show_bug.cgi?id=1563
 
 Summary: dynamic cast is not always performed
 Product: D
 Version: 1.022
 Platform: PC
 OS/Version: Windows
 Status: NEW
 Severity: normal
 Priority: P2
 Component: DMD
 AssignedTo: bugzilla digitalmars.com
 ReportedBy: davidl 126.com
 class A{}
 class B:A{}
 class C:B{}
 void main()
 {
 A a = new B;
 C c = cast(C)cast(void*)a;
 c = cast(C)c;
 assert(c is null);  // assertion failure
 c = cast(C)cast(A)cast(void*)c;       // workaround
 assert(c is null);
 }

it looks to me like the bug is that "cast(ClassType)voidPt" doesn't check the type. I think that assuming that something of type C actually is of type C should be allowed. The guards should be at the original assignment. OTOH that makes things with unions fun.

If you make cast(ClassType)voidPt check the type then D will have no way at all to do a reinterpret_cast. And I also agree that assuming something of type C is actually type C should be allowed. So I think the example is just bad code. If you do a reinterpret_cast then you're taking responsibility into your own hands. But the danger involved would definitely be more apparent if there were a more obvious construct for reinterpret casts like reinterpret_cast!(T). --
Oct 09 2007
parent BCS <ao pathlink.com> writes:
Reply to  wbaxter gmail.com

 If you make cast(ClassType)voidPt check the type then D will have no
 way at all
 to do a reinterpret_cast.  And I also agree that assuming something of
 type C
 is actually type C should be allowed.  So I think the example is just
 bad code.
 If you do a reinterpret_cast then you're taking responsibility into
 your own
 hands.
 But the danger involved would definitely be more apparent if there
 were a more obvious construct for reinterpret casts like
 reinterpret_cast!(T).
 

is their any reson to cast somthing that isn't a C to type C? Only a few reasons some to mind and I'm not shrue any of them should be allowed Get a call to a derived class to ack on a base class (this won't work anyway unless you can force a non v-tbl call, and I don't think you can) Get somthing that is not an object at all to act like one (again v-tbl calls make this realy unlikely) ??? and even if reinterpret_cast is dropped, we will always have unions template Reinterpret(R) { R Cast(T)(T t) { union RT{R r;T t;} RT rt; rt.t=t; return rt.r; } }
Oct 09 2007
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1563


smjg iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com




------- Comment #4 from smjg iname.com  2007-11-08 06:42 -------
(In reply to comment #3)
 is their any reson to cast somthing that isn't a C to type C? Only a few 
 reasons some to mind and I'm not shrue any of them should be allowed

It's the well-documented method of testing an object to see if it's of a particular class. http://www.digitalmars.com/d/expression.html#CastExpression "In order to determine if an object o is an instance of a class B use a cast: if (cast(B) o) { // o is an instance of B } else { // o is not an instance of B }" However, for this to work, o has to be declared as some superclass of B, not B itself. If the variable is declared as a B, then the compiler is within its right to assume that the object is a B (or o is already null). So it's reasonable that given C c; then c = cast(C) c; is a nop. The problem is that, unless I've missed something, the behaviour of casting a void* to class type is unspecified. --
Nov 08 2007