ioeric updated this revision to Diff 58081.
ioeric added a comment.

- removed redundant dependency for findAllSymbols.


http://reviews.llvm.org/D20496

Files:
  include-fixer/CMakeLists.txt
  include-fixer/find-all-symbols/FindAllMacros.cpp
  include-fixer/find-all-symbols/FindAllMacros.h
  include-fixer/find-all-symbols/FindAllSymbols.cpp
  include-fixer/find-all-symbols/FindAllSymbols.h
  include-fixer/find-all-symbols/SymbolReporter.h
  include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
  include-fixer/find-stl-symbols/CMakeLists.txt
  include-fixer/find-stl-symbols/FindSTLSymbolsAction.cpp
  include-fixer/find-stl-symbols/FindSTLSymbolsAction.h
  include-fixer/find-stl-symbols/STLSymbolsFinder.cpp
  include-fixer/find-stl-symbols/STLSymbolsFinder.h
  include-fixer/find-stl-symbols/tool/CMakeLists.txt
  include-fixer/find-stl-symbols/tool/FindSTLSymbolsMain.cpp
  unittests/include-fixer/CMakeLists.txt
  unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
  unittests/include-fixer/find-stl-symbols/CMakeLists.txt
  unittests/include-fixer/find-stl-symbols/STLSymbolsFinderTests.cpp

