Permalink
Browse files

Merge pull request #1781 from jpf91/fix9777

Fix issue 9777 Wrong code when calling final interface methods
  • Loading branch information...
2 parents 60733bc + f35c753 commit 1375dee59cdc795ce489985ece034fbbc75f353e @WalterBright WalterBright committed Mar 22, 2013
Showing with 78 additions and 12 deletions.
  1. +1 −1 src/aggregate.h
  2. +3 −3 src/class.c
  3. +17 −4 src/mtype.c
  4. +57 −4 test/runnable/xtest46.d
View
@@ -261,7 +261,7 @@ struct ClassDeclaration : AggregateDeclaration
virtual int isBaseInfoComplete();
Dsymbol *search(Loc, Identifier *ident, int flags);
- Dsymbol *searchBase(Loc, Identifier *ident);
+ ClassDeclaration *searchBase(Loc, Identifier *ident);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
View
@@ -979,17 +979,17 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
return s;
}
-Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
+ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
{
// Search bases classes in depth-first, left to right order
for (size_t i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = (*baseclasses)[i];
- Dsymbol *cdb = b->type->isClassHandle();
+ ClassDeclaration *cdb = b->type->isClassHandle();
if (cdb->ident->equals(ident))
return cdb;
- cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident);
+ cdb = cdb->searchBase(loc, ident);
if (cdb)
return cdb;
}
View
@@ -8487,13 +8487,26 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
// See if it's 'this' class or a base class
if (e->op != TOKtype)
{
- Dsymbol *cbase = sym->ident == ident ?
- sym : sym->searchBase(e->loc, ident);
- if (cbase)
+ if (sym->ident == ident)
{
- e = new DotTypeExp(0, e, cbase);
+ e = new DotTypeExp(0, e, sym);
return e;
}
+
+ ClassDeclaration *cbase = sym->searchBase(e->loc, ident);
+ if (cbase)
+ {
+ if (InterfaceDeclaration *ifbase = cbase->isInterfaceDeclaration())
+ {
+ e = new CastExp(0, e, ifbase->type);
+ return e;
+ }
+ else
+ {
+ e = new DotTypeExp(0, e, cbase);
+ return e;
+ }
+ }
}
if (ident == Id::classinfo)
View
@@ -4300,25 +4300,78 @@ static assert(typeof(cfunc6596).stringof == "extern (C) int()");
interface Timer
{
- final int run() { printf("Timer.run()\n"); return 1; };
+ final int run() { printf("Timer.run()\n"); fun(); return 1; };
+ int fun();
}
interface Application
{
- final int run() { printf("Application.run()\n"); return 2; };
+ final int run() { printf("Application.run()\n"); fun(); return 2; };
+ int fun();
}
class TimedApp : Timer, Application
{
+ int funCalls;
+ override int fun()
+ {
+ printf("TimedApp.fun()\n");
+ funCalls++;
+ return 2;
+ }
+}
+
+class SubTimedApp : TimedApp
+{
+ int subFunCalls;
+
+ override int fun()
+ {
+ printf("SubTimedApp.fun()\n");
+ subFunCalls++;
+ return 1;
+ }
}
void test4647()
{
- auto app = new TimedApp;
- assert(app.Timer.run() == 1); // error, no Timer property
+ //Test access to TimedApps base interfaces
+ auto app = new TimedApp();
+ assert((cast(Application)app).run() == 2);
+ assert((cast(Timer)app).run() == 1);
+ assert(app.Timer.run() == 1); // error, no Timer property
assert(app.Application.run() == 2); // error, no Application property
assert(app.run() == 1); // This would call Timer.run() if the two calls
// above were commented out
+ assert(app.funCalls == 5);
+
+ assert(app.TimedApp.fun() == 2);
+ assert(app.funCalls == 6);
+
+ //Test direct access to SubTimedApp interfaces
+ auto app2 = new SubTimedApp();
+ assert((cast(Application)app2).run() == 2);
+ assert((cast(Timer)app2).run() == 1);
+ assert(app2.Application.run() == 2);
+ assert(app2.Timer.run() == 1);
+ assert(app2.funCalls == 0);
+ assert(app2.subFunCalls == 4);
+
+ assert(app2.fun() == 1);
+ assert(app2.SubTimedApp.fun() == 1);
+ assert(app2.funCalls == 0);
+ assert(app2.subFunCalls == 6);
+
+ //Test access to SubTimedApp interfaces via TimedApp
+ auto app3 = new SubTimedApp();
+ (cast(Timer)cast(TimedApp)app3).run();
+ app3.TimedApp.Timer.run();
+ assert((cast(Application)cast(TimedApp)app3).run() == 2);
+ assert((cast(Timer)cast(TimedApp)app3).run() == 1);
+ assert(app3.TimedApp.Application.run() == 2);
+ assert(app3.TimedApp.Timer.run() == 1);
+ assert(app3.funCalls == 0);
+ assert(app3.subFunCalls == 6);
}
/***************************************************/

0 comments on commit 1375dee

Please sign in to comment.