[cfe-dev] Reparse rewritten source

nicolas normand via cfe-dev cfe-dev at lists.llvm.org
Fri Aug 5 04:58:24 PDT 2016


Hello gentlemen,

I'm trying to write a clang tool which will instrument source code.
I'm using a FrontEndAction, an ASTConsumer and finally a
RecursiveASTVisitor, which will use a Rewriter to update the source code.

Now, I'd like to add another pass with an updated AST (which should match
the rewritten source code), and I can't get how to do this (I searched for
a long time before posting here).

I could, of course, dump new source code on the file system, and then parse
the new file. But this method is rather inelegant, probably time consuming
and inappropriate for my needs.

I'd be grateful to anyone helping me.
  Nicolas

P.S.
Here's a minimalist source code I'm based on:

static llvm::cl::OptionCategory ToolingSampleCategory("Test");

class myASTVisitor: public clang::RecursiveASTVisitor<myASTVisitor>
{
        clang::CompilerInstance& ci__;
        clang::Rewriter& rewriter__;

        public:
        myASTVisitor(clang::CompilerInstance& ci, clang::Rewriter& r):
ci__(ci), rewriter__(r) {}

        bool VisitDeclStmt(clang::DeclStmt* ds)
        {
                // Code which involves the rewriter__
                return true;
        }
};

class ASTConsumer : public clang::ASTConsumer
{
        clang::CompilerInstance& ci__;
        clang::StringRef file__;
        clang::Rewriter& rewriter__;

        public:
        ASTConsumer(clang::CompilerInstance& ci, clang::StringRef file,
clang::Rewriter& rw): ci__(ci), file__(file), rewriter__(rw) {}

        bool HandleTopLevelDecl(clang::DeclGroupRef DR) override {
                for (clang::DeclGroupRef::iterator it = DR.begin(); it !=
DR.end(); ++it) {
                        clang::FunctionDecl* fd =
clang::cast<clang::FunctionDecl>(*it);
                        if (fd != NULL) {
                                myASTVisitor visitor(ci__, rewriter__);
                                visitor.TraverseDecl(fd);
                        }
                }
                return true;
        }
};

class FrontendAction : public clang::ASTFrontendAction
{
        clang::Rewriter rewriter__;
        clang::CompilerInstance* ci__;

        public:
        FrontendAction() {}

        void EndSourceFileAction() override {

rewriter__.getEditBuffer(ci__->getSourceManager().getMainFileID()).write(llvm::outs());
                // write to stdout for now, but there (only if
appropriate), I would like
                // to run a second pass, using another
ASTVisitor/ASTConsumer
                // on the new AST from the rewritten sources
        }

        std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance& CI, clang::StringRef file)
override {
                ci__ = &CI;
                rewriter__.setSourceMgr(CI.getSourceManager(),
CI.getLangOpts());
                return std::unique_ptr<clang::ASTConsumer>(new
ASTConsumer(CI, file, rewriter__));
        }
};

int main(int argc, const char** argv)
{
        clang::tooling::CommonOptionsParser op(argc, argv,
ToolingSampleCategory);
        clang::tooling::ClangTool Tool(op.getCompilations(),
op.getSourcePathList());

        return
Tool.run(clang::tooling::newFrontendActionFactory<FrontendAction>().get());
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160805/8ce59e71/attachment.html>


More information about the cfe-dev mailing list