<div dir="ltr"><div><font face="monospace, monospace" size="1">#include <stdio.h></font></div><div><font face="monospace, monospace" size="1">#include <string></font></div><div><font face="monospace, monospace" size="1">#include <vector></font></div><div><font face="monospace, monospace" size="1">#include <system_error></font></div><div><font face="monospace, monospace" size="1">#include <type_traits></font></div><div><font face="monospace, monospace" size="1">#include "clang/AST/AST.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Frontend/TextDiagnosticPrinter.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Tooling/CommonOptionsParser.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/ASTMatchers/ASTMatchers.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/ASTMatchers/ASTMatchFinder.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Basic/SourceManager.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Frontend/FrontendActions.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Lex/Lexer.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Tooling/CompilationDatabase.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Tooling/Refactoring.h"</font></div><div><font face="monospace, monospace" size="1">#include "clang/Tooling/Tooling.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/ADT/Twine.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/CommandLine.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/MemoryBuffer.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/Path.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/Signals.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/raw_ostream.h"</font></div><div><font face="monospace, monospace" size="1">#include "llvm/Support/TargetSelect.h"</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">using namespace llvm;</font></div><div><font face="monospace, monospace" size="1">using clang::tooling::newFrontendActionFactory;</font></div><div><font face="monospace, monospace" size="1">using clang::tooling::Replacement;</font></div><div><font face="monospace, monospace" size="1">using clang::tooling::CompilationDatabase;</font></div><div><font face="monospace, monospace" size="1">using namespace clang;</font></div><div><font face="monospace, monospace" size="1">using namespace clang::ast_matchers;</font></div><div><font face="monospace, monospace" size="1">using namespace clang::driver;</font></div><div><font face="monospace, monospace" size="1">using namespace clang::tooling;</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">static llvm::cl::OptionCategory ToolingSampleCategory("IsEmpty");</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">// Returns the text that makes up 'node' in the source.</font></div><div><font face="monospace, monospace" size="1">// Returns an empty string if the text cannot be found.</font></div><div><font face="monospace, monospace" size="1">template <typename T></font></div><div><font face="monospace, monospace" size="1">static std::string getText(const SourceManager &SourceManager, const T &Node) {</font></div><div><font face="monospace, monospace" size="1">  SourceLocation StartSpellingLocation =</font></div><div><font face="monospace, monospace" size="1">      SourceManager.getSpellingLoc(Node.getLocStart());</font></div><div><font face="monospace, monospace" size="1">  SourceLocation EndSpellingLocation =</font></div><div><font face="monospace, monospace" size="1">      SourceManager.getSpellingLoc(Node.getLocEnd());</font></div><div><font face="monospace, monospace" size="1">  if (!StartSpellingLocation.isValid() || !EndSpellingLocation.isValid()) {</font></div><div><font face="monospace, monospace" size="1">    return std::string();</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">  bool Invalid = true;</font></div><div><font face="monospace, monospace" size="1">  const char *Text =</font></div><div><font face="monospace, monospace" size="1">      SourceManager.getCharacterData(StartSpellingLocation, &Invalid);</font></div><div><font face="monospace, monospace" size="1">  if (Invalid) {</font></div><div><font face="monospace, monospace" size="1">    return std::string();</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">  std::pair<FileID, unsigned> Start =</font></div><div><font face="monospace, monospace" size="1">      SourceManager.getDecomposedLoc(StartSpellingLocation);</font></div><div><font face="monospace, monospace" size="1">  std::pair<FileID, unsigned> End =</font></div><div><font face="monospace, monospace" size="1">      SourceManager.getDecomposedLoc(Lexer::getLocForEndOfToken(</font></div><div><font face="monospace, monospace" size="1">          EndSpellingLocation, 0, SourceManager, LangOptions()));</font></div><div><font face="monospace, monospace" size="1">  if (Start.first != End.first) {</font></div><div><font face="monospace, monospace" size="1">    // Start and end are in different files.</font></div><div><font face="monospace, monospace" size="1">    return std::string();</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">  if (End.second < Start.second) {</font></div><div><font face="monospace, monospace" size="1">    // Shuffling text with macros may cause this.</font></div><div><font face="monospace, monospace" size="1">    return std::string();</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">  return std::string(Text, End.second - Start.second);</font></div><div><font face="monospace, monospace" size="1">}</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">class ColIsEmptyHandler: public MatchFinder::MatchCallback {</font></div><div><font face="monospace, monospace" size="1">public:</font></div><div><font face="monospace, monospace" size="1">  ColIsEmptyHandler(Replacements *Replace): Replace(Replace) {};</font></div><div><font face="monospace, monospace" size="1">  virtual void run(const MatchFinder::MatchResult &Result) {</font></div><div><font face="monospace, monospace" size="1">    if (const CXXMemberCallExpr *callExpr = Result.Nodes.getNodeAs<clang::CXXMemberCallExpr>("Col::IsEmptyExpr")) {</font></div><div><span style="font-family:monospace,monospace;font-size:x-small">      const std::string text = getText(*(Result.SourceManager), *callExpr); </span><br></div><div><span style="font-family:monospace,monospace;font-size:x-small">      Replacement Rep(*(Result.SourceManager), CharSourceRange::getTokenRange(SourceRange(callExpr->getCallee()->getExprLoc())), "IsEmpty");</span><br></div><div><font face="monospace, monospace" size="1">      Replace->insert(Rep);</font></div><div><font face="monospace, monospace" size="1">    }</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">private:</font></div><div><font face="monospace, monospace" size="1">  Replacements *Replace;  </font></div><div><font face="monospace, monospace" size="1">};</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">class ColIsEmptyInClassHandler: public MatchFinder::MatchCallback {</font></div><div><font face="monospace, monospace" size="1">public:</font></div><div><font face="monospace, monospace" size="1">  ColIsEmptyInClassHandler(Replacements *Replace): Replace(Replace) {};</font></div><div><font face="monospace, monospace" size="1">  virtual void run(const MatchFinder::MatchResult &Result) {</font></div><div><font face="monospace, monospace" size="1">    if (const CXXMethodDecl *decl = Result.Nodes.getNodeAs<clang::CXXMethodDecl>("Col::IsEmptyInClass")) {</font></div><div><span style="font-family:monospace,monospace;font-size:x-small">      const std::string text = getText(*(Result.SourceManager), *decl); </span><br></div><div><font face="monospace, monospace" size="1">      Replacement Rep(*(Result.SourceManager), CharSourceRange::getTokenRange(SourceRange(decl->getNameInfo().getLoc())), "IsEmpty");</font></div><div><font face="monospace, monospace" size="1">      Replace->insert(Rep);</font></div><div><font face="monospace, monospace" size="1">    }</font></div><div><font face="monospace, monospace" size="1">  }</font></div><div><font face="monospace, monospace" size="1">private:</font></div><div><font face="monospace, monospace" size="1">  Replacements *Replace;  </font></div><div><font face="monospace, monospace" size="1">};</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">int main(int argc, const char **argv) {</font></div><div><font face="monospace, monospace" size="1">  llvm::InitializeAllTargets();</font></div><div><font face="monospace, monospace" size="1">  llvm::InitializeAllTargetMCs();</font></div><div><font face="monospace, monospace" size="1">  llvm::InitializeAllAsmPrinters();</font></div><div><font face="monospace, monospace" size="1">  llvm::InitializeAllAsmParsers();<span class="" style="white-space:pre">      </span></font></div><div><font face="monospace, monospace" size="1">  CommonOptionsParser op(argc, argv, ToolingSampleCategory);</font></div><div><font face="monospace, monospace" size="1">  RefactoringTool Tool(op.getCompilations(), op.getSourcePathList());</font></div><div><font face="monospace, monospace" size="1">  // Set up AST matcher callbacks.</font></div><div><font face="monospace, monospace" size="1">  ColIsEmptyHandler HandlerForColIsEmpty(&Tool.getReplacements());</font></div><div><font face="monospace, monospace" size="1">  ColIsEmptyInClassHandler HandlerForColIsEmptyInClass(&Tool.getReplacements());</font></div><div><font face="monospace, monospace" size="1">  MatchFinder Finder;</font></div><div><font face="monospace, monospace" size="1">  Finder.addMatcher(memberCallExpr(hasDeclaration(methodDecl(</font></div><div><font face="monospace, monospace" size="1">  <span class="" style="white-space:pre">                                 </span>hasName("Empty"), ofClass(isSameOrDerivedFrom(hasName("Col")))))).bind("Col::IsEmptyExpr"), &HandlerForColIsEmpty);</font></div><div><font face="monospace, monospace" size="1">  Finder.addMatcher(methodDecl(hasName("Empty"), ofClass(isSameOrDerivedFrom(hasName("Col")))).bind("Col::IsEmptyInClass"), &HandlerForColIsEmptyInClass);</font></div><div><font face="monospace, monospace" size="1">  // Run the tool and collect a list of replacements.</font></div><div><font face="monospace, monospace" size="1">  if (int Result = Tool.runAndSave(newFrontendActionFactory(&Finder).get())) {</font></div><div><font face="monospace, monospace" size="1">    return Result;</font></div><div><font face="monospace, monospace" size="1">  }  </font></div><div><font face="monospace, monospace" size="1">  llvm::outs() << "Replacements collected by the tool:\n";</font></div><div><font face="monospace, monospace" size="1">  for (auto &r : Tool.getReplacements()) {</font></div><div><font face="monospace, monospace" size="1">    llvm::outs() << r.toString() << "\n";</font></div><div><font face="monospace, monospace" size="1">  }  </font></div><div><font face="monospace, monospace" size="1">  return 0;</font></div><div><font face="monospace, monospace" size="1">}</font></div><div class="gmail_extra"><font face="monospace, monospace" size="1"><br></font><div class="gmail_quote"><font face="monospace, monospace" size="1">On Thu, Jul 16, 2015 at 11:11 AM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br></font><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><font face="monospace, monospace" size="1">Can you post the code for the matcher?</font></div><font face="monospace, monospace" size="1"><br></font><div class="gmail_quote"><div><div class="h5"><div dir="ltr"><font face="monospace, monospace" size="1">On Thu, Jul 16, 2015 at 11:02 AM Han Wang <<a href="mailto:wanghan02@gmail.com" target="_blank">wanghan02@gmail.com</a>> wrote:<br></font></div></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><font face="monospace, monospace" size="1">Hi, </font><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">I'm using clang AST matcher tool on MAC to analyse complex files with many many headers included. It turns out that it takes more than 10 times longer than just compile the same file with clang. Is it normal or am I doing something wrong? Thanks!</font></div><div><font face="monospace, monospace" size="1"><br></font></div><div><font face="monospace, monospace" size="1">Best regards,</font></div><div><font face="monospace, monospace" size="1">Han</font></div></div></div></div><font face="monospace, monospace" size="1">
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</font></blockquote></div>
</blockquote></div><br></div></div>