clang-tools  7.0.0
FindAllSymbolsMain.cpp
Go to the documentation of this file.
1 //===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "FindAllSymbolsAction.h"
11 #include "STLPostfixHeaderMap.h"
12 #include "SymbolInfo.h"
13 #include "SymbolReporter.h"
14 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 #include "clang/ASTMatchers/ASTMatchers.h"
16 #include "clang/Frontend/CompilerInstance.h"
17 #include "clang/Frontend/FrontendActions.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Tooling/CommonOptionsParser.h"
20 #include "clang/Tooling/Tooling.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/ThreadPool.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <map>
31 #include <mutex>
32 #include <set>
33 #include <string>
34 #include <system_error>
35 #include <vector>
36 
37 using namespace clang::tooling;
38 using namespace llvm;
40 
41 // Apply a custom category to all command-line options so that they are the
42 // only ones displayed.
43 static cl::OptionCategory FindAllSymbolsCategory("find_all_symbols options");
44 
45 // CommonOptionsParser declares HelpMessage with a description of the common
46 // command-line options related to the compilation database and input files.
47 // It's nice to have this help message in all tools.
48 static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
49 
50 // A help message for this specific tool can be added afterwards.
51 static cl::extrahelp MoreHelp("\nMore help text...");
52 
53 static cl::opt<std::string> OutputDir("output-dir", cl::desc(R"(
54 The output directory for saving the results.)"),
55  cl::init("."),
56  cl::cat(FindAllSymbolsCategory));
57 
58 static cl::opt<std::string> MergeDir("merge-dir", cl::desc(R"(
59 The directory for merging symbols.)"),
60  cl::init(""),
61  cl::cat(FindAllSymbolsCategory));
62 namespace clang {
63 namespace find_all_symbols {
64 
65 class YamlReporter : public SymbolReporter {
66 public:
67  void reportSymbols(StringRef FileName,
68  const SymbolInfo::SignalMap &Symbols) override {
69  int FD;
70  SmallString<128> ResultPath;
71  llvm::sys::fs::createUniqueFile(
72  OutputDir + "/" + llvm::sys::path::filename(FileName) + "-%%%%%%.yaml",
73  FD, ResultPath);
74  llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
75  WriteSymbolInfosToStream(OS, Symbols);
76  }
77 };
78 
79 bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
80  std::error_code EC;
81  SymbolInfo::SignalMap Symbols;
82  std::mutex SymbolMutex;
83  auto AddSymbols = [&](ArrayRef<SymbolAndSignals> NewSymbols) {
84  // Synchronize set accesses.
85  std::unique_lock<std::mutex> LockGuard(SymbolMutex);
86  for (const auto &Symbol : NewSymbols) {
87  Symbols[Symbol.Symbol] += Symbol.Signals;
88  }
89  };
90 
91  // Load all symbol files in MergeDir.
92  {
93  llvm::ThreadPool Pool;
94  for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd;
95  Dir != DirEnd && !EC; Dir.increment(EC)) {
96  // Parse YAML files in parallel.
97  Pool.async(
98  [&AddSymbols](std::string Path) {
99  auto Buffer = llvm::MemoryBuffer::getFile(Path);
100  if (!Buffer) {
101  llvm::errs() << "Can't open " << Path << "\n";
102  return;
103  }
104  std::vector<SymbolAndSignals> Symbols =
105  ReadSymbolInfosFromYAML(Buffer.get()->getBuffer());
106  for (auto &Symbol : Symbols) {
107  // Only count one occurrence per file, to avoid spam.
108  Symbol.Signals.Seen = std::min(Symbol.Signals.Seen, 1u);
109  Symbol.Signals.Used = std::min(Symbol.Signals.Used, 1u);
110  }
111  // FIXME: Merge without creating such a heavy contention point.
112  AddSymbols(Symbols);
113  },
114  Dir->path());
115  }
116  }
117 
118  llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
119  if (EC) {
120  llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
121  << '\n';
122  return false;
123  }
124  WriteSymbolInfosToStream(OS, Symbols);
125  return true;
126 }
127 
128 } // namespace clang
129 } // namespace find_all_symbols
130 
131 int main(int argc, const char **argv) {
132  CommonOptionsParser OptionsParser(argc, argv, FindAllSymbolsCategory);
133  ClangTool Tool(OptionsParser.getCompilations(),
134  OptionsParser.getSourcePathList());
135 
136  std::vector<std::string> sources = OptionsParser.getSourcePathList();
137  if (sources.empty()) {
138  llvm::errs() << "Must specify at least one one source file.\n";
139  return 1;
140  }
141  if (!MergeDir.empty()) {
143  return 0;
144  }
145 
147 
148  auto Factory =
149  llvm::make_unique<clang::find_all_symbols::FindAllSymbolsActionFactory>(
151  return Tool.run(Factory.get());
152 }
Some operations such as code completion produce a set of candidates.
int main(int argc, const char **argv)
bool WriteSymbolInfosToStream(llvm::raw_ostream &OS, const SymbolInfo::SignalMap &Symbols)
Write SymbolInfos to a stream (YAML format).
Definition: SymbolInfo.cpp:119
std::vector< HeaderHandle > Path
std::vector< SymbolAndSignals > ReadSymbolInfosFromYAML(llvm::StringRef Yaml)
Read SymbolInfos from a YAML document.
Definition: SymbolInfo.cpp:129
static cl::OptionCategory FindAllSymbolsCategory("find_all_symbols options")
clang::find_all_symbols::SymbolInfo SymbolInfo
static cl::extrahelp MoreHelp("\ore help text...")
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage)
PathRef FileName
static cl::opt< std::string > MergeDir("merge-dir", cl::desc(R"( The directory for merging symbols.)"), cl::init(""), cl::cat(FindAllSymbolsCategory))
static cl::opt< std::string > OutputDir("output-dir", cl::desc(R"( The output directory for saving the results.)"), cl::init("."), cl::cat(FindAllSymbolsCategory))
An interface for classes that collect symbols.
bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const HeaderMapCollector::RegexHeaderMap * getSTLPostfixHeaderMap()
std::map< SymbolInfo, Signals > SignalMap
Definition: SymbolInfo.h:69
Describes a named symbol from a header.
Definition: SymbolInfo.h:28