Plugin: Rewriter does not work?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Plugin: Rewriter does not work?

Sumner, Brian via cfe-dev
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");

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Plugin: Rewriter does not work?

Sumner, Brian via cfe-dev
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?

 From my current understanding it is not possible to alter the AST in a
plugin. Is this correct?

Thanks

Marcel


Am 19.07.2017 um 14:28 schrieb Marcel Schaible via cfe-dev:

> 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 change is not visible in the generated
> assembler 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");
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Plugin: Rewriter does not work?

Sumner, Brian via cfe-dev
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

> -----Original Message-----
> From: cfe-dev [mailto:[hidden email]] On Behalf Of
> Marcel Schaible via cfe-dev
> Sent: 19 July 2017 20:26
> To: [hidden email]
> Subject: Re: [cfe-dev] Plugin: Rewriter does not work?
>
> 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?
>
>  From my current understanding it is not possible to alter the AST in a
> plugin. Is this correct?
>
> Thanks
>
> Marcel
>
>
> Am 19.07.2017 um 14:28 schrieb Marcel Schaible via cfe-dev:
> > 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 change is not visible in the generated
> > assembler 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");
> >
> > _______________________________________________
> > cfe-dev mailing list
> > [hidden email]
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Plugin: Rewriter does not work?

Sumner, Brian via cfe-dev
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


Am 20.07.2017 um 11:36 schrieb John Brawn:

>  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
>
>> -----Original Message-----
>> From: cfe-dev [mailto:[hidden email]] On Behalf Of
>> Marcel Schaible via cfe-dev
>> Sent: 19 July 2017 20:26
>> To: [hidden email]
>> Subject: Re: [cfe-dev] Plugin: Rewriter does not work?
>>
>> 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?
>>
>>   From my current understanding it is not possible to alter the AST in a
>> plugin. Is this correct?
>>
>> Thanks
>>
>> Marcel
>>
>>
>> Am 19.07.2017 um 14:28 schrieb Marcel Schaible via cfe-dev:
>>> 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 change is not visible in the generated
>>> assembler 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");
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> [hidden email]
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Plugin: Rewriter does not work?

Sumner, Brian via cfe-dev
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

> -----Original Message-----
> From: Marcel Schaible [mailto:[hidden email]]
> Sent: 20 July 2017 11:28
> To: John Brawn
> Cc: [hidden email]; nd
> Subject: Re: [cfe-dev] Plugin: Rewriter does not work?
>
> 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
>
>
> Am 20.07.2017 um 11:36 schrieb John Brawn:
> >  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
> >
> >> -----Original Message-----
> >> From: cfe-dev [mailto:[hidden email]] On Behalf Of
> >> Marcel Schaible via cfe-dev
> >> Sent: 19 July 2017 20:26
> >> To: [hidden email]
> >> Subject: Re: [cfe-dev] Plugin: Rewriter does not work?
> >>
> >> 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?
> >>
> >>   From my current understanding it is not possible to alter the AST
> in a
> >> plugin. Is this correct?
> >>
> >> Thanks
> >>
> >> Marcel
> >>
> >>
> >> Am 19.07.2017 um 14:28 schrieb Marcel Schaible via cfe-dev:
> >>> 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 change is not visible in the
> generated
> >>> assembler 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");
> >>>
> >>> _______________________________________________
> >>> cfe-dev mailing list
> >>> [hidden email]
> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> >> _______________________________________________
> >> cfe-dev mailing list
> >> [hidden email]
> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...