Index: unittests/include-fixer/find-stl-symbols/STLSymbolsFinderTests.cpp
===================================================================
--- /dev/null
+++ unittests/include-fixer/find-stl-symbols/STLSymbolsFinderTests.cpp
@@ -0,0 +1,115 @@
+//===-- STLSymbolsFinderTests.cpp - STLSymbolsFinder unittests---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindSTLSymbolsAction.h"
+#include "STLSymbolsFinder.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+#include <string>
+#include <vector>
+
+using namespace clang::find_all_symbols;
+
+namespace clang {
+namespace find_stl_symbols {
+namespace {
+
+class TestSymbolReporter : public SymbolReporter {
+public:
+  ~TestSymbolReporter() override {}
+
+  void reportSymbol(llvm::StringRef, const SymbolInfo &Symbol,
+                    const Args *) override {
+    Symbols.push_back(Symbol);
+  }
+
+  bool hasSymbol(const SymbolInfo &Symbol) const {
+    for (const auto &S : Symbols) {
+      if (S == Symbol)
+        return true;
+    }
+    return false;
+  }
+
+private:
+  std::vector<SymbolInfo> Symbols;
+};
+
+class STLSymbolsFinderTest : public ::testing::Test {
+public:
+  STLSymbolsFinderTest()
+      : InMemoryFS(new vfs::InMemoryFileSystem),
+        Files(new FileManager(FileSystemOptions(), InMemoryFS)) {}
+
+protected:
+  bool hasSymbol(const SymbolInfo &Symbol) {
+    return Reporter.hasSymbol(Symbol);
+  }
+
+  bool runSTLSymbolsFinder(
+      const std::vector<std::pair<std::string, std::string>> &Contents) {
+    llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+        new vfs::InMemoryFileSystem);
+    llvm::IntrusiveRefCntPtr<FileManager> Files(
+        new FileManager(FileSystemOptions(), InMemoryFileSystem));
+
+    // Add headers into InMemoryFileSystem so that Finder and ClangTool can read
+    // files from the (virtual) include directory.
+    for (const auto &Pair : Contents) {
+      InMemoryFileSystem->addFile(
+          Pair.first, 0, llvm::MemoryBuffer::getMemBuffer(Pair.second));
+    }
+
+    STLSymbolsFinder Finder(*Files, kIncludePath);
+    Finder.run(&Reporter);
+    return true;
+  }
+
+  TestSymbolReporter Reporter;
+  llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFS;
+  llvm::IntrusiveRefCntPtr<FileManager> Files;
+  std::string kIncludePath = "/include/";
+};
+
+TEST_F(STLSymbolsFinderTest, FindInFakeLibrary) {
+  std::vector<std::pair<std::string, std::string>> Contents;
+  Contents.emplace_back(kIncludePath + "a",
+                        "#include <internal/a_1.h>\nclass A {};");
+  Contents.emplace_back(kIncludePath + "b", "#include <internal/b_1.h>");
+  Contents.emplace_back(kIncludePath + "internal/a_1.h",
+                        "#include <internal/a_2.h>");
+  Contents.emplace_back(kIncludePath + "internal/a_2.h",
+                        "#include <internal/common.h>");
+  Contents.emplace_back(kIncludePath + "internal/b_1.h",
+                        "#include <internal/common.h>\nclass B{};");
+  // struct Common is included by both a.h and b.h, but b.h has smaller
+  // include depth, so the file path for struct Common will be b.h.
+  Contents.emplace_back(kIncludePath + "internal/common.h",
+                        "struct Common {};");
+
+  runSTLSymbolsFinder(Contents);
+
+  SymbolInfo Symbol =
+      SymbolInfo("A", SymbolInfo::SymbolKind::Class, "a", 2, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+
+  Symbol = SymbolInfo("B", SymbolInfo::SymbolKind::Class, "b", 2, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+
+  Symbol = SymbolInfo("Common", SymbolInfo::SymbolKind::Class, "b", 1, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+}
+
+} // anonymous namespace
+} // namespace find_stl_symbols
+} // namespace clang
Index: unittests/include-fixer/find-stl-symbols/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/include-fixer/find-stl-symbols/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(INCLUDE_FIXER_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../../include-fixer/find-stl-symbols REALPATH)
+include_directories(
+  ${INCLUDE_FIXER_SOURCE_DIR}
+  )
+
+add_extra_unittest(FindSTLSymbolsTests
+  STLSymbolsFinderTests.cpp
+  )
+
+target_link_libraries(FindSTLSymbolsTests
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  findSTLSymbols
+  )
Index: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===================================================================
--- unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -37,8 +37,8 @@
 public:
   ~TestSymbolReporter() override {}
 
-  void reportSymbol(llvm::StringRef FileName,
-                    const SymbolInfo &Symbol) override {
+  void reportSymbol(llvm::StringRef FileName, const SymbolInfo &Symbol,
+                    const Args *) override {
     Symbols.push_back(Symbol);
   }
 
Index: unittests/include-fixer/CMakeLists.txt
===================================================================
--- unittests/include-fixer/CMakeLists.txt
+++ unittests/include-fixer/CMakeLists.txt
@@ -26,3 +26,4 @@
   )
 
 add_subdirectory(find-all-symbols)
+add_subdirectory(find-stl-symbols)
Index: include-fixer/find-stl-symbols/tool/FindSTLSymbolsMain.cpp
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/tool/FindSTLSymbolsMain.cpp
@@ -0,0 +1,87 @@
+//===-- FindSTLSymbolsMain.cpp - find stl symbols tool ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file This file implements a find-stl-symbols tool that extract all symbols
+///  from C++ standard library and replaces symbols' include header with header
+///  names that can be #include'd.
+///
+///  For example, the file path of symbol "vector" will be "vector" instead of
+///  something like "/usr/include/c++/.../vector" when running find-all-symbols.
+///
+///  NOTE: please run this tool under llvm/build/dir/bin.
+//===----------------------------------------------------------------------===//
+
+#include "STLSymbolsFinder.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace llvm;
+using namespace clang;
+using SymbolInfo = clang::find_all_symbols::SymbolInfo;
+
+static cl::opt<std::string>
+    CXXIncludePath("i", cl::desc("C++ standard library include path. Headers "
+                                 "under this directory will be processed."),
+                   cl::init(""), cl::value_desc("libc++ include path"));
+
+static cl::opt<std::string>
+    OutputFile("o", cl::desc("The file path for saving the results."),
+               cl::init("stl-symbols.yaml"),
+               cl::value_desc("output-file.yaml"));
+
+static cl::opt<bool> Verbose("v", cl::desc("Verbose mode."), cl::init(false));
+
+namespace clang {
+namespace find_stl_symbols {
+
+class STLYamlReporter : public find_all_symbols::SymbolReporter {
+public:
+  explicit STLYamlReporter(StringRef OutputFile) : OutputFile(OutputFile) {}
+
+  ~STLYamlReporter() override {
+    int FD;
+    auto ErrCode =
+        llvm::sys::fs::openFileForWrite(OutputFile, FD, sys::fs::F_None);
+    if (ErrCode) {
+      llvm::errs() << ErrCode.message();
+      return;
+    }
+    llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true);
+    WriteSymbolInfosToStream(OS, Symbols);
+  }
+
+  void reportSymbol(StringRef, const SymbolInfo &Symbol,
+                    const Args *) override {
+    Symbols.insert(Symbol);
+  }
+
+private:
+  std::string OutputFile;
+  std::set<SymbolInfo> Symbols;
+};
+
+} // namespace find_stl_symbols
+} // namespace clang
+
+int main(int argc, const char **argv) {
+  cl::ParseCommandLineOptions(argc, argv);
+  if (CXXIncludePath.empty()) {
+    llvm::errs() << "C++ standard library include path is not provided.\n";
+    return 1;
+  }
+  find_stl_symbols::STLYamlReporter Reporter(OutputFile);
+
+  llvm::IntrusiveRefCntPtr<FileManager> Files(
+      new FileManager(FileSystemOptions()));
+  find_stl_symbols::STLSymbolsFinder Finder(*Files, CXXIncludePath, Verbose);
+  Finder.run(&Reporter);
+  return 0;
+}
Index: include-fixer/find-stl-symbols/tool/CMakeLists.txt
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/tool/CMakeLists.txt
@@ -0,0 +1,11 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(find-stl-symbols FindSTLSymbolsMain.cpp)
+target_link_libraries(find-stl-symbols
+
+  clangBasic
+  clangFrontend
+  clangLex
+  clangTooling
+  findSTLSymbols
+  )
Index: include-fixer/find-stl-symbols/STLSymbolsFinder.h
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/STLSymbolsFinder.h
@@ -0,0 +1,104 @@
+//===-- STLSymbolsFinder.h - find libc++ symbols ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_STL_SYMBOLS_FINDER_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_STL_SYMBOLS_FINDER_H
+
+#include "../find-all-symbols/SymbolInfo.h"
+#include "../find-all-symbols/SymbolReporter.h"
+
+namespace clang {
+
+class FileManager;
+
+namespace find_stl_symbols {
+
+/// Find all symbols from C++ standard library and finds the appropriate
+/// #include path for each symbol.
+///
+/// To decide which symbols can be #include'd from each headear, we run
+/// FindSTLSymbolsAction on each header to retrieve all symbols in the
+/// translation unit. We can say these symbols can be #include'd via
+/// corresponding header, so we can replace the file_path for these symbols with
+/// the header name.
+///
+/// However, a single symbol can be #include'd via multiple #include headers,
+/// some of which might transitively #include the symbol by #including other top
+/// level headers. For example, the symbol "vector" can be #include'd with
+/// headers <queue>, <algorithm>, and of course <vector> itself. It makes no
+/// sense to suggest <queue> when we #include_fix "vector". The trick we use to
+/// prevent this is to consider the include depth, which is the number of
+/// transitive #include's from the top-level header to header that a symbol is
+/// actually declared. The header that #include's a symbol with the smallest
+/// include path is chosen to be the #include header for that symbol. For
+/// example, although "vector" can be #include'd with either <queue> or
+/// <vector>, we choose <vector> to be the #include header for "vector" because
+/// <vector> has smaller include depth for "vector" than <queue> since  <queue>
+/// transitively #include's "vector" via <vector>.
+class STLSymbolsFinder {
+public:
+  /// \param Files FileManager.
+  /// \param CXXIncludePath The directory under which the STL symbols are to be
+  /// retrieved.
+  /// \param Verbose Run clang tool in verbose mode.
+  STLSymbolsFinder(FileManager &Files, const std::string &CXXIncludePath,
+                   bool Verbose = false);
+
+  /// Run the finder and send all STL symbols to the \p OutputReporter after
+  /// processing all headers.
+  /// \param OutpuReporter The reporter to which finder reports final results.
+  void run(find_all_symbols::SymbolReporter *OutputReporter);
+
+private:
+  bool findSymbolsInHeader(llvm::StringRef Header);
+
+  // Stores all symbols and their include_depth. Only outputs symbol information
+  // after processing all headers from C++ standard library - for each symbol,
+  // the header that has the smallest include depth is chosen to be its
+  // FilePath.
+  // The result symbols can be retrived by calling
+  // `calculateHeadersAndReportAll` by providing an `OutputReporter`.
+  class STLReporter : public find_all_symbols::SymbolReporter {
+  public:
+    // A map from SymbolInfo to <header name, include depth> pair.
+    // We always stores the header with the smallest include depth for each
+    // symbol.
+    typedef std::map<find_all_symbols::SymbolInfo, std::pair<std::string, int>>
+        SymbolToHeaderMap;
+
+    void setCurrentHeader(llvm::StringRef Header) { this->Header = Header; }
+
+    void reportSymbol(llvm::StringRef FileName,
+                      const find_all_symbols::SymbolInfo &Symbol,
+                      const Args *ExtraArgs = nullptr) override;
+
+    // The result symbols are redirected to \p OutputReporter in the end.
+    void calculateHeadersAndReportAll(
+        find_all_symbols::SymbolReporter *OutputReporter);
+
+  private:
+    SymbolToHeaderMap SymbolMap;
+    // The STL header from which the symbol is included. This will be updated
+    // for each header run.
+    std::string Header;
+  };
+
+  FileManager &Files;
+  /// The directory under which the STL symbols are to be retrieved.
+  std::string CXXIncludePath;
+  /// All symbols collected are stored in this reporter before final processing.
+  STLReporter Reporter;
+  /// Wether to run clang tool in verbose mode.
+  bool Verbose;
+};
+
+} // namespace find_stl_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_STL_SYMBOLS_FINDER_H
Index: include-fixer/find-stl-symbols/STLSymbolsFinder.cpp
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/STLSymbolsFinder.cpp
@@ -0,0 +1,108 @@
+//===-- STLSymbolsFinder.cpp - find libc++ symbols --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "STLSymbolsFinder.h"
+#include "FindSTLSymbolsAction.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Debug.h"
+#include <utility>
+
+#define DEBUG_TYPE "find-stl-symbols"
+
+using namespace clang::find_all_symbols;
+using namespace clang::tooling;
+using namespace llvm;
+
+namespace clang {
+namespace find_stl_symbols {
+
+STLSymbolsFinder::STLSymbolsFinder(FileManager &Files,
+                                   const std::string &CXXIncludePath,
+                                   bool Verbose)
+    : Files(Files), CXXIncludePath(CXXIncludePath), Verbose(Verbose) {
+  if (*CXXIncludePath.rbegin() != '/')
+    this->CXXIncludePath.push_back('/');
+}
+
+void STLSymbolsFinder::STLReporter::reportSymbol(
+    llvm::StringRef FileName, const SymbolInfo &Symbol,
+    const SymbolReporter::Args *ExtraArgs) {
+  assert(ExtraArgs && "Expecting include depth in extra args.");
+  int IncludeDepth = ExtraArgs->Arg1;
+  auto Iter = SymbolMap.find(Symbol);
+  if (Iter == SymbolMap.end() || (IncludeDepth < Iter->second.second)) {
+    SymbolMap[Symbol] = std::make_pair(Header, IncludeDepth);
+  }
+}
+
+void STLSymbolsFinder::STLReporter::calculateHeadersAndReportAll(
+    SymbolReporter *OutputReporter) {
+  std::set<SymbolInfo> Results;
+  for (const auto &Entry : SymbolMap) {
+    const auto &Symbol = Entry.first;
+    SymbolInfo NewSymbol(Symbol.getName(), Symbol.getSymbolKind(),
+                         Entry.second.first, Symbol.getLineNumber(),
+                         Symbol.getContexts());
+    OutputReporter->reportSymbol(NewSymbol.getFilePath(), NewSymbol);
+  }
+}
+
+bool STLSymbolsFinder::findSymbolsInHeader(llvm::StringRef Header) {
+  Reporter.setCurrentHeader(Header);
+  const std::string kIncludePathOption = "-I" + CXXIncludePath;
+  DEBUG(llvm::errs() << "Processing header " << Header << "\n");
+
+  auto FS = Files.getVirtualFileSystem();
+  std::string MainFile = (Header + ".cc").str();
+  std::vector<std::string> Args = {
+      std::string("FindSTLSymbols"), std::string("-fsyntax-only"),
+      std::string("-std=c++11"), kIncludePathOption, MainFile};
+  if (Verbose)
+    Args.push_back("-v");
+  tooling::ToolInvocation Invocation(Args, new FindSTLSymbolsAction(&Reporter),
+                                     &Files);
+  // Header itself (without .h extension) does not compile. Walk around this
+  // by including the header in a dummy main file.
+  std::string Code =
+      ("#include <" + Header + ">\nint main() { return 0; }").str();
+  Invocation.mapVirtualFile(MainFile, Code);
+  return Invocation.run();
+}
+
+// Get all files under `CXXIncludePath` and call `findSymbolsInHeader` on each
+// of them.
+void STLSymbolsFinder::run(SymbolReporter *OutputReporter) {
+  std::error_code EC;
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = Files.getVirtualFileSystem();
+  DEBUG(llvm::errs() << "Checking CXXIncludePath " << CXXIncludePath << "\n";);
+  auto File = FS->dir_begin(CXXIncludePath, EC);
+  vfs::directory_iterator FileEnd;
+  while (File != FileEnd && !EC) {
+    DEBUG(llvm::errs() << "Checking " << File->getName() << "\n";);
+    if (File->getType() == sys::fs::file_type::regular_file) {
+      if (!findSymbolsInHeader(sys::path::filename(File->getName()))) {
+        llvm::errs() << "Failed processing " << File->getName() << "\n";
+      }
+    }
+
+    File.increment(EC);
+  }
+  if (EC) {
+    llvm::errs() << EC.message() << "\n";
+    return;
+  }
+  Reporter.calculateHeadersAndReportAll(OutputReporter);
+}
+
+} // namespace find_stl_symbols
+} // namespace clang
Index: include-fixer/find-stl-symbols/FindSTLSymbolsAction.h
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/FindSTLSymbolsAction.h
@@ -0,0 +1,70 @@
+//===-- FindSTLSymbolsAction.h - find STL symbols ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_FIND_STL_SYMBOLS_ACTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_FIND_STL_SYMBOLS_ACTION_H
+
+#include "../find-all-symbols/FindAllMacros.h"
+#include "../find-all-symbols/FindAllSymbols.h"
+#include "../find-all-symbols/SymbolInfo.h"
+#include "../find-all-symbols/SymbolReporter.h"
+#include "clang/Frontend/FrontendAction.h"
+
+namespace clang {
+namespace find_stl_symbols {
+
+/// A `FrontendAction` that finds symbols exported by top-level STL headers and
+/// reports then to the reporter provided.
+/// The include depth (the number of transitive #include's from the top-level
+/// header to the header in which a symbols is declaraed) for each symbol is
+/// reported as an extra argument.
+class FindSTLSymbolsAction : public clang::ASTFrontendAction {
+public:
+  FindSTLSymbolsAction(find_all_symbols::SymbolReporter *Reporter)
+      : Reporter(Reporter), MatchFinder(), Matcher(Reporter) {
+    Matcher.registerMatchers(&MatchFinder);
+  }
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &Compiler,
+                    StringRef InFile) override;
+
+private:
+  // Overrides reportDecl so that the include depth can be retrieved.
+  class FindSTLSymbols : public find_all_symbols::FindAllSymbols {
+  public:
+    explicit FindSTLSymbols(find_all_symbols::SymbolReporter *Reporter)
+        : FindAllSymbols(Reporter) {}
+
+  private:
+    void reportDecl(const SourceManager &SM, const clang::NamedDecl *ND,
+                    const find_all_symbols::SymbolInfo &Symbol) override;
+  };
+
+  // Overrides reportMacros so that the include depth can be retrieved.
+  class FindSTLMacros : public find_all_symbols::FindAllMacros {
+  public:
+    explicit FindSTLMacros(find_all_symbols::SymbolReporter *Reporter,
+                           SourceManager *SM)
+        : FindAllMacros(Reporter, SM) {}
+
+  private:
+    void reportMacro(const Token &MacroNameTok,
+                     const find_all_symbols::SymbolInfo &Symbol) override;
+  };
+
+  find_all_symbols::SymbolReporter *const Reporter;
+  clang::ast_matchers::MatchFinder MatchFinder;
+  FindSTLSymbols Matcher;
+};
+
+} // namespace find_stl_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_STL_SYMBOLS_FIND_STL_SYMBOLS_ACTION_H
Index: include-fixer/find-stl-symbols/FindSTLSymbolsAction.cpp
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/FindSTLSymbolsAction.cpp
@@ -0,0 +1,56 @@
+//===-- FindSTLSymbolsAction.cpp - find libc++ symbols ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindSTLSymbolsAction.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::find_all_symbols;
+
+namespace clang {
+namespace find_stl_symbols {
+
+std::unique_ptr<clang::ASTConsumer>
+FindSTLSymbolsAction::CreateASTConsumer(clang::CompilerInstance &Compiler,
+                                        StringRef InFile) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      llvm::make_unique<FindSTLMacros>(Reporter, &Compiler.getSourceManager()));
+  return MatchFinder.newASTConsumer();
+}
+
+static int calculateIncludeDepth(const SourceManager &SM, SourceLocation Loc) {
+  int Result = 0;
+  while (true) {
+    auto Fid = SM.getFileID(Loc);
+    Loc = SM.getIncludeLoc(Fid);
+    if (!Loc.isValid()) break;
+    Result++;
+  }
+  return Result;
+}
+
+void FindSTLSymbolsAction::FindSTLSymbols::reportDecl(
+    const SourceManager &SM, const clang::NamedDecl *ND,
+    const SymbolInfo &Symbol) {
+  int IncludeDepth = calculateIncludeDepth(SM, ND->getLocation());
+  SymbolReporter::Args ExtraArgs{IncludeDepth};
+  Reporter->reportSymbol(SM.getFileEntryForID(SM.getMainFileID())->getName(),
+                         Symbol, &ExtraArgs);
+}
+
+void FindSTLSymbolsAction::FindSTLMacros::reportMacro(
+    const Token &MacroNameTok, const SymbolInfo &Symbol) {
+  int IncludeDepth = calculateIncludeDepth(*SM, MacroNameTok.getLocation());
+  SymbolReporter::Args ExtraArgs{IncludeDepth};
+  Reporter->reportSymbol(SM->getFileEntryForID(SM->getMainFileID())->getName(),
+                         Symbol, &ExtraArgs);
+}
+
+} // namespace find_stl_symbols
+} // namespace clang
Index: include-fixer/find-stl-symbols/CMakeLists.txt
===================================================================
--- /dev/null
+++ include-fixer/find-stl-symbols/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_clang_library(findSTLSymbols
+  FindSTLSymbolsAction.cpp
+  STLSymbolsFinder.cpp
+
+  LINK_LIBS
+  clangBasic
+  clangLex
+  clangTooling
+  findAllSymbols
+  )
+
+add_subdirectory(tool)
Index: include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
===================================================================
--- include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
+++ include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -65,11 +65,12 @@
 namespace clang {
 namespace find_all_symbols {
 
-class YamlReporter : public clang::find_all_symbols::SymbolReporter {
+class YamlReporter : public SymbolReporter {
 public:
   ~YamlReporter() override {}
 
-  void reportSymbol(StringRef FileName, const SymbolInfo &Symbol) override {
+  void reportSymbol(StringRef FileName, const SymbolInfo &Symbol,
+                    const Args *) override {
     Symbols[FileName].insert(Symbol);
   }
 
Index: include-fixer/find-all-symbols/SymbolReporter.h
===================================================================
--- include-fixer/find-all-symbols/SymbolReporter.h
+++ include-fixer/find-all-symbols/SymbolReporter.h
@@ -20,8 +20,13 @@
 public:
   virtual ~SymbolReporter() = default;
 
-  virtual void reportSymbol(llvm::StringRef FileName,
-                            const SymbolInfo &Symbol) = 0;
+  // A struct for carrying optional extra arguments for reportSymbol.
+  struct Args {
+    int Arg1;
+  };
+
+  virtual void reportSymbol(llvm::StringRef FileName, const SymbolInfo &Symbol,
+                            const Args *ExtraArgs = nullptr) = 0;
 };
 
 } // namespace find_all_symbols
Index: include-fixer/find-all-symbols/FindAllSymbols.h
===================================================================
--- include-fixer/find-all-symbols/FindAllSymbols.h
+++ include-fixer/find-all-symbols/FindAllSymbols.h
@@ -43,7 +43,11 @@
   void
   run(const clang::ast_matchers::MatchFinder::MatchResult &result) override;
 
-private:
+protected:
+  // The way SymbolInfo of a decl is reported can be overrided.
+  virtual void reportDecl(const SourceManager &SM, const clang::NamedDecl *ND,
+                          const SymbolInfo &Info);
+
   // Reporter for SymbolInfo.
   SymbolReporter *const Reporter;
   // A remapping header file collector allowing clients include a different
Index: include-fixer/find-all-symbols/FindAllSymbols.cpp
===================================================================
--- include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -9,7 +9,6 @@
 
 #include "FindAllSymbols.h"
 #include "HeaderMapCollector.h"
-#include "SymbolInfo.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Type.h"
@@ -206,21 +205,26 @@
       this);
 }
 
+void FindAllSymbols::reportDecl(const SourceManager &SM,
+                                const clang::NamedDecl *ND,
+                                const SymbolInfo &Symbol) {
+  Reporter->reportSymbol(SM.getFileEntryForID(SM.getMainFileID())->getName(),
+                         Symbol);
+}
+
 void FindAllSymbols::run(const MatchFinder::MatchResult &Result) {
   // Ignore Results in failing TUs.
   if (Result.Context->getDiagnostics().hasErrorOccurred()) {
     return;
   }
 
   const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("decl");
   assert(ND && "Matched declaration must be a NamedDecl!");
-  const SourceManager *SM = Result.SourceManager;
 
-  llvm::Optional<SymbolInfo> Symbol =
-      CreateSymbolInfo(ND, *SM, Collector);
+  SourceManager &SM = *Result.SourceManager;
+  llvm::Optional<SymbolInfo> Symbol = CreateSymbolInfo(ND, SM, Collector);
   if (Symbol)
-    Reporter->reportSymbol(
-        SM->getFileEntryForID(SM->getMainFileID())->getName(), *Symbol);
+    reportDecl(SM, ND, *Symbol);
 }
 
 } // namespace find_all_symbols
