One thought about llvm::df_iterator

Hi @all,

Disclaimer: altough I know this is clang and not llvm, I'm sure there is some interest in the topic on this list.

While trying to eleminate as much std::tr1::function as possible I stumbled over a design flaw in llvm::df_iterator.
Consider the following code:

void for_all_stmts(Stmt* S, const std::tr1::function<void(Stmt*)>& fn)
{
  if (S)
  {
    fn(S);
    for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
    {
      for_all_stmts(*i, fn);
    }
  }
}

In a first step I want to replace this with:

void for_all_stmts(Stmt* S, const std::tr1::function<void(Stmt*)>& fn)
{
  for (llvm::df_iterator<Stmt*> i = llvm::df_begin(S), e = llvm::df_end(S); i != e; ++i)
  {
    if (*i) fn(*i);
  }
}

However if fn replaces childrens of a just processed statement (which happens a lot), the iteration may crash. Looking at df_iterator reveals the reason: the first child of a particular statement is stored too early for this kind of usage. IMHO this could be fixed by delaying the computation of the first child until it's needed (that is in the preincrement operator). The only open question would be: how do we mark the children iterator invalid before its first use.

Best
Olaf Krzikalla