diff --git a/src/aggregate.h b/src/aggregate.h index 8cd1f5ee34e5..6791dbc2477d 100644 --- a/src/aggregate.h +++ b/src/aggregate.h @@ -284,6 +284,7 @@ class ClassDeclaration : public AggregateDeclaration bool isFuncHidden(FuncDeclaration *fd); FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); void interfaceSemantic(Scope *sc); + unsigned setBaseInterfaceOffsets(unsigned baseOffset); bool isCOMclass(); virtual bool isCOMinterface(); bool isCPPclass(); diff --git a/src/class.c b/src/class.c index 366986d2a859..b9e053d2db6a 100644 --- a/src/class.c +++ b/src/class.c @@ -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 @@ -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; +} + /**************************************** */ @@ -1613,6 +1624,9 @@ void InterfaceDeclaration::finalizeSize(Scope *sc) { structsize = Target::ptrsize * 2; sizeok = SIZEOKdone; + + // set the offset of base interfaces + setBaseInterfaceOffsets(0); } /******************************************* diff --git a/test/runnable/interface2.d b/test/runnable/interface2.d index 68f5f42a643b..b4ddae161662 100644 --- a/test/runnable/interface2.d +++ b/test/runnable/interface2.d @@ -923,7 +923,7 @@ void test27() } /*******************************************************/ -// 1747 +// 1747 & 2013 void test1747() { @@ -961,11 +961,11 @@ void test1747() assert(pia == pc + n); assert(id.mA() == 1); - //assert(id.mB() == 2); // NG (returns 1, bugzilla 2013 case) + assert(id.mB() == 2); // OK <- NG (bugzilla 2013 case) assert(id.mD() == 3); assert(ic.mA() == 1); - //assert(ic.mB() == 2); // NG (returns 1, bugzilla 2013 case) + assert(ic.mB() == 2); // OK <- NG (bugzilla 2013 case) assert(ib.mA() == 1); assert(ib.mB() == 2); // OK <- NG