[cfe-dev] Problem with retrieving the BinaryOperator RHS end location

Nat! via cfe-dev cfe-dev at lists.llvm.org
Sun May 5 05:45:07 PDT 2019


I accidentally added some garbage in the middle of the source while 
writing the mail, here is the corrected source.

Sorry for that.


```

//------------------------------------------------------------------------------ 

// Tooling sample. Demonstrates:
//
// * How to write a simple source tool using libTooling.
// * How to use RecursiveASTVisitor to find interesting AST nodes.
// * How to use the Rewriter API to rewrite the source code.
//
// Eli Bendersky (eliben at gmail.com)
// This code is in the public domain
//------------------------------------------------------------------------------ 

#include <sstream>
#include <string>

#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;

static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");

// By implementing RecursiveASTVisitor, we can specify which AST nodes
// we're interested in by overriding relevant methods.
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
public:
   MyASTVisitor(Rewriter &R) : TheRewriter(R) {}

   bool VisitMemberExpr(MemberExpr *Expr) {
     SourceManager   *SM;
     int             length;
     const char      *startBuf;
     const char      *endBuf;
     const char      *opBuf;

     SM       = &TheRewriter.getSourceMgr();
     startBuf = SM->getCharacterData( Expr->getBeginLoc());
     opBuf    = SM->getCharacterData( Expr->getOperatorLoc());
     endBuf   = SM->getCharacterData( Expr->getEndLoc());
     length   = endBuf - startBuf;

     std::string  front( startBuf, opBuf - startBuf);

     length  += Lexer::MeasureTokenLength( Expr->getEndLoc(), *SM, 
TheRewriter.getLangOpts());

     std::string  origin( startBuf, length);
     std::string  replace;

     replace = std::string( "getX(") + front + std::string( ")");

     fprintf( stderr, "rewrite: \"%s\" -> \"%s\"\n", origin.c_str(), 
replace.c_str());
     TheRewriter.ReplaceText( Expr->getBeginLoc(), length, replace);

     return true;
   }

private:
   Rewriter &TheRewriter;
};


// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
class MyASTConsumer : public ASTConsumer {
public:
   MyASTConsumer(Rewriter &R) : Visitor(R) {}

   // Override the method that gets called for each parsed top-level
   // declaration.
   bool HandleTopLevelDecl(DeclGroupRef DR) override {
     for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; 
++b) {
       // Traverse the declaration using our AST visitor.
       Visitor.TraverseDecl(*b);
       (*b)->dump();
     }
     return true;
   }

private:
   MyASTVisitor Visitor;
};

// For each source file provided to the tool, a new FrontendAction is 
created.
class MyFrontendAction : public ASTFrontendAction {
public:
   MyFrontendAction() {}
   void EndSourceFileAction() override {
     SourceManager &SM = TheRewriter.getSourceMgr();
     llvm::errs() << "** EndSourceFileAction for: "
                  << SM.getFileEntryForID(SM.getMainFileID())->getName() 
<< "\n";

     // Now emit the rewritten buffer.
TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
   }

   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                  StringRef file) 
override {
     llvm::errs() << "** Creating AST consumer for: " << file << "\n";
     TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
     return llvm::make_unique<MyASTConsumer>(TheRewriter);
   }

private:
   Rewriter TheRewriter;
};

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

   return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
}
```





More information about the cfe-dev mailing list