RFA: tree-nested.c

I'm getting a crash with some Objective-C code that involves "blocks".
Basically, it gets to this "walk_all_functions" call and fails:

lower_nested_functions (tree fndecl, bool skip_outermost_fndecl)
{
...
#ifdef ENABLE_LLVM
  walk_all_functions (construct_reverse_callgraph, root);
  propagate_chains (root);
#endif
...
}

The construct_reverse_callgraph calls lookup_context_for_decl, where it crashes:

lookup_context_for_decl (tree fndecl)
{
...
  slot = (struct nesting_info **) htab_find_slot (ni_map, &dummy, NO_INSERT);
  gcc_assert (slot != NULL); /* CRASHES HERE */
  return *slot;
}

construct_reverse_callgraph (tree *tp, int *walk_subtrees, void *data)
{
...
  switch (TREE_CODE (t))
    {
    case ADDR_EXPR:
...
      /* Add an edge from the callee to the caller. */
      pointer_set_insert (lookup_context_for_decl (decl)->callers, info);
      break;

    default:
...
}

What are the assumptions going into this "walk_all_functions" call?
Should the code have been placed into some nesting info slot or
something?

FYI, here's the code in question:

$ cat testcase.i
typedef struct A *ARef;
@implementation bork
- (id)B {
  __attribute__((__blocks__(byref))) bork* new = ((void *)0);
}
- (void)C {
  __attribute__((__blocks__(byref))) id var;
  [self func:^() {}];
}
@end

$ llvm-gcc -x objective-c -std=gnu99 -c testcase.i
testcase.i:9: internal compiler error: in lookup_context_for_decl, at
tree-nested.c:1680
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://developer.apple.com/bugreporter&gt; for instructions.

Thanks for any hints you can give!

-bw

What are the assumptions going into this "walk_all_functions" call?
Should the code have been placed into some nesting info slot or
something?

Hi Bill, should I think about this or is it fixed already?

D.

Hi Duncan,

I put a fix in there, and I think that it's correct, but would like a second opinion.

From what I could gather, a "block helper" function is synthesized on the fly. There are a few places in the code base, that work on nested functions, where these functions are explicitly excluded. (My understanding is that they "look" like nested functions during processing. But once they are created, the helper function can be used in more than one function. Indeed, that was the behavior I was seeing in tree-nested.c.) I simply excluded them from the LLVM-specific code in tree-nested.c.

What is that code doing? Is there a way to test it if I did something wrong?

-bw