Search code examples
c++clangllvmlibtooling

Replacements returning empty map in clang RefactoringTool


I have a MatchFinder defined as:

MatchFinder Finder;
Finder.addMatcher(FunctionCallMatcher, &printer);

And the DeclarationMatcher, and the MatchCallback are as below:

DeclarationMatcher FunctionCallMatcher = functionDecl(isDefinition()).bind("func");

class FuncPrinter : public MatchFinder::MatchCallback {
public :
  FuncPrinter(){Replace = new Replacements;}
  FuncPrinter(Replacements *Replace) : Replace(Replace) {}
  virtual void run(const MatchFinder::MatchResult &Result) {
    clang::ASTContext *Context = Result.Context;

    if (const FunctionDecl *FS = Result.Nodes.getNodeAs<clang::FunctionDecl>("func")) {
      FS->dump();
      SourceRange sr = FS->getSourceRange();
      std::string s = std::string("test");
      Replacement Rep(*(Result.SourceManager), sr.getEnd(), s.length(), s);
      if(llvm::Error err = Replace->add(Rep)) {

      }
    }
  }
private:
  Replacements *Replace;
};

In my main code, I execute the Frontend Action for the finder, and get the replacements:

RefactoringTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());
  FuncPrinter printer;
  MatchFinder Finder;
  Finder.addMatcher(FunctionCallMatcher, &printer);                                                                                                                            
  if (int Result = Tool.run(newFrontendActionFactory(&Finder).get())) {
    return Result;
  }
  std::map<std::string, Replacements>& reps = Tool.getReplacements();

Although I can observe that the Replace variable in the FuncPrinter get populated when the FrontendAction is executed, Tool.getReplacements() return an empty std::map<std::string, Replacements>. I would be grateful if anyone can come up with where I went wrong.


Solution

  • Managed to solve it, so posting my own solution. The problem was in using the default constructor, whereas the constructor with the FuncPrinter(reps_t *reps) does the trick.

    class FuncPrinter : public MatchFinder::MatchCallback {
      using reps_t = std::map<std::string, Replacements>;     
    public :
      FuncPrinter(reps_t *reps) : Replace(reps) {}
      virtual void run(const MatchFinder::MatchResult &Result) {
        clang::ASTContext *Context = Result.Context;
    
        if (const FunctionDecl *FS = Result.Nodes.getNodeAs<clang::FunctionDecl>("func")) {
          FS->dump();
          SourceRange sr = FS->getSourceRange();
          std::string s = std::string("test");
          Replacement Rep(*(Result.SourceManager), sr.getEnd(), s.length(), s);
          Replace->insert(std::pair<std::string,Replacements>(path, Replacements(Rep)));
        }
      }
    private:
      reps_t *Replace;
    };