Plugin: Rewriter does not work?

Hi,

in my clang plugin I want to rewrite certain parts of the translation unit. In the MyVisitor I'll setup a rewriter and try to replace for e.g. the name of a function decl:

TheRewriter.ReplaceText(funcDecl->getLocation(), funcName.length(), "myreturn");

This code is excecuted but the chnage is not visible in the generated assmebler file.

Any idea what I am doing wrong?

Thanks

Marcel

<---snippet--->

Rewriter TheRewriter;

namespace {

     class MyVisitor : public RecursiveASTVisitor<MyVisitor> {
     private:
         ASTContext *astContext;

     public:
         explicit MyVisitor(CompilerInstance *CI) : m_diag(CI->getDiagnostics()),
             astContext(&(CI->getASTContext()))
         {
TheRewriter.setSourceMgr(astContext->getSourceManager(), astContext->getLangOpts());
         }

         bool VisitFunctionDecl(const FunctionDecl *funcDecl) {
             string funcName = funcDecl->getNameInfo().getName().getAsString();
             if (funcName == "return_fourtytwo") {
TheRewriter.ReplaceText(funcDecl->getLocation(), funcName.length(), "myreturn");
                 errs() << "Rewrote function def: " << funcName << "\n";
             }

     private:
         DiagnosticsEngine &m_diag;
     };

     class FuncDeclConsumer : public ASTConsumer {
     public:
         explicit FuncDeclConsumer(CompilerInstance *CI)
             : m_visitor(MyVisitor(CI)) {}

         // Called by the parser for each top-level declaration group.
         // Returns true to continue parsing, or false to abort parsing.
         virtual bool HandleTopLevelDecl(DeclGroupRef dg) override {
             for (Decl *decl : dg) {
                 m_visitor.TraverseDecl(decl);
             }
             return true;
         }

     private:
         MyVisitor m_visitor;
     };

     class MyInstrumentation : public PluginASTAction {
     protected:
         std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &ci,
             llvm::StringRef) override {
             return llvm::make_unique<FuncDeclConsumer>(&ci);
         }

         PluginASTAction::ActionType getActionType() override {
             return AddAfterMainAction;
         }
     };
} // end namespace

static FrontendPluginRegistry::Add<MyInstrumentation>
X("check-parameter-names", "check for parameter names mismatch");

Hi,

I need some advice. I want to create a plugin for clang which for e.g. alters the argument list of specific functions and insert valid c statements at certain points in the translation unit.

The Rewriter class is changing the source code as expected and I can write it to a temporary file and start the clang compiler without my plugin again.

Is there a better solution like calling clang with my plugin and apply my changes on the fly?

plugin. Is this correct?

Thanks

Marcel

From a quick look at your code MyInstrumentation::getActionType is
returning AddAfterMainAction which means it's getting run after code
generation. To run it before code generation change that to
AddBeforeMainAction, which should hopefully make it do what you want.

John

Good point. I'll changed it, but I think the Rewriter will not change the AST and therefore my changes are ignored by further compiler stages.

Is there a mechanism to rebuild the AST from RewriteBuffer?

Thanks

Marcel

I'm guessing that probably you'd be better off modifying the AST directly
instead of doing a source rewrite then reparsing that, e.g. in the example
given you'd change VisitFunctionDecl to take a non-const FunctionDecl and
call funcDecl->setDeclName(). I have no experience with Rewriter or
RecursiveASTVisitor though, so that maybe isn't the best way to do it.

John