Index: include-fixer/find-all-symbols/FindAllMacros.h
===================================================================
--- include-fixer/find-all-symbols/FindAllMacros.h
+++ include-fixer/find-all-symbols/FindAllMacros.h
@@ -32,7 +32,9 @@
   void MacroDefined(const Token &MacroNameTok,
                     const MacroDirective *MD) override;
 
-private:
+protected:
+  virtual void reportMacro(const Token &MacroNameTok, const SymbolInfo &Info);
+
   // Reporter for SymbolInfo.
   SymbolReporter *const Reporter;
   SourceManager *const SM;
Index: include-fixer/find-all-symbols/FindAllMacros.cpp
===================================================================
--- include-fixer/find-all-symbols/FindAllMacros.cpp
+++ include-fixer/find-all-symbols/FindAllMacros.cpp
@@ -17,9 +17,14 @@
 namespace clang {
 namespace find_all_symbols {
 
+void FindAllMacros::reportMacro(const Token &, const SymbolInfo &Symbol) {
+  Reporter->reportSymbol(SM->getFileEntryForID(SM->getMainFileID())->getName(),
+                         Symbol);
+}
+
 void FindAllMacros::MacroDefined(const Token &MacroNameTok,
                                  const MacroDirective *MD) {
-  SourceLocation Loc = SM->getExpansionLoc(MacroNameTok.getLocation());
+  SourceLocation Loc = MacroNameTok.getLocation();
   if (Loc.isInvalid() || SM->isInMainFile(Loc))
     return;
 
@@ -38,8 +43,7 @@
                     SymbolInfo::SymbolKind::Macro, FilePath.str(),
                     SM->getSpellingLineNumber(Loc), {});
 
-  Reporter->reportSymbol(SM->getFileEntryForID(SM->getMainFileID())->getName(),
-                         Symbol);
+  reportMacro(MacroNameTok, Symbol);
 }
 
 } // namespace find_all_symbols
Index: include-fixer/CMakeLists.txt
===================================================================
--- include-fixer/CMakeLists.txt
+++ include-fixer/CMakeLists.txt
@@ -23,3 +23,4 @@
 
 add_subdirectory(tool)
 add_subdirectory(find-all-symbols)
+add_subdirectory(find-stl-symbols)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to