make_early_inc_range(M) does not work as expected: infinite loop when inserting a new function

Hi all. I want to iterate through all the functions and clone them. make_early_inc_range should allow to insert new elements in the list without invalidating iterators. However, this code leads to an infinite loop:

for (Function &F : make_early_inc_range(M)) {
  Function *NF = Function::Create(cast<FunctionType>(F.getValueType()), F.getLinkage(),
                                  F.getAddressSpace(), F.getName(), &M);
  ...
}

Meanwhile, this code works as expected:

SmallVector<Function*> FList;
for (auto &F: M)
  FList.push_back(&F);

for (Function *F : FList) {
  Function *NF = Function::Create(cast<FunctionType>(F->getValueType()), F->getLinkage(),
                                                     F->getAddressSpace(), F->getName(), &M);
  ...
}

LLVM 15.0.3

make_early_inc_range does not prevent iterator invalidation in the absolute actually. If you were iterating a vector and modifying it by resizing it, it would be unsafe. It helps with linked list though by pre-incrementing.

In your case the problem is different: you’re inserting the new function at the end of the module, so if you have more than 2 functions in the module you get an infinite loop…

// iteration 0
func A(); 
func B(); <- iterator while processing A
func A_inserted(); <- inserted during current iteration
// iteration 1
func A(); 
func B();
func A_inserted(); <- iterator while processing B
func B_inserted(); <- inserted during current iteration

1 Like