[Issue 2013] interface to interface dynamic cast is incorrect in some cases

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sat Jul 18 06:02:30 PDT 2015


https://issues.dlang.org/show_bug.cgi?id=2013

--- Comment #3 from Kenji Hara <k.hara.pg at gmail.com> ---
The problem is in both dmd and druntime code.

For the class/interface hierarchy:

  interface IA          { ... }
  interface IB : IA     { ... }
  interface IC : IB     { }
  interface ID : IA, IC { ... }
  class C : ID { ... }

The layout of pointer to vtbls in the class C instance object is:

            (IA)
             IB
        IA,  IC
  C  :  ID
  ----------------------
  0     n    n+ptrsize
  // Note: n is the size of __vtbl + __monitor + sum of C field sizes.
  // It's 8 with -m32.

Currently dmd generates following tree of `object.Interface` structs to
represent the hierarchy:

   +-> CI(IA).interfaces[] == []
   |    A
   |    +-------------------------+
   |                              |
   |   CI(IB).interfaces[] == [CI(IA)/0]
   |    A
   |    +-------------------------+
   |                              |
   |   CI(IC).interfaces[] == [CI(IB)/0]
   |    A
   |    +---------------------------+----------+
   |                                |          |
   +----------------------+         |          |
                          |         |          |
  CI(ID).interfaces[] == [CI(IA)/0, CI(IC)/0]  |
   A                                           |
   +----------------------+         +----------+
                          |         |
   CI(C).interfaces[] == [CI(ID)/n, CI(IC)/n+ptrsize]

  // Note: CI(X) == ClassInfo(X) == typeid(X).info
  //       CI(X)/num --> num == object.Interface.offset

For the cast from IA to IB, druntime once downcast IA to Object, then calculate
offset from Object(== C) to IB.

It's handled by _d_interface_cast(), _d_dynamic_cast(), and _d_isbaseof2()
functions in druntime/src/rt/_cast.d.

The problem is in _d_isbaseof2(). It should return n+ptrsize for the cast from
Object to IB, but while the iteration of above thee by breadth-first, it
incorrectly returns n.

-------

The way to fix the issue:
1. Fix compiler-generated Interfaces[] tree
2. Fix _d_isbaseof2() function to calculate correct offset.

--


More information about the Digitalmars-d-bugs mailing list