Implicit cast node => ReplaceText spoils the buffer for recursive rewrite

I periodically hit that ReplaceText is buggy when hit nodes with implicit casts. This bug does not occur in single-replacement cases, it only reproduces when I try to make a recursive code rewriter. For example, I want to rewrite expressions with complex numbers from C++ to pure C using functions.

Input:


complex test_bug(complex cosTheta, complex eta, float lambda)
{
  return cosTheta + eta/lambda;
}

complex test_ok(complex cosTheta, complex eta, float lambda)
{
  return cosTheta + eta/complex(lambda);
}

Output:

complex test_bug(complex cosTheta, complex eta, float lambda)
{
  return complex_add(cosTheta,complex_div(eta,to_com))plex(lambda);
}

complex test_ok(complex cosTheta, complex eta, float lambda)
{
  return complex_add(cosTheta,complex_div(eta,to_complex(lambda)));
}

The minimal example is here

Reproduces for llvm-19 on Kubuntu 24.04 and llvm-17 on Ubuntu 22.04.

I have localized the bug a bit. I made separate brach " llvm-18-inside" where i have build this plugin within llvm in debug.

Inside VisitCXXConstructExpr i did that:

      std::string textOri = GetOriginalText(range);
      std::string textRes = "to_complex" + FunctionCallRewriteNoName(call); 
      m_rewriter.ReplaceText(range, textRes);
      std::string textRes2 = m_rewriter.getRewrittenText(range);

textOri : “lambda”
textRes : “to_complex(lambda)”
textRes2 : “to_com”

So, if we get the result right after ReplaceText, it becames broken. I’m trying to fix myself, but it is hard for me to figure out the logic which is inside. Whether we have some doc about what happens inside this function?

Thanks!