Skip to content

Commit

Permalink
Merge pull request #4789 from 9rnsr/fix6417
Browse files Browse the repository at this point in the history
Issue 6417 - Wrong context for nested functions in virtual class member function contracts
  • Loading branch information
WalterBright committed Jul 5, 2015
2 parents 692c7a5 + b2f1367 commit 82f91e2
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/toir.c
Expand Up @@ -96,14 +96,36 @@ elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd)
elem *ethis;
FuncDeclaration *thisfd = irs->getFunc();
Dsymbol *fdparent = fd->toParent2();
Dsymbol *fdp = fdparent;

/* These two are compiler generated functions for the in and out contracts,
* and are called from an overriding function, not just the one they're
* nested inside, so this hack is so they'll pass
*/
if (fdparent != thisfd && (fd->ident == Id::require || fd->ident == Id::ensure))
{
FuncDeclaration *fdthis = thisfd;
for (size_t i = 0; ; )
{
if (i == fdthis->foverrides.dim)
{
if (i == 0)
break;
fdthis = fdthis->foverrides[0];
i = 0;
continue;
}
if (fdthis->foverrides[i] == fdp)
{
fdparent = thisfd;
break;
}
i++;
}
}

//printf("[%s] getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", loc.toChars(), thisfd->toPrettyChars(), fd->toPrettyChars(), fdparent->toPrettyChars());
if (fdparent == thisfd ||
/* These two are compiler generated functions for the in and out contracts,
* and are called from an overriding function, not just the one they're
* nested inside, so this hack is so they'll pass
*/
fd->ident == Id::require || fd->ident == Id::ensure)
if (fdparent == thisfd)
{
/* Going down one nesting level, i.e. we're calling
* a nested function from its enclosing function.
Expand Down Expand Up @@ -191,7 +213,7 @@ elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd)
if (!ad)
{
Lnoframe:
irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars());
irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toPrettyChars());
return el_long(TYnptr, 0); // error recovery
}
ClassDeclaration *cd = ad->isClassDeclaration();
Expand Down
35 changes: 35 additions & 0 deletions test/runnable/testcontracts.d
Expand Up @@ -356,6 +356,40 @@ class Foo5204 : IFoo5204
Foo5204 bar() { return null; }
}

/*******************************************/
// 6417

class Bug6417
{
void bar()
in
{
int i = 14;
assert(i == 14);
auto dg = (){
//printf("in: i = %d\n", i);
assert(i == 14, "in contract failure");
};
dg();
}
out
{
int j = 10;
assert(j == 10);
auto dg = (){
//printf("out: j = %d\n", j);
assert(j == 10, "out contract failure");
};
dg();
}
body {}
}

void test6417()
{
(new Bug6417).bar();
}

/*******************************************/
// 7218

Expand Down Expand Up @@ -647,6 +681,7 @@ int main()
test8();
test9();
test4785();
test6417();
test7218();
test8073();
test8093();
Expand Down

0 comments on commit 82f91e2

Please sign in to comment.