[dmd-internals] lambdaCheckForNestedRef not catching all closure vars.

Iain Buclaw ibuclaw at ubuntu.com
Fri Apr 5 11:17:29 PDT 2013


Hi,

In the following example code:

---
import std.container;

void run (E) (lazy E expression)
{
  expression();
}

void main()
{
  Array!int a = [1, 2, 3];
  auto r = a.dup[];
  run(a.insertBefore(r, 42));
}
---

Although D main doesn't require a closure, closureVars are pushed into the
function.  GDC depends on this being correct because chains are built in
the frontend glue, as the backend can not handle the way delegates are
supposed to work, and so never builds the function frame correctly.

In the above, the following is generated (in pseudo code)

---
void main()
{
   alias (main.chain)->a a;
   Range r;    //  Should be 'alias (main.chain)->r r';

   r = dup (&a);
   try {
      run ( {.object = main.chain, .func = __dgliteral} );
   }
   finally {
      fieldDtor (r);
   }
}

int __dgliteral (void* this)
{
   Range __cpcttmp;
   __cpctor (&__cpccttmp, &r);    // Should be '__cpctor (&__cpcttmp,
((main.chain) this)->r);
   return insertBefore (((main.chain) this)->a, __cpcttmp, 42);
}
---


Reason this appears to happen is because in the stage where it converts the
following argument to a delegate:

a.insertBefore((Range __cpcttmp = __cpcttmp.__cpctor(r);\n , __cpcttmp), 42)

It does not check if the RHS of the __cpcttmp assignment has any nested
refs that could potentially need adding to the closure as well.

I've got a fix in the frontend for this, and it looks to not affect
anything in the testsuite at least.  Is it worth pushing this in for a
review?


Thanks
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-internals/attachments/20130405/c124ce6f/attachment.html>


More information about the dmd-internals mailing list