Rewriter::InsertText

Hi,
I’m facing strange bug with Rewriter::InsertText.
Here is the code:

void RewritingPass::Initialize(ASTContext &context)
{
this->context = &context;
SourceLocation L;
mainFileId = context.getSourceManager().getMainFileID();
rewriter = new Rewriter(context.getSourceManager(), context.getLangOptions());
const llvm::StringRef preamble(getPreamble());
if (preamble.size() > 0)
rewriter->InsertText(context.getSourceManager().getLocForStartOfFile(mainFileId), preamble, true);
}

const std::string CastRewritePass::getPreamble() const
{
return " /* cast rewrite pass */\n\n";
}

after execution of RewritingPass::Initialize preamble changed it’s not /* cast rewrite pass*/, but 0\230\bast rewrite pass*/.
I found a solvation - use not string in getPreamble, but StringRef. If i do so, it works ok.

Sergey

Сергей Филиппов <rolenof-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
writes:

[...]

void RewritingPass::Initialize(ASTContext &context)
{
this->context = &context;
SourceLocation L;
mainFileId = context.getSourceManager().getMainFileID();
rewriter = new Rewriter(context.getSourceManager(), context.getLangOptions());
const llvm::StringRef preamble(getPreamble());
if (preamble.size() > 0)
rewriter->InsertText(context.getSourceManager().getLocForStartOfFile(mainFileId), preamble, true);
}

const std::string CastRewritePass::getPreamble() const
{
return " /* cast rewrite pass */\n\n";
}

after execution of RewritingPass::Initialize preamble changed it's not /* cast rewrite pass*/, but 0\230\bast rewrite pass*/.
I found a solvation - use not string in getPreamble, but StringRef. If i do so, it works ok.

Does it also work if you give the result of getPreamble() a name?
Something like this:

   const std::string& temp(getPreamble());
   const llvm::StringRef preamble(temp);

If so, then obviously I'd suspect an issue with temporaries. (I must
admit intuitively it looks like there shouldn't be an issue with that
code, but my intuition is probably not a good guide to C++.)

StringRef is a reference to a string that exists somewhere in memory; it doesn't copy the contents of the string. In this case, getPreamble() returns a temporary, and the preamble StringRef refers to that temporary's storage. When the temporary is destroyed, the storage goes away... and you get strange behavior. Capture the result of getPreamble() in a local string, then pass that along to InsertText.

It's generally not a good idea to have a StringRef variable.

  - Doug

Thanks

Sergey