Bug 3706 – delegates of interfaces with multiple inheritance fail

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2010-01-14T12:42:00Z
Last change time
2015-06-09T05:10:38Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
fawzi

Attachments

IDFilenameSummaryContent-TypeSize
550bugDelegate.dan example of the bugtext/d-source967
551bugDelegate2.da shorter exampletext/d-source571

Comments

Comment #0 by fawzi — 2010-01-14T12:42:31Z
Created attachment 550 an example of the bug Delegates of an interface that refer to methods in sub interfaces that are not the first one fail. Somehow when done through ThreadLocal variables the bug is slightly different (nothing seems to be called), whereas the other examples that I show another method get called. I set it as major because it is a subtle bug that took me very long to track down, its effects a similar to memory pollution... This is a bug in both 1.047 and 1.055
Comment #1 by fawzi — 2010-01-14T12:58:44Z
Created attachment 551 a shorter example
Comment #2 by clugdbug — 2010-07-22T12:20:12Z
Here's a slightly reduced test case. -------------- interface I{ void h(); } interface K{ void f(); } interface J:I,K {} class A:J{ void f(){ } void h(){ } } void main(){ auto a = new A(); J b = a; K c = a; assert(&b.f == &c.f); // fails: &b.f returns &a.h. }
Comment #3 by clugdbug — 2010-07-22T13:55:22Z
The problem lies in delegate expressions formed from interfaces. We need to ensure that the correct interface is used, otherwise the vtblIndex will refer to the wrong one. Applies to both D1 and D2. PATCH: expression.c, not yet fully tested in the test suite. Maybe this patch should be made in getRightThis() instead? Expression *DelegateExp::semantic(Scope *sc) { #if LOGSEMANTIC printf("DelegateExp::semantic('%s')\n", toChars()); #endif if (!type) { e1 = e1->semantic(sc); type = new TypeDelegate(func->type); type = type->semantic(loc, sc); AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); if (func->needThis()) e1 = getRightThis(loc, sc, ad, e1, func); + if (ad && ad->type != e1->type) + { // A downcast is required for interfaces + e1 = new CastExp(loc, e1, ad->type); + e1 = e1->semantic(sc); + } } return this; }
Comment #4 by bugzilla — 2010-07-24T19:10:38Z