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