Expand Up
@@ -419,7 +419,7 @@ void ClassDeclaration::semantic(Scope *sc)
* we need to set baseClass field for class covariance check.
*/
baseClass = tc -> sym ;
b -> base = baseClass ;
b -> sym = baseClass ;
if (tc -> sym -> scope && tc -> sym -> baseok < BASEOKdone )
tc -> sym -> semantic (NULL ); // Try to resolve forward reference
Expand Down
Expand Up
@@ -452,9 +452,9 @@ void ClassDeclaration::semantic(Scope *sc)
for (size_t j = (baseClass ? 1 : 0 ); j < i ; j ++ )
{
BaseClass * b2 = (* baseclasses )[j ];
if (b2 -> base == tc -> sym )
if (b2 -> sym == tc -> sym )
{
error ("inherits from duplicate interface %s" , b2 -> base -> toChars ());
error ("inherits from duplicate interface %s" , b2 -> sym -> toChars ());
baseclasses -> remove (i );
continue ;
}
Expand All
@@ -471,7 +471,7 @@ void ClassDeclaration::semantic(Scope *sc)
}
}
b -> base = tc -> sym ;
b -> sym = tc -> sym ;
if (tc -> sym -> scope && tc -> sym -> baseok < BASEOKdone )
tc -> sym -> semantic (NULL ); // Try to resolve forward reference
Expand Down
Expand Up
@@ -514,7 +514,7 @@ void ClassDeclaration::semantic(Scope *sc)
baseClass = tc -> sym ;
assert (!baseClass -> isInterfaceDeclaration ());
b -> base = baseClass ;
b -> sym = baseClass ;
}
if (baseClass )
{
Expand All
@@ -540,11 +540,11 @@ void ClassDeclaration::semantic(Scope *sc)
BaseClass * b = interfaces [i ];
// If this is an interface, and it derives from a COM interface,
// then this is a COM interface too.
if (b -> base -> isCOMinterface ())
if (b -> sym -> isCOMinterface ())
com = true;
if (cpp && !b -> base -> isCPPinterface ())
if (cpp && !b -> sym -> isCPPinterface ())
{
::error (loc , "C++ class '%s' cannot implement D interface '%s'" , toPrettyChars (), b -> base -> toPrettyChars ());
::error (loc , "C++ class '%s' cannot implement D interface '%s'" , toPrettyChars (), b -> sym -> toPrettyChars ());
}
}
Expand Down
Expand Up
@@ -849,7 +849,7 @@ bool ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
for (size_t i = 0 ; i < cd -> baseclasses -> dim ; i ++ )
{
BaseClass * b = (* cd -> baseclasses )[i ];
if (b -> base == this || isBaseOf2 (b -> base ))
if (b -> sym == this || isBaseOf2 (b -> sym ))
return true;
}
return false;
Expand Down
Expand Up
@@ -925,13 +925,13 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
{
BaseClass * b = (* baseclasses )[i ];
if (b -> base )
if (b -> sym )
{
if (!b -> base -> symtab )
error ("base %s is forward referenced" , b -> base -> ident -> toChars ());
if (!b -> sym -> symtab )
error ("base %s is forward referenced" , b -> sym -> ident -> toChars ());
else
{
s = b -> base -> search (loc , ident , flags );
s = b -> sym -> search (loc , ident , flags );
if (s == this ) // happens if s is nested in this and derives from this
s = NULL ;
else if (s )
Expand Down
Expand Up
@@ -995,30 +995,8 @@ void ClassDeclaration::finalizeSize(Scope *sc)
if (sizeok == SIZEOKfwd )
return ;
// Allocate instance of each new interface
offset = structsize ;
assert (vtblInterfaces ); // Bugzilla 12984
for (size_t i = 0 ; i < vtblInterfaces -> dim ; i ++ )
{
BaseClass * b = (* vtblInterfaces )[i ];
unsigned thissize = Target ::ptrsize ;
alignmember (STRUCTALIGN_DEFAULT , thissize , & offset );
assert (b -> offset == 0 );
b -> offset = offset ;
// Take care of single inheritance offsets
while (b -> baseInterfaces_dim )
{
b = & b -> baseInterfaces [0 ];
b -> offset = offset ;
}
offset += thissize ;
if (alignsize < thissize )
alignsize = thissize ;
}
structsize = offset ;
// Add vptr's for any interfaces implemented by this class
structsize += setBaseInterfaceOffsets (structsize );
sizeok = SIZEOKdone ;
// Look for the constructor
Expand Down
Expand Up
@@ -1194,6 +1172,39 @@ void ClassDeclaration::interfaceSemantic(Scope *sc)
}
}
unsigned ClassDeclaration ::setBaseInterfaceOffsets (unsigned baseOffset )
{
assert (vtblInterfaces ); // Bugzilla 12984
// set the offset of base interfaces from this (most derived) class/interface.
unsigned offset = baseOffset ;
//if (vtblInterfaces->dim) printf("\n%s->finalizeSize()\n", toChars());
for (size_t i = 0 ; i < vtblInterfaces -> dim ; i ++ )
{
BaseClass * b = (* vtblInterfaces )[i ];
unsigned thissize = Target ::ptrsize ;
alignmember (STRUCTALIGN_DEFAULT , thissize , & offset );
b -> offset = offset ;
//printf("\tvtblInterfaces[%d] b->sym = %s, offset = %d\n", i, b->sym->toChars(), b->offset);
// Take care of single inheritance offsets
while (b -> baseInterfaces_dim )
{
b = & b -> baseInterfaces [0 ];
b -> offset = offset ;
//printf("\tvtblInterfaces[%d] + sym = %s, offset = %d\n", i, b->sym->toChars(), b->offset);
}
offset += thissize ;
if (alignsize < thissize )
alignsize = thissize ;
}
return offset - baseOffset ;
}
/****************************************
*/
Expand Down
Expand Up
@@ -1407,9 +1418,9 @@ void InterfaceDeclaration::semantic(Scope *sc)
for (size_t j = 0 ; j < i ; j ++ )
{
BaseClass * b2 = (* baseclasses )[j ];
if (b2 -> base == tc -> sym )
if (b2 -> sym == tc -> sym )
{
error ("inherits from duplicate interface %s" , b2 -> base -> toChars ());
error ("inherits from duplicate interface %s" , b2 -> sym -> toChars ());
baseclasses -> remove (i );
continue ;
}
Expand All
@@ -1433,7 +1444,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
}
b -> base = tc -> sym ;
b -> sym = tc -> sym ;
if (tc -> sym -> scope && tc -> sym -> baseok < BASEOKdone )
tc -> sym -> semantic (NULL ); // Try to resolve forward reference
Expand Down
Expand Up
@@ -1464,9 +1475,9 @@ void InterfaceDeclaration::semantic(Scope *sc)
BaseClass * b = interfaces [i ];
// If this is an interface, and it derives from a COM interface,
// then this is a COM interface too.
if (b -> base -> isCOMinterface ())
if (b -> sym -> isCOMinterface ())
com = true;
if (b -> base -> isCPPinterface ())
if (b -> sym -> isCPPinterface ())
cpp = true;
}
Expand Down
Expand Up
@@ -1522,19 +1533,19 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
// Copy vtbl[] from base class
if (b -> base -> vtblOffset ())
if (b -> sym -> vtblOffset ())
{
size_t d = b -> base -> vtbl .dim ;
size_t d = b -> sym -> vtbl .dim ;
if (d > 1 )
{
vtbl .reserve (d - 1 );
for (size_t j = 1 ; j < d ; j ++ )
vtbl .push (b -> base -> vtbl [j ]);
vtbl .push (b -> sym -> vtbl [j ]);
}
}
else
{
vtbl .append (& b -> base -> vtbl );
vtbl .append (& b -> sym -> vtbl );
}
Lcontinue:
Expand Down
Expand Up
@@ -1613,6 +1624,9 @@ void InterfaceDeclaration::finalizeSize(Scope *sc)
{
structsize = Target ::ptrsize * 2 ;
sizeok = SIZEOKdone ;
// set the offset of base interfaces
setBaseInterfaceOffsets (0 );
}
/*******************************************
Expand All
@@ -1634,22 +1648,31 @@ bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
{
BaseClass * b = cd -> interfaces [j ];
//printf("\tbase %s\n", b->base ->toChars());
if (this == b -> base )
//printf("\tX base %s\n", b->sym ->toChars());
if (this == b -> sym )
{
//printf("\tfound at offset %d\n", b->offset);
if (poffset )
{
* poffset = b -> offset ;
if (j && cd -> isInterfaceDeclaration ())
* poffset = OFFSET_RUNTIME ;
/* TODO: Even though it's an interface to base interface upcast,
* I think we can avoid runtime offset determination ultimately.
* (I doubt that it was just a workaround for the bug in the
* inferface to Object downcast)
*/
}
return true;
}
if (isBaseOf (b , poffset ))
{
if (j && poffset && cd -> isInterfaceDeclaration ())
* poffset = OFFSET_RUNTIME ;
if (poffset )
{
if (j && cd -> isInterfaceDeclaration ())
* poffset = OFFSET_RUNTIME ;
}
return true;
}
}
Expand All
@@ -1662,28 +1685,25 @@ bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
return false;
}
bool InterfaceDeclaration ::isBaseOf (BaseClass * bc , int * poffset )
{
//printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base ->toChars());
//printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym ->toChars());
for (size_t j = 0 ; j < bc -> baseInterfaces_dim ; j ++ )
{
BaseClass * b = & bc -> baseInterfaces [j ];
if (this == b -> base )
//printf("\tY base %s\n", b->sym->toChars());
if (this == b -> sym )
{
//printf("\tfound at offset %d\n", b->offset);
if (poffset )
{
* poffset = b -> offset ;
if (j && bc -> base -> isInterfaceDeclaration ())
* poffset = OFFSET_RUNTIME ;
}
return true;
}
if (isBaseOf (b , poffset ))
{
if (j && poffset && bc -> base -> isInterfaceDeclaration ())
* poffset = OFFSET_RUNTIME ;
return true;
}
}
Expand Down
Expand Up
@@ -1737,11 +1757,11 @@ BaseClass::BaseClass(Type *type, Prot protection)
//printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
this -> type = type ;
this -> protection = protection ;
base = NULL ;
offset = 0 ;
this -> sym = NULL ;
this -> offset = 0 ;
baseInterfaces_dim = 0 ;
baseInterfaces = NULL ;
this -> baseInterfaces_dim = 0 ;
this -> baseInterfaces = NULL ;
}
/****************************************
Expand All
@@ -1759,14 +1779,14 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
{
bool result = false;
//printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base ->toChars(), cd->toChars());
//printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym ->toChars(), cd->toChars());
if (vtbl )
vtbl -> setDim (base -> vtbl .dim );
vtbl -> setDim (sym -> vtbl .dim );
// first entry is ClassInfo reference
for (size_t j = base -> vtblOffset (); j < base -> vtbl .dim ; j ++ )
for (size_t j = sym -> vtblOffset (); j < sym -> vtbl .dim ; j ++ )
{
FuncDeclaration * ifd = base -> vtbl [j ]-> isFuncDeclaration ();
FuncDeclaration * ifd = sym -> vtbl [j ]-> isFuncDeclaration ();
FuncDeclaration * fd ;
TypeFunction * tf ;
Expand All
@@ -1787,7 +1807,7 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
// Check that it is current
if (newinstance &&
fd -> toParent () != cd &&
ifd -> toParent () == base )
ifd -> toParent () == sym )
cd -> error ("interface function '%s' is not implemented" , ifd -> toFullSignature ());
if (fd -> toParent () == cd )
Expand All
@@ -1811,18 +1831,18 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
void BaseClass ::copyBaseInterfaces (BaseClasses * vtblInterfaces )
{
//printf("+copyBaseInterfaces(), %s\n", base ->toChars());
//printf("+copyBaseInterfaces(), %s\n", sym ->toChars());
// if (baseInterfaces_dim)
// return;
baseInterfaces_dim = base -> interfaces_dim ;
baseInterfaces_dim = sym -> interfaces_dim ;
baseInterfaces = (BaseClass * )mem .xcalloc (baseInterfaces_dim , sizeof (BaseClass ));
//printf("%s.copyBaseInterfaces()\n", base ->toChars());
//printf("%s.copyBaseInterfaces()\n", sym ->toChars());
for (size_t i = 0 ; i < baseInterfaces_dim ; i ++ )
{
BaseClass * b = & baseInterfaces [i ];
BaseClass * b2 = base -> interfaces [i ];
BaseClass * b2 = sym -> interfaces [i ];
assert (b2 -> vtbl .dim == 0 ); // should not be filled yet
memcpy (b , b2 , sizeof (BaseClass ));
Expand Down