summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-include-fixer/find-all-symbols
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-include-fixer/find-all-symbols')
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/CMakeLists.txt24
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.cpp69
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.h64
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp268
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.h62
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp36
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h62
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp44
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.h56
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.cpp41
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.h36
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp36
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h40
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp653
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h22
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.cpp136
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.h142
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolReporter.h29
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt24
-rw-r--r--clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp151
-rwxr-xr-xclang-tools-extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py123
21 files changed, 2118 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/CMakeLists.txt b/clang-tools-extra/clang-include-fixer/find-all-symbols/CMakeLists.txt
new file mode 100644
index 00000000000..c5fe19bfdbd
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(findAllSymbols
+ FindAllSymbols.cpp
+ FindAllSymbolsAction.cpp
+ FindAllMacros.cpp
+ HeaderMapCollector.cpp
+ PathConfig.cpp
+ PragmaCommentHandler.cpp
+ STLPostfixHeaderMap.cpp
+ SymbolInfo.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangFrontend
+ clangLex
+ clangTooling
+ )
+
+add_subdirectory(tool)
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.cpp
new file mode 100644
index 00000000000..ed1bc2f490a
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.cpp
@@ -0,0 +1,69 @@
+//===-- FindAllMacros.cpp - find all macros ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllMacros.h"
+#include "HeaderMapCollector.h"
+#include "PathConfig.h"
+#include "SymbolInfo.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Token.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+llvm::Optional<SymbolInfo>
+FindAllMacros::CreateMacroSymbol(const Token &MacroNameTok,
+ const MacroInfo *info) {
+ std::string FilePath =
+ getIncludePath(*SM, info->getDefinitionLoc(), Collector);
+ if (FilePath.empty())
+ return llvm::None;
+ return SymbolInfo(MacroNameTok.getIdentifierInfo()->getName(),
+ SymbolInfo::SymbolKind::Macro, FilePath, {});
+}
+
+void FindAllMacros::MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ if (auto Symbol = CreateMacroSymbol(MacroNameTok, MD->getMacroInfo()))
+ ++FileSymbols[*Symbol].Seen;
+}
+
+void FindAllMacros::MacroUsed(const Token &Name, const MacroDefinition &MD) {
+ if (!MD || !SM->isInMainFile(SM->getExpansionLoc(Name.getLocation())))
+ return;
+ if (auto Symbol = CreateMacroSymbol(Name, MD.getMacroInfo()))
+ ++FileSymbols[*Symbol].Used;
+}
+
+void FindAllMacros::MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MD, SourceRange Range,
+ const MacroArgs *Args) {
+ MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ MacroUsed(MacroNameTok, MD);
+}
+
+void FindAllMacros::EndOfMainFile() {
+ Reporter->reportSymbols(SM->getFileEntryForID(SM->getMainFileID())->getName(),
+ FileSymbols);
+ FileSymbols.clear();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.h
new file mode 100644
index 00000000000..5aaf388456e
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllMacros.h
@@ -0,0 +1,64 @@
+//===-- FindAllMacros.h - find all macros -----------------------*- C++ -*-===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
+
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/Lex/PPCallbacks.h"
+
+namespace clang {
+class MacroInfo;
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief A preprocessor that collects all macro symbols.
+/// The contexts of a macro will be ignored since they are not available during
+/// preprocessing period.
+class FindAllMacros : public clang::PPCallbacks {
+public:
+ explicit FindAllMacros(SymbolReporter *Reporter, SourceManager *SM,
+ HeaderMapCollector *Collector = nullptr)
+ : Reporter(Reporter), SM(SM), Collector(Collector) {}
+
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override;
+
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+
+ void EndOfMainFile() override;
+
+private:
+ llvm::Optional<SymbolInfo> CreateMacroSymbol(const Token &MacroNameTok,
+ const MacroInfo *MD);
+ // Not a callback, just a common path for all usage types.
+ void MacroUsed(const Token &Name, const MacroDefinition &MD);
+
+ SymbolInfo::SignalMap FileSymbols;
+ // Reporter for SymbolInfo.
+ SymbolReporter *const Reporter;
+ SourceManager *const SM;
+ // A remapping header file collector allowing clients to include a different
+ // header.
+ HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
new file mode 100644
index 00000000000..bb6a3fa9f16
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -0,0 +1,268 @@
+//===-- FindAllSymbols.cpp - find all symbols--------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "PathConfig.h"
+#include "SymbolInfo.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace find_all_symbols {
+namespace {
+
+AST_MATCHER(EnumConstantDecl, isInScopedEnum) {
+ if (const auto *ED = dyn_cast<EnumDecl>(Node.getDeclContext()))
+ return ED->isScoped();
+ return false;
+}
+
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+ CXXRecordDecl)) {
+ if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+ bool IsPartialSpecialization =
+ llvm::isa<VarTemplatePartialSpecializationDecl>(Node) ||
+ llvm::isa<ClassTemplatePartialSpecializationDecl>(Node);
+ return !IsPartialSpecialization;
+ }
+ return false;
+}
+
+std::vector<SymbolInfo::Context> GetContexts(const NamedDecl *ND) {
+ std::vector<SymbolInfo::Context> Contexts;
+ for (const auto *Context = ND->getDeclContext(); Context;
+ Context = Context->getParent()) {
+ if (llvm::isa<TranslationUnitDecl>(Context) ||
+ llvm::isa<LinkageSpecDecl>(Context))
+ break;
+
+ assert(llvm::isa<NamedDecl>(Context) &&
+ "Expect Context to be a NamedDecl");
+ if (const auto *NSD = dyn_cast<NamespaceDecl>(Context)) {
+ if (!NSD->isInlineNamespace())
+ Contexts.emplace_back(SymbolInfo::ContextType::Namespace,
+ NSD->getName().str());
+ } else if (const auto *ED = dyn_cast<EnumDecl>(Context)) {
+ Contexts.emplace_back(SymbolInfo::ContextType::EnumDecl,
+ ED->getName().str());
+ } else {
+ const auto *RD = cast<RecordDecl>(Context);
+ Contexts.emplace_back(SymbolInfo::ContextType::Record,
+ RD->getName().str());
+ }
+ }
+ return Contexts;
+}
+
+llvm::Optional<SymbolInfo>
+CreateSymbolInfo(const NamedDecl *ND, const SourceManager &SM,
+ const HeaderMapCollector *Collector) {
+ SymbolInfo::SymbolKind Type;
+ if (llvm::isa<VarDecl>(ND)) {
+ Type = SymbolInfo::SymbolKind::Variable;
+ } else if (llvm::isa<FunctionDecl>(ND)) {
+ Type = SymbolInfo::SymbolKind::Function;
+ } else if (llvm::isa<TypedefNameDecl>(ND)) {
+ Type = SymbolInfo::SymbolKind::TypedefName;
+ } else if (llvm::isa<EnumConstantDecl>(ND)) {
+ Type = SymbolInfo::SymbolKind::EnumConstantDecl;
+ } else if (llvm::isa<EnumDecl>(ND)) {
+ Type = SymbolInfo::SymbolKind::EnumDecl;
+ // Ignore anonymous enum declarations.
+ if (ND->getName().empty())
+ return llvm::None;
+ } else {
+ assert(llvm::isa<RecordDecl>(ND) &&
+ "Matched decl must be one of VarDecl, "
+ "FunctionDecl, TypedefNameDecl, EnumConstantDecl, "
+ "EnumDecl and RecordDecl!");
+ // C-style record decl can have empty name, e.g "struct { ... } var;".
+ if (ND->getName().empty())
+ return llvm::None;
+ Type = SymbolInfo::SymbolKind::Class;
+ }
+
+ SourceLocation Loc = SM.getExpansionLoc(ND->getLocation());
+ if (!Loc.isValid()) {
+ llvm::errs() << "Declaration " << ND->getNameAsString() << "("
+ << ND->getDeclKindName()
+ << ") has invalid declaration location.";
+ return llvm::None;
+ }
+
+ std::string FilePath = getIncludePath(SM, Loc, Collector);
+ if (FilePath.empty()) return llvm::None;
+
+ return SymbolInfo(ND->getNameAsString(), Type, FilePath, GetContexts(ND));
+}
+
+} // namespace
+
+void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) {
+ // FIXME: Handle specialization.
+ auto IsInSpecialization = hasAncestor(
+ decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
+ functionDecl(isExplicitTemplateSpecialization()))));
+
+ // Matchers for both C and C++.
+ // We only match symbols from header files, i.e. not from main files (see
+ // function's comment for detailed explanation).
+ auto CommonFilter =
+ allOf(unless(isImplicit()), unless(isExpansionInMainFile()));
+
+ auto HasNSOrTUCtxMatcher =
+ hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
+
+ // We need seperate rules for C record types and C++ record types since some
+ // template related matchers are inapplicable on C record declarations.
+ //
+ // Matchers specific to C++ code.
+ // All declarations should be in namespace or translation unit.
+ auto CCMatcher =
+ allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
+ unless(ast_matchers::isTemplateInstantiation()),
+ unless(isInstantiated()), unless(isFullySpecialized()));
+
+ // Matchers specific to code in extern "C" {...}.
+ auto ExternCMatcher = hasDeclContext(linkageSpecDecl());
+
+ // Matchers for variable declarations.
+ //
+ // In most cases, `ParmVarDecl` is filtered out by hasDeclContext(...)
+ // matcher since the declaration context is usually `MethodDecl`. However,
+ // this assumption does not hold for parameters of a function pointer
+ // parameter.
+ // For example, consider a function declaration:
+ // void Func(void (*)(float), int);
+ // The float parameter of the function pointer has an empty name, and its
+ // declaration context is an anonymous namespace; therefore, it won't be
+ // filtered out by our matchers above.
+ auto Vars = varDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher),
+ unless(parmVarDecl()));
+
+ // Matchers for C-style record declarations in extern "C" {...}.
+ auto CRecords = recordDecl(CommonFilter, ExternCMatcher, isDefinition());
+ // Matchers for C++ record declarations.
+ auto CXXRecords = cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
+
+ // Matchers for function declarations.
+ // We want to exclude friend declaration, but the `DeclContext` of a friend
+ // function declaration is not the class in which it is declared, so we need
+ // to explicitly check if the parent is a `friendDecl`.
+ auto Functions = functionDecl(CommonFilter, unless(hasParent(friendDecl())),
+ anyOf(ExternCMatcher, CCMatcher));
+
+ // Matcher for typedef and type alias declarations.
+ //
+ // typedef and type alias can come from C-style headers and C++ headers.
+ // For C-style headers, `DeclContxet` can be either `TranslationUnitDecl`
+ // or `LinkageSpecDecl`.
+ // For C++ headers, `DeclContext ` can be either `TranslationUnitDecl`
+ // or `NamespaceDecl`.
+ // With the following context matcher, we can match `typedefNameDecl` from
+ // both C-style headers and C++ headers (except for those in classes).
+ // "cc_matchers" are not included since template-related matchers are not
+ // applicable on `TypedefNameDecl`.
+ auto Typedefs =
+ typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher,
+ hasDeclContext(linkageSpecDecl())));
+
+ // Matchers for enum declarations.
+ auto Enums = enumDecl(CommonFilter, isDefinition(),
+ anyOf(HasNSOrTUCtxMatcher, ExternCMatcher));
+
+ // Matchers for enum constant declarations.
+ // We only match the enum constants in non-scoped enum declarations which are
+ // inside toplevel translation unit or a namespace.
+ auto EnumConstants = enumConstantDecl(
+ CommonFilter, unless(isInScopedEnum()),
+ anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher));
+
+ // Most of the time we care about all matchable decls, or all types.
+ auto Types = namedDecl(anyOf(CRecords, CXXRecords, Enums));
+ auto Decls = namedDecl(anyOf(CRecords, CXXRecords, Enums, Typedefs, Vars,
+ EnumConstants, Functions));
+
+ // We want eligible decls bound to "decl"...
+ MatchFinder->addMatcher(Decls.bind("decl"), this);
+
+ // ... and all uses of them bound to "use". These have many cases:
+ // Uses of values/functions: these generate a declRefExpr.
+ MatchFinder->addMatcher(
+ declRefExpr(isExpansionInMainFile(), to(Decls.bind("use"))), this);
+ // Uses of function templates:
+ MatchFinder->addMatcher(
+ declRefExpr(isExpansionInMainFile(),
+ to(functionDecl(hasParent(
+ functionTemplateDecl(has(Functions.bind("use"))))))),
+ this);
+
+ // Uses of most types: just look at what the typeLoc refers to.
+ MatchFinder->addMatcher(
+ typeLoc(isExpansionInMainFile(),
+ loc(qualType(hasDeclaration(Types.bind("use"))))),
+ this);
+ // Uses of typedefs: these are often transparent to hasDeclaration, so we need
+ // to handle them explicitly.
+ MatchFinder->addMatcher(
+ typeLoc(isExpansionInMainFile(),
+ loc(typedefType(hasDeclaration(Typedefs.bind("use"))))),
+ this);
+ // Uses of class templates:
+ // The typeLoc names the templateSpecializationType. Its declaration is the
+ // ClassTemplateDecl, which contains the CXXRecordDecl we want.
+ MatchFinder->addMatcher(
+ typeLoc(isExpansionInMainFile(),
+ loc(templateSpecializationType(hasDeclaration(
+ classTemplateSpecializationDecl(hasSpecializedTemplate(
+ classTemplateDecl(has(CXXRecords.bind("use"))))))))),
+ this);
+}
+
+void FindAllSymbols::run(const MatchFinder::MatchResult &Result) {
+ // Ignore Results in failing TUs.
+ if (Result.Context->getDiagnostics().hasErrorOccurred()) {
+ return;
+ }
+
+ SymbolInfo::Signals Signals;
+ const NamedDecl *ND;
+ if ((ND = Result.Nodes.getNodeAs<NamedDecl>("use")))
+ Signals.Used = 1;
+ else if ((ND = Result.Nodes.getNodeAs<NamedDecl>("decl")))
+ Signals.Seen = 1;
+ else
+ assert(false && "Must match a NamedDecl!");
+
+ const SourceManager *SM = Result.SourceManager;
+ if (auto Symbol = CreateSymbolInfo(ND, *SM, Collector)) {
+ Filename = SM->getFileEntryForID(SM->getMainFileID())->getName();
+ FileSymbols[*Symbol] += Signals;
+ }
+}
+
+void FindAllSymbols::onEndOfTranslationUnit() {
+ if (Filename != "") {
+ Reporter->reportSymbols(Filename, FileSymbols);
+ FileSymbols.clear();
+ Filename = "";
+ }
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.h
new file mode 100644
index 00000000000..d78da668ee4
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.h
@@ -0,0 +1,62 @@
+//===-- FindAllSymbols.h - find all symbols----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+
+namespace clang {
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief FindAllSymbols collects all classes, free standing functions and
+/// global variables with some extra information such as the path of the header
+/// file, the namespaces they are contained in, the type of variables and the
+/// parameter types of functions.
+///
+/// NOTE:
+/// - Symbols declared in main files are not collected since they can not be
+/// included.
+/// - Member functions are not collected because accessing them must go
+/// through the class. #include fixer only needs the class name to find
+/// headers.
+///
+class FindAllSymbols : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ explicit FindAllSymbols(SymbolReporter *Reporter,
+ HeaderMapCollector *Collector = nullptr)
+ : Reporter(Reporter), Collector(Collector) {}
+
+ void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
+
+ void run(const ast_matchers::MatchFinder::MatchResult &result) override;
+
+protected:
+ void onEndOfTranslationUnit() override;
+
+private:
+ // Current source file being processed, filled by first symbol found.
+ std::string Filename;
+ // Findings for the current source file, flushed on onEndOfTranslationUnit.
+ SymbolInfo::SignalMap FileSymbols;
+ // Reporter for SymbolInfo.
+ SymbolReporter *const Reporter;
+ // A remapping header file collector allowing clients include a different
+ // header.
+ HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
new file mode 100644
index 00000000000..9f1d31dc38a
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
@@ -0,0 +1,36 @@
+//===-- FindAllSymbolsAction.cpp - find all symbols action --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbolsAction.h"
+#include "FindAllMacros.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+FindAllSymbolsAction::FindAllSymbolsAction(
+ SymbolReporter *Reporter,
+ const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap)
+ : Reporter(Reporter), Collector(RegexHeaderMap), Handler(&Collector),
+ Matcher(Reporter, &Collector) {
+ Matcher.registerMatchers(&MatchFinder);
+}
+
+std::unique_ptr<ASTConsumer>
+FindAllSymbolsAction::CreateASTConsumer(CompilerInstance &Compiler,
+ StringRef InFile) {
+ Compiler.getPreprocessor().addCommentHandler(&Handler);
+ Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique<FindAllMacros>(
+ Reporter, &Compiler.getSourceManager(), &Collector));
+ return MatchFinder.newASTConsumer();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h
new file mode 100644
index 00000000000..ccffa4b3c9d
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h
@@ -0,0 +1,62 @@
+//===-- FindAllSymbolsAction.h - find all symbols action --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
+
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "PragmaCommentHandler.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang {
+namespace find_all_symbols {
+
+class FindAllSymbolsAction : public clang::ASTFrontendAction {
+public:
+ explicit FindAllSymbolsAction(
+ SymbolReporter *Reporter,
+ const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr);
+
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &Compiler,
+ StringRef InFile) override;
+
+private:
+ SymbolReporter *const Reporter;
+ clang::ast_matchers::MatchFinder MatchFinder;
+ HeaderMapCollector Collector;
+ PragmaCommentHandler Handler;
+ FindAllSymbols Matcher;
+};
+
+class FindAllSymbolsActionFactory : public tooling::FrontendActionFactory {
+public:
+ FindAllSymbolsActionFactory(
+ SymbolReporter *Reporter,
+ const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr)
+ : Reporter(Reporter), RegexHeaderMap(RegexHeaderMap) {}
+
+ clang::FrontendAction *create() override {
+ return new FindAllSymbolsAction(Reporter, RegexHeaderMap);
+ }
+
+private:
+ SymbolReporter *const Reporter;
+ const HeaderMapCollector::RegexHeaderMap *const RegexHeaderMap;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_SYMBOLS_ACTION_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp
new file mode 100644
index 00000000000..6ec49cae2a6
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp
@@ -0,0 +1,44 @@
+//===-- HeaderMapCoolector.h - find all symbols------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "HeaderMapCollector.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+HeaderMapCollector::HeaderMapCollector(
+ const RegexHeaderMap *RegexHeaderMappingTable) {
+ assert(RegexHeaderMappingTable);
+ this->RegexHeaderMappingTable.reserve(RegexHeaderMappingTable->size());
+ for (const auto &Entry : *RegexHeaderMappingTable) {
+ this->RegexHeaderMappingTable.emplace_back(llvm::Regex(Entry.first),
+ Entry.second);
+ }
+}
+
+llvm::StringRef
+HeaderMapCollector::getMappedHeader(llvm::StringRef Header) const {
+ auto Iter = HeaderMappingTable.find(Header);
+ if (Iter != HeaderMappingTable.end())
+ return Iter->second;
+ // If there is no complete header name mapping for this header, check the
+ // regex header mapping.
+ for (auto &Entry : RegexHeaderMappingTable) {
+#ifndef NDEBUG
+ std::string Dummy;
+ assert(Entry.first.isValid(Dummy) && "Regex should never be invalid!");
+#endif
+ if (Entry.first.match(Header))
+ return Entry.second;
+ }
+ return Header;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.h
new file mode 100644
index 00000000000..2135827561d
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/HeaderMapCollector.h
@@ -0,0 +1,56 @@
+//===-- HeaderMapCoolector.h - find all symbols------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Regex.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief HeaderMappCollector collects all remapping header files. This maps
+/// complete header names or header name regex patterns to header names.
+class HeaderMapCollector {
+public:
+ typedef llvm::StringMap<std::string> HeaderMap;
+ typedef std::vector<std::pair<const char *, const char *>> RegexHeaderMap;
+
+ HeaderMapCollector() = default;
+ explicit HeaderMapCollector(const RegexHeaderMap *RegexHeaderMappingTable);
+
+ void addHeaderMapping(llvm::StringRef OrignalHeaderPath,
+ llvm::StringRef MappingHeaderPath) {
+ HeaderMappingTable[OrignalHeaderPath] = MappingHeaderPath;
+ };
+
+ /// Check if there is a mapping from \p Header or a regex pattern that matches
+ /// it to another header name.
+ /// \param Header A header name.
+ /// \return \p Header itself if there is no mapping for it; otherwise, return
+ /// a mapped header name.
+ llvm::StringRef getMappedHeader(llvm::StringRef Header) const;
+
+private:
+ /// A string-to-string map saving the mapping relationship.
+ HeaderMap HeaderMappingTable;
+
+ // A map from header patterns to header names.
+ // The header names are not owned. This is only threadsafe because the regexes
+ // never fail.
+ mutable std::vector<std::pair<llvm::Regex, const char *>>
+ RegexHeaderMappingTable;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.cpp
new file mode 100644
index 00000000000..4f1ebc7732a
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.cpp
@@ -0,0 +1,41 @@
+//===-- PathConfig.cpp - Process paths of symbols ---------------*- C++ -*-===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PathConfig.h"
+#include "llvm/Support/Path.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+std::string getIncludePath(const SourceManager &SM, SourceLocation Loc,
+ const HeaderMapCollector *Collector) {
+ llvm::StringRef FilePath;
+ // Walk up the include stack to skip .inc files.
+ while (true) {
+ if (!Loc.isValid() || SM.isInMainFile(Loc))
+ return "";
+ FilePath = SM.getFilename(Loc);
+ if (FilePath.empty())
+ return "";
+ if (!FilePath.endswith(".inc"))
+ break;
+ FileID ID = SM.getFileID(Loc);
+ Loc = SM.getIncludeLoc(ID);
+ }
+
+ if (Collector)
+ FilePath = Collector->getMappedHeader(FilePath);
+ SmallString<256> CleanedFilePath = FilePath;
+ llvm::sys::path::remove_dots(CleanedFilePath, /*remove_dot_dot=*/false);
+
+ return CleanedFilePath.str();
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.h
new file mode 100644
index 00000000000..9c430f2526a
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/PathConfig.h
@@ -0,0 +1,36 @@
+//===-- PathConfig.h - Process paths of symbols -----------------*- C++ -*-===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PATH_CONFIG_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PATH_CONFIG_H
+
+#include "HeaderMapCollector.h"
+#include "clang/Basic/SourceManager.h"
+#include <string>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief This calculates the include path for \p Loc.
+///
+/// \param SM SourceManager.
+/// \param Loc A SourceLocation.
+/// \param Collector An optional header mapping collector.
+///
+/// \return The file path (or mapped file path if Collector is provided) of the
+/// header that includes \p Loc. If \p Loc comes from .inc header file, \p Loc
+/// is set to the location from which the .inc header file is included. If \p
+/// Loc is invalid or comes from a main file, this returns an empty string.
+std::string getIncludePath(const SourceManager &SM, SourceLocation Loc,
+ const HeaderMapCollector *Collector = nullptr);
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PATH_CONFIG_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp
new file mode 100644
index 00000000000..494897529e2
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp
@@ -0,0 +1,36 @@
+//===-- PragmaCommentHandler.cpp - find all symbols -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PragmaCommentHandler.h"
+#include "FindAllSymbols.h"
+#include "HeaderMapCollector.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace find_all_symbols {
+namespace {
+const char IWYUPragma[] = "// IWYU pragma: private, include ";
+} // namespace
+
+bool PragmaCommentHandler::HandleComment(Preprocessor &PP, SourceRange Range) {
+ StringRef Text =
+ Lexer::getSourceText(CharSourceRange::getCharRange(Range),
+ PP.getSourceManager(), PP.getLangOpts());
+ size_t Pos = Text.find(IWYUPragma);
+ if (Pos == StringRef::npos)
+ return false;
+ StringRef RemappingFilePath = Text.substr(Pos + std::strlen(IWYUPragma));
+ Collector->addHeaderMapping(
+ PP.getSourceManager().getFilename(Range.getBegin()),
+ RemappingFilePath.trim("\"<>"));
+ return false;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h
new file mode 100644
index 00000000000..752c82f5a06
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h
@@ -0,0 +1,40 @@
+//===-- PragmaCommentHandler.h - find all symbols----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Preprocessor.h"
+#include <map>
+
+namespace clang {
+namespace find_all_symbols {
+
+class HeaderMapCollector;
+
+/// \brief PragmaCommentHandler parses pragma comment on include files to
+/// determine when we should include a different header from the header that
+/// directly defines a symbol.
+///
+/// Currently it only supports IWYU private pragma:
+/// https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-private
+class PragmaCommentHandler : public clang::CommentHandler {
+public:
+ PragmaCommentHandler(HeaderMapCollector *Collector) : Collector(Collector) {}
+
+ bool HandleComment(Preprocessor &PP, SourceRange Range) override;
+
+private:
+ HeaderMapCollector *const Collector;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_PRAGMA_COMMENT_HANDLER_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
new file mode 100644
index 00000000000..0d0bbd9f055
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -0,0 +1,653 @@
+//===-- STLPostfixHeaderMap.h - hardcoded STL header map --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "STLPostfixHeaderMap.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+const HeaderMapCollector::RegexHeaderMap *getSTLPostfixHeaderMap() {
+ static const HeaderMapCollector::RegexHeaderMap STLPostfixHeaderMap = {
+ {"include/__stddef_max_align_t.h$", "<cstddef>"},
+ {"include/__wmmintrin_aes.h$", "<wmmintrin.h>"},
+ {"include/__wmmintrin_pclmul.h$", "<wmmintrin.h>"},
+ {"include/adxintrin.h$", "<immintrin.h>"},
+ {"include/ammintrin.h$", "<ammintrin.h>"},
+ {"include/avx2intrin.h$", "<immintrin.h>"},
+ {"include/avx512bwintrin.h$", "<immintrin.h>"},
+ {"include/avx512cdintrin.h$", "<immintrin.h>"},
+ {"include/avx512dqintrin.h$", "<immintrin.h>"},
+ {"include/avx512erintrin.h$", "<immintrin.h>"},
+ {"include/avx512fintrin.h$", "<immintrin.h>"},
+ {"include/avx512ifmaintrin.h$", "<immintrin.h>"},
+ {"include/avx512ifmavlintrin.h$", "<immintrin.h>"},
+ {"include/avx512pfintrin.h$", "<immintrin.h>"},
+ {"include/avx512vbmiintrin.h$", "<immintrin.h>"},
+ {"include/avx512vbmivlintrin.h$", "<immintrin.h>"},
+ {"include/avx512vlbwintrin.h$", "<immintrin.h>"},
+ {"include/avx512vlcdintrin.h$", "<immintrin.h>"},
+ {"include/avx512vldqintrin.h$", "<immintrin.h>"},
+ {"include/avx512vlintrin.h$", "<immintrin.h>"},
+ {"include/avxintrin.h$", "<immintrin.h>"},
+ {"include/bmi2intrin.h$", "<x86intrin.h>"},
+ {"include/bmiintrin.h$", "<x86intrin.h>"},
+ {"include/emmintrin.h$", "<emmintrin.h>"},
+ {"include/f16cintrin.h$", "<emmintrin.h>"},
+ {"include/float.h$", "<cfloat>"},
+ {"include/fma4intrin.h$", "<x86intrin.h>"},
+ {"include/fmaintrin.h$", "<immintrin.h>"},
+ {"include/fxsrintrin.h$", "<immintrin.h>"},
+ {"include/ia32intrin.h$", "<x86intrin.h>"},
+ {"include/immintrin.h$", "<immintrin.h>"},
+ {"include/inttypes.h$", "<cinttypes>"},
+ {"include/limits.h$", "<climits>"},
+ {"include/lzcntintrin.h$", "<x86intrin.h>"},
+ {"include/mm3dnow.h$", "<mm3dnow.h>"},
+ {"include/mm_malloc.h$", "<mm_malloc.h>"},
+ {"include/mmintrin.h$", "<mmintrin>"},
+ {"include/mwaitxintrin.h$", "<x86intrin.h>"},
+ {"include/pkuintrin.h$", "<immintrin.h>"},
+ {"include/pmmintrin.h$", "<pmmintrin.h>"},
+ {"include/popcntintrin.h$", "<popcntintrin.h>"},
+ {"include/prfchwintrin.h$", "<x86intrin.h>"},
+ {"include/rdseedintrin.h$", "<x86intrin.h>"},
+ {"include/rtmintrin.h$", "<immintrin.h>"},
+ {"include/shaintrin.h$", "<immintrin.h>"},
+ {"include/smmintrin.h$", "<smmintrin.h>"},
+ {"include/stdalign.h$", "<cstdalign>"},
+ {"include/stdarg.h$", "<cstdarg>"},
+ {"include/stdbool.h$", "<cstdbool>"},
+ {"include/stddef.h$", "<cstddef>"},
+ {"include/stdint.h$", "<cstdint>"},
+ {"include/tbmintrin.h$", "<x86intrin.h>"},
+ {"include/tmmintrin.h$", "<tmmintrin.h>"},
+ {"include/wmmintrin.h$", "<wmmintrin.h>"},
+ {"include/x86intrin.h$", "<x86intrin.h>"},
+ {"include/xmmintrin.h$", "<xmmintrin.h>"},
+ {"include/xopintrin.h$", "<x86intrin.h>"},
+ {"include/xsavecintrin.h$", "<immintrin.h>"},
+ {"include/xsaveintrin.h$", "<immintrin.h>"},
+ {"include/xsaveoptintrin.h$", "<immintrin.h>"},
+ {"include/xsavesintrin.h$", "<immintrin.h>"},
+ {"include/xtestintrin.h$", "<immintrin.h>"},
+ {"include/_G_config.h$", "<cstdio>"},
+ {"include/assert.h$", "<cassert>"},
+ {"algorithm$", "<algorithm>"},
+ {"array$", "<array>"},
+ {"atomic$", "<atomic>"},
+ {"backward/auto_ptr.h$", "<memory>"},
+ {"backward/binders.h$", "<string>"},
+ {"bits/algorithmfwd.h$", "<algorithm>"},
+ {"bits/alloc_traits.h$", "<unordered_set>"},
+ {"bits/allocator.h$", "<string>"},
+ {"bits/atomic_base.h$", "<atomic>"},
+ {"bits/atomic_lockfree_defines.h$", "<exception>"},
+ {"bits/basic_ios.h$", "<ios>"},
+ {"bits/basic_ios.tcc$", "<ios>"},
+ {"bits/basic_string.h$", "<string>"},
+ {"bits/basic_string.tcc$", "<string>"},
+ {"bits/char_traits.h$", "<string>"},
+ {"bits/codecvt.h$", "<locale>"},
+ {"bits/concept_check.h$", "<numeric>"},
+ {"bits/cpp_type_traits.h$", "<cmath>"},
+ {"bits/cxxabi_forced.h$", "<cxxabi.h>"},
+ {"bits/deque.tcc$", "<deque>"},
+ {"bits/exception_defines.h$", "<exception>"},
+ {"bits/exception_ptr.h$", "<exception>"},
+ {"bits/forward_list.h$", "<forward_list>"},
+ {"bits/forward_list.tcc$", "<forward_list>"},
+ {"bits/fstream.tcc$", "<fstream>"},
+ {"bits/functexcept.h$", "<list>"},
+ {"bits/functional_hash.h$", "<string>"},
+ {"bits/gslice.h$", "<valarray>"},
+ {"bits/gslice_array.h$", "<valarray>"},
+ {"bits/hash_bytes.h$", "<typeinfo>"},
+ {"bits/hashtable.h$", "<unordered_set>"},
+ {"bits/hashtable_policy.h$", "<unordered_set>"},
+ {"bits/indirect_array.h$", "<valarray>"},
+ {"bits/ios_base.h$", "<ios>"},
+ {"bits/istream.tcc$", "<istream>"},
+ {"bits/list.tcc$", "<list>"},
+ {"bits/locale_classes.h$", "<locale>"},
+ {"bits/locale_classes.tcc$", "<locale>"},
+ {"bits/locale_facets.h$", "<locale>"},
+ {"bits/locale_facets.tcc$", "<locale>"},
+ {"bits/locale_facets_nonio.h$", "<locale>"},
+ {"bits/locale_facets_nonio.tcc$", "<locale>"},
+ {"bits/localefwd.h$", "<locale>"},
+ {"bits/mask_array.h$", "<valarray>"},
+ {"bits/memoryfwd.h$", "<memory>"},
+ {"bits/move.h$", "<utility>"},
+ {"bits/nested_exception.h$", "<exception>"},
+ {"bits/ostream.tcc$", "<ostream>"},
+ {"bits/ostream_insert.h$", "<ostream>"},
+ {"bits/postypes.h$", "<iosfwd>"},
+ {"bits/ptr_traits.h$", "<memory>"},
+ {"bits/random.h$", "<random>"},
+ {"bits/random.tcc$", "<random>"},
+ {"bits/range_access.h$", "<iterator>"},
+ {"bits/regex.h$", "<regex>"},
+ {"bits/regex_compiler.h$", "<regex>"},
+ {"bits/regex_constants.h$", "<regex>"},
+ {"bits/regex_cursor.h$", "<regex>"},
+ {"bits/regex_error.h$", "<regex>"},
+ {"bits/regex_grep_matcher.h$", "<regex>"},
+ {"bits/regex_grep_matcher.tcc$", "<regex>"},
+ {"bits/regex_nfa.h$", "<regex>"},
+ {"bits/shared_ptr.h$", "<memory>"},
+ {"bits/shared_ptr_base.h$", "<memory>"},
+ {"bits/slice_array.h$", "<valarray>"},
+ {"bits/sstream.tcc$", "<sstream>"},
+ {"bits/stl_algo.h$", "<algorithm>"},
+ {"bits/stl_algobase.h$", "<list>"},
+ {"bits/stl_bvector.h$", "<vector>"},
+ {"bits/stl_construct.h$", "<deque>"},
+ {"bits/stl_deque.h$", "<deque>"},
+ {"bits/stl_function.h$", "<string>"},
+ {"bits/stl_heap.h$", "<queue>"},
+ {"bits/stl_iterator.h$", "<iterator>"},
+ {"bits/stl_iterator_base_funcs.h$", "<iterator>"},
+ {"bits/stl_iterator_base_types.h$", "<numeric>"},
+ {"bits/stl_list.h$", "<list>"},
+ {"bits/stl_map.h$", "<map>"},
+ {"bits/stl_multimap.h$", "<map>"},
+ {"bits/stl_multiset.h$", "<set>"},
+ {"bits/stl_numeric.h$", "<numeric>"},
+ {"bits/stl_pair.h$", "<utility>"},
+ {"bits/stl_queue.h$", "<queue>"},
+ {"bits/stl_raw_storage_iter.h$", "<memory>"},
+ {"bits/stl_relops.h$", "<utility>"},
+ {"bits/stl_set.h$", "<set>"},
+ {"bits/stl_stack.h$", "<stack>"},
+ {"bits/stl_tempbuf.h$", "<memory>"},
+ {"bits/stl_tree.h$", "<map>"},
+ {"bits/stl_uninitialized.h$", "<deque>"},
+ {"bits/stl_vector.h$", "<vector>"},
+ {"bits/stream_iterator.h$", "<iterator>"},
+ {"bits/streambuf.tcc$", "<streambuf>"},
+ {"bits/streambuf_iterator.h$", "<iterator>"},
+ {"bits/stringfwd.h$", "<string>"},
+ {"bits/unique_ptr.h$", "<memory>"},
+ {"bits/unordered_map.h$", "<unordered_map>"},
+ {"bits/unordered_set.h$", "<unordered_set>"},
+ {"bits/uses_allocator.h$", "<tuple>"},
+ {"bits/valarray_after.h$", "<valarray>"},
+ {"bits/valarray_array.h$", "<valarray>"},
+ {"bits/valarray_array.tcc$", "<valarray>"},
+ {"bits/valarray_before.h$", "<valarray>"},
+ {"bits/vector.tcc$", "<vector>"},
+ {"bitset$", "<bitset>"},
+ {"ccomplex$", "<ccomplex>"},
+ {"cctype$", "<cctype>"},
+ {"cerrno$", "<cerrno>"},
+ {"cfenv$", "<cfenv>"},
+ {"cfloat$", "<cfloat>"},
+ {"chrono$", "<chrono>"},
+ {"cinttypes$", "<cinttypes>"},
+ {"climits$", "<climits>"},
+ {"clocale$", "<clocale>"},
+ {"cmath$", "<cmath>"},
+ {"complex$", "<complex>"},
+ {"complex.h$", "<complex.h>"},
+ {"condition_variable$", "<condition_variable>"},
+ {"csetjmp$", "<csetjmp>"},
+ {"csignal$", "<csignal>"},
+ {"cstdalign$", "<cstdalign>"},
+ {"cstdarg$", "<cstdarg>"},
+ {"cstdbool$", "<cstdbool>"},
+ {"cstdint$", "<cstdint>"},
+ {"cstdio$", "<cstdio>"},
+ {"cstdlib$", "<cstdlib>"},
+ {"cstring$", "<cstring>"},
+ {"ctgmath$", "<ctgmath>"},
+ {"ctime$", "<ctime>"},
+ {"cwchar$", "<cwchar>"},
+ {"cwctype$", "<cwctype>"},
+ {"cxxabi.h$", "<cxxabi.h>"},
+ {"debug/debug.h$", "<numeric>"},
+ {"debug/map.h$", "<map>"},
+ {"debug/multimap.h$", "<multimap>"},
+ {"debug/multiset.h$", "<multiset>"},
+ {"debug/set.h$", "<set>"},
+ {"deque$", "<deque>"},
+ {"exception$", "<exception>"},
+ {"ext/alloc_traits.h$", "<deque>"},
+ {"ext/atomicity.h$", "<memory>"},
+ {"ext/concurrence.h$", "<memory>"},
+ {"ext/new_allocator.h$", "<string>"},
+ {"ext/numeric_traits.h$", "<list>"},
+ {"ext/string_conversions.h$", "<string>"},
+ {"ext/type_traits.h$", "<cmath>"},
+ {"fenv.h$", "<fenv.h>"},
+ {"forward_list$", "<forward_list>"},
+ {"fstream$", "<fstream>"},
+ {"functional$", "<functional>"},
+ {"future$", "<future>"},
+ {"initializer_list$", "<initializer_list>"},
+ {"iomanip$", "<iomanip>"},
+ {"ios$", "<ios>"},
+ {"iosfwd$", "<iosfwd>"},
+ {"iostream$", "<iostream>"},
+ {"istream$", "<istream>"},
+ {"iterator$", "<iterator>"},
+ {"limits$", "<limits>"},
+ {"list$", "<list>"},
+ {"locale$", "<locale>"},
+ {"map$", "<map>"},
+ {"memory$", "<memory>"},
+ {"mutex$", "<mutex>"},
+ {"new$", "<new>"},
+ {"numeric$", "<numeric>"},
+ {"ostream$", "<ostream>"},
+ {"queue$", "<queue>"},
+ {"random$", "<random>"},
+ {"ratio$", "<ratio>"},
+ {"regex$", "<regex>"},
+ {"scoped_allocator$", "<scoped_allocator>"},
+ {"set$", "<set>"},
+ {"sstream$", "<sstream>"},
+ {"stack$", "<stack>"},
+ {"stdexcept$", "<stdexcept>"},
+ {"streambuf$", "<streambuf>"},
+ {"string$", "<string>"},
+ {"system_error$", "<system_error>"},
+ {"tgmath.h$", "<tgmath.h>"},
+ {"thread$", "<thread>"},
+ {"tuple$", "<tuple>"},
+ {"type_traits$", "<type_traits>"},
+ {"typeindex$", "<typeindex>"},
+ {"typeinfo$", "<typeinfo>"},
+ {"unordered_map$", "<unordered_map>"},
+ {"unordered_set$", "<unordered_set>"},
+ {"utility$", "<utility>"},
+ {"valarray$", "<valarray>"},
+ {"vector$", "<vector>"},
+ {"include/complex.h$", "<complex.h>"},
+ {"include/ctype.h$", "<cctype>"},
+ {"include/errno.h$", "<cerrno>"},
+ {"include/fenv.h$", "<fenv.h>"},
+ {"include/inttypes.h$", "<cinttypes>"},
+ {"include/libio.h$", "<cstdio>"},
+ {"include/limits.h$", "<climits>"},
+ {"include/locale.h$", "<clocale>"},
+ {"include/math.h$", "<cmath>"},
+ {"include/setjmp.h$", "<csetjmp>"},
+ {"include/signal.h$", "<csignal>"},
+ {"include/stdint.h$", "<cstdint>"},
+ {"include/stdio.h$", "<cstdio>"},
+ {"include/stdlib.h$", "<cstdlib>"},
+ {"include/string.h$", "<cstring>"},
+ {"include/time.h$", "<ctime>"},
+ {"include/wchar.h$", "<cwchar>"},
+ {"include/wctype.h$", "<cwctype>"},
+ {"bits/cmathcalls.h$", "<complex.h>"},
+ {"bits/errno.h$", "<cerrno>"},
+ {"bits/fenv.h$", "<fenv.h>"},
+ {"bits/huge_val.h$", "<cmath>"},
+ {"bits/huge_valf.h$", "<cmath>"},
+ {"bits/huge_vall.h$", "<cmath>"},
+ {"bits/inf.h$", "<cmath>"},
+ {"bits/local_lim.h$", "<climits>"},
+ {"bits/locale.h$", "<clocale>"},
+ {"bits/mathcalls.h$", "<math.h>"},
+ {"bits/mathdef.h$", "<cmath>"},
+ {"bits/nan.h$", "<cmath>"},
+ {"bits/posix1_lim.h$", "<climits>"},
+ {"bits/posix2_lim.h$", "<climits>"},
+ {"bits/setjmp.h$", "<csetjmp>"},
+ {"bits/sigaction.h$", "<csignal>"},
+ {"bits/sigcontext.h$", "<csignal>"},
+ {"bits/siginfo.h$", "<csignal>"},
+ {"bits/signum.h$", "<csignal>"},
+ {"bits/sigset.h$", "<csignal>"},
+ {"bits/sigstack.h$", "<csignal>"},
+ {"bits/stdio_lim.h$", "<cstdio>"},
+ {"bits/sys_errlist.h$", "<cstdio>"},
+ {"bits/time.h$", "<ctime>"},
+ {"bits/timex.h$", "<ctime>"},
+ {"bits/typesizes.h$", "<cstdio>"},
+ {"bits/wchar.h$", "<cwchar>"},
+ {"bits/wordsize.h$", "<csetjmp>"},
+ {"bits/xopen_lim.h$", "<climits>"},
+ {"include/xlocale.h$", "<cstring>"},
+ {"bits/atomic_word.h$", "<memory>"},
+ {"bits/basic_file.h$", "<fstream>"},
+ {"bits/c\\+\\+allocator.h$", "<string>"},
+ {"bits/c\\+\\+config.h$", "<iosfwd>"},
+ {"bits/c\\+\\+io.h$", "<ios>"},
+ {"bits/c\\+\\+locale.h$", "<locale>"},
+ {"bits/cpu_defines.h$", "<iosfwd>"},
+ {"bits/ctype_base.h$", "<locale>"},
+ {"bits/cxxabi_tweaks.h$", "<cxxabi.h>"},
+ {"bits/error_constants.h$", "<system_error>"},
+ {"bits/gthr-default.h$", "<memory>"},
+ {"bits/gthr.h$", "<memory>"},
+ {"bits/opt_random.h$", "<random>"},
+ {"bits/os_defines.h$", "<iosfwd>"},
+ // GNU C headers
+ {"include/aio.h$", "<aio.h>"},
+ {"include/aliases.h$", "<aliases.h>"},
+ {"include/alloca.h$", "<alloca.h>"},
+ {"include/ar.h$", "<ar.h>"},
+ {"include/argp.h$", "<argp.h>"},
+ {"include/argz.h$", "<argz.h>"},
+ {"include/arpa/nameser.h$", "<resolv.h>"},
+ {"include/arpa/nameser_compat.h$", "<resolv.h>"},
+ {"include/byteswap.h$", "<byteswap.h>"},
+ {"include/cpio.h$", "<cpio.h>"},
+ {"include/crypt.h$", "<crypt.h>"},
+ {"include/dirent.h$", "<dirent.h>"},
+ {"include/dlfcn.h$", "<dlfcn.h>"},
+ {"include/elf.h$", "<elf.h>"},
+ {"include/endian.h$", "<endian.h>"},
+ {"include/envz.h$", "<envz.h>"},
+ {"include/err.h$", "<err.h>"},
+ {"include/error.h$", "<error.h>"},
+ {"include/execinfo.h$", "<execinfo.h>"},
+ {"include/fcntl.h$", "<fcntl.h>"},
+ {"include/features.h$", "<features.h>"},
+ {"include/fenv.h$", "<fenv.h>"},
+ {"include/fmtmsg.h$", "<fmtmsg.h>"},
+ {"include/fnmatch.h$", "<fnmatch.h>"},
+ {"include/fstab.h$", "<fstab.h>"},
+ {"include/fts.h$", "<fts.h>"},
+ {"include/ftw.h$", "<ftw.h>"},
+ {"include/gconv.h$", "<gconv.h>"},
+ {"include/getopt.h$", "<getopt.h>"},
+ {"include/glob.h$", "<glob.h>"},
+ {"include/grp.h$", "<grp.h>"},
+ {"include/gshadow.h$", "<gshadow.h>"},
+ {"include/iconv.h$", "<iconv.h>"},
+ {"include/ifaddrs.h$", "<ifaddrs.h>"},
+ {"include/kdb.h$", "<kdb.h>"},
+ {"include/langinfo.h$", "<langinfo.h>"},
+ {"include/libgen.h$", "<libgen.h>"},
+ {"include/libintl.h$", "<libintl.h>"},
+ {"include/link.h$", "<link.h>"},
+ {"include/malloc.h$", "<malloc.h>"},
+ {"include/mcheck.h$", "<mcheck.h>"},
+ {"include/memory.h$", "<memory.h>"},
+ {"include/mntent.h$", "<mntent.h>"},
+ {"include/monetary.h$", "<monetary.h>"},
+ {"include/mqueue.h$", "<mqueue.h>"},
+ {"include/netdb.h$", "<netdb.h>"},
+ {"include/netinet/in.h$", "<netinet/in.h>"},
+ {"include/nl_types.h$", "<nl_types.h>"},
+ {"include/nss.h$", "<nss.h>"},
+ {"include/obstack.h$", "<obstack.h>"},
+ {"include/panel.h$", "<panel.h>"},
+ {"include/paths.h$", "<paths.h>"},
+ {"include/printf.h$", "<printf.h>"},
+ {"include/profile.h$", "<profile.h>"},
+ {"include/pthread.h$", "<pthread.h>"},
+ {"include/pty.h$", "<pty.h>"},
+ {"include/pwd.h$", "<pwd.h>"},
+ {"include/re_comp.h$", "<re_comp.h>"},
+ {"include/regex.h$", "<regex.h>"},
+ {"include/regexp.h$", "<regexp.h>"},
+ {"include/resolv.h$", "<resolv.h>"},
+ {"include/rpc/netdb.h$", "<netdb.h>"},
+ {"include/sched.h$", "<sched.h>"},
+ {"include/search.h$", "<search.h>"},
+ {"include/semaphore.h$", "<semaphore.h>"},
+ {"include/sgtty.h$", "<sgtty.h>"},
+ {"include/shadow.h$", "<shadow.h>"},
+ {"include/spawn.h$", "<spawn.h>"},
+ {"include/stab.h$", "<stab.h>"},
+ {"include/stdc-predef.h$", "<stdc-predef.h>"},
+ {"include/stdio_ext.h$", "<stdio_ext.h>"},
+ {"include/strings.h$", "<strings.h>"},
+ {"include/stropts.h$", "<stropts.h>"},
+ {"include/sudo_plugin.h$", "<sudo_plugin.h>"},
+ {"include/sysexits.h$", "<sysexits.h>"},
+ {"include/tar.h$", "<tar.h>"},
+ {"include/tcpd.h$", "<tcpd.h>"},
+ {"include/term.h$", "<term.h>"},
+ {"include/term_entry.h$", "<term_entry.h>"},
+ {"include/termcap.h$", "<termcap.h>"},
+ {"include/termios.h$", "<termios.h>"},
+ {"include/thread_db.h$", "<thread_db.h>"},
+ {"include/tic.h$", "<tic.h>"},
+ {"include/ttyent.h$", "<ttyent.h>"},
+ {"include/uchar.h$", "<uchar.h>"},
+ {"include/ucontext.h$", "<ucontext.h>"},
+ {"include/ulimit.h$", "<ulimit.h>"},
+ {"include/unctrl.h$", "<unctrl.h>"},
+ {"include/unistd.h$", "<unistd.h>"},
+ {"include/utime.h$", "<utime.h>"},
+ {"include/utmp.h$", "<utmp.h>"},
+ {"include/utmpx.h$", "<utmpx.h>"},
+ {"include/values.h$", "<values.h>"},
+ {"include/wordexp.h$", "<wordexp.h>"},
+ {"fpu_control.h$", "<fpu_control.h>"},
+ {"ieee754.h$", "<ieee754.h>"},
+ {"include/xlocale.h$", "<xlocale.h>"},
+ {"gnu/lib-names.h$", "<gnu/lib-names.h>"},
+ {"gnu/libc-version.h$", "<gnu/libc-version.h>"},
+ {"gnu/option-groups.h$", "<gnu/option-groups.h>"},
+ {"gnu/stubs-32.h$", "<gnu/stubs-32.h>"},
+ {"gnu/stubs-64.h$", "<gnu/stubs-64.h>"},
+ {"gnu/stubs-x32.h$", "<gnu/stubs-x32.h>"},
+ {"include/rpc/auth_des.h$", "<rpc/auth_des.h>"},
+ {"include/rpc/rpc_msg.h$", "<rpc/rpc_msg.h>"},
+ {"include/rpc/pmap_clnt.h$", "<rpc/pmap_clnt.h>"},
+ {"include/rpc/rpc.h$", "<rpc/rpc.h>"},
+ {"include/rpc/types.h$", "<rpc/types.h>"},
+ {"include/rpc/auth_unix.h$", "<rpc/auth_unix.h>"},
+ {"include/rpc/key_prot.h$", "<rpc/key_prot.h>"},
+ {"include/rpc/pmap_prot.h$", "<rpc/pmap_prot.h>"},
+ {"include/rpc/auth.h$", "<rpc/auth.h>"},
+ {"include/rpc/svc_auth.h$", "<rpc/svc_auth.h>"},
+ {"include/rpc/xdr.h$", "<rpc/xdr.h>"},
+ {"include/rpc/pmap_rmt.h$", "<rpc/pmap_rmt.h>"},
+ {"include/rpc/des_crypt.h$", "<rpc/des_crypt.h>"},
+ {"include/rpc/svc.h$", "<rpc/svc.h>"},
+ {"include/rpc/rpc_des.h$", "<rpc/rpc_des.h>"},
+ {"include/rpc/clnt.h$", "<rpc/clnt.h>"},
+ {"include/scsi/scsi.h$", "<scsi/scsi.h>"},
+ {"include/scsi/sg.h$", "<scsi/sg.h>"},
+ {"include/scsi/scsi_ioctl.h$", "<scsi/scsi_ioctl>"},
+ {"include/netrose/rose.h$", "<netrose/rose.h>"},
+ {"include/nfs/nfs.h$", "<nfs/nfs.h>"},
+ {"include/netatalk/at.h$", "<netatalk/at.h>"},
+ {"include/netinet/ether.h$", "<netinet/ether.h>"},
+ {"include/netinet/icmp6.h$", "<netinet/icmp6.h>"},
+ {"include/netinet/if_ether.h$", "<netinet/if_ether.h>"},
+ {"include/netinet/if_fddi.h$", "<netinet/if_fddi.h>"},
+ {"include/netinet/if_tr.h$", "<netinet/if_tr.h>"},
+ {"include/netinet/igmp.h$", "<netinet/igmp.h>"},
+ {"include/netinet/in.h$", "<netinet/in.h>"},
+ {"include/netinet/in_systm.h$", "<netinet/in_systm.h>"},
+ {"include/netinet/ip.h$", "<netinet/ip.h>"},
+ {"include/netinet/ip6.h$", "<netinet/ip6.h>"},
+ {"include/netinet/ip_icmp.h$", "<netinet/ip_icmp.h>"},
+ {"include/netinet/tcp.h$", "<netinet/tcp.h>"},
+ {"include/netinet/udp.h$", "<netinet/udp.h>"},
+ {"include/netrom/netrom.h$", "<netrom/netrom.h>"},
+ {"include/protocols/routed.h$", "<protocols/routed.h>"},
+ {"include/protocols/rwhod.h$", "<protocols/rwhod.h>"},
+ {"include/protocols/talkd.h$", "<protocols/talkd.h>"},
+ {"include/protocols/timed.h$", "<protocols/timed.h>"},
+ {"include/rpcsvc/klm_prot.x$", "<rpcsvc/klm_prot.x>"},
+ {"include/rpcsvc/rstat.h$", "<rpcsvc/rstat.h>"},
+ {"include/rpcsvc/spray.x$", "<rpcsvc/spray.x>"},
+ {"include/rpcsvc/nlm_prot.x$", "<rpcsvc/nlm_prot.x>"},
+ {"include/rpcsvc/nis_callback.x$", "<rpcsvc/nis_callback.x>"},
+ {"include/rpcsvc/yp.h$", "<rpcsvc/yp.h>"},
+ {"include/rpcsvc/yp.x$", "<rpcsvc/yp.x>"},
+ {"include/rpcsvc/nfs_prot.h$", "<rpcsvc/nfs_prot.h>"},
+ {"include/rpcsvc/rex.h$", "<rpcsvc/rex.h>"},
+ {"include/rpcsvc/yppasswd.h$", "<rpcsvc/yppasswd.h>"},
+ {"include/rpcsvc/rex.x$", "<rpcsvc/rex.x>"},
+ {"include/rpcsvc/nis_tags.h$", "<rpcsvc/nis_tags.h>"},
+ {"include/rpcsvc/nis_callback.h$", "<rpcsvc/nis_callback.h>"},
+ {"include/rpcsvc/nfs_prot.x$", "<rpcsvc/nfs_prot.x>"},
+ {"include/rpcsvc/bootparam_prot.x$", "<rpcsvc/bootparam_prot.x>"},
+ {"include/rpcsvc/rusers.x$", "<rpcsvc/rusers.x>"},
+ {"include/rpcsvc/rquota.x$", "<rpcsvc/rquota.x>"},
+ {"include/rpcsvc/nis.h$", "<rpcsvc/nis.h>"},
+ {"include/rpcsvc/nislib.h$", "<rpcsvc/nislib.h>"},
+ {"include/rpcsvc/ypupd.h$", "<rpcsvc/ypupd.h>"},
+ {"include/rpcsvc/bootparam.h$", "<rpcsvc/bootparam.h>"},
+ {"include/rpcsvc/spray.h$", "<rpcsvc/spray.h>"},
+ {"include/rpcsvc/key_prot.h$", "<rpcsvc/key_prot.h>"},
+ {"include/rpcsvc/klm_prot.h$", "<rpcsvc/klm_prot.h>"},
+ {"include/rpcsvc/sm_inter.h$", "<rpcsvc/sm_inter.h>"},
+ {"include/rpcsvc/nlm_prot.h$", "<rpcsvc/nlm_prot.h>"},
+ {"include/rpcsvc/yp_prot.h$", "<rpcsvc/yp_prot.h>"},
+ {"include/rpcsvc/ypclnt.h$", "<rpcsvc/ypclnt.h>"},
+ {"include/rpcsvc/rstat.x$", "<rpcsvc/rstat.x>"},
+ {"include/rpcsvc/rusers.h$", "<rpcsvc/rusers.h>"},
+ {"include/rpcsvc/key_prot.x$", "<rpcsvc/key_prot.x>"},
+ {"include/rpcsvc/sm_inter.x$", "<rpcsvc/sm_inter.x>"},
+ {"include/rpcsvc/rquota.h$", "<rpcsvc/rquota.h>"},
+ {"include/rpcsvc/nis.x$", "<rpcsvc/nis.x>"},
+ {"include/rpcsvc/bootparam_prot.h$", "<rpcsvc/bootparam_prot.h>"},
+ {"include/rpcsvc/mount.h$", "<rpcsvc/mount.h>"},
+ {"include/rpcsvc/mount.x$", "<rpcsvc/mount.x>"},
+ {"include/rpcsvc/nis_object.x$", "<rpcsvc/nis_object.x>"},
+ {"include/rpcsvc/yppasswd.x$", "<rpcsvc/yppasswd.x>"},
+ {"sys/acct.h$", "<sys/acct.h>"},
+ {"sys/auxv.h$", "<sys/auxv.h>"},
+ {"sys/cdefs.h$", "<sys/cdefs.h>"},
+ {"sys/debugreg.h$", "<sys/debugreg.h>"},
+ {"sys/dir.h$", "<sys/dir.h>"},
+ {"sys/elf.h$", "<sys/elf.h>"},
+ {"sys/epoll.h$", "<sys/epoll.h>"},
+ {"sys/eventfd.h$", "<sys/eventfd.h>"},
+ {"sys/fanotify.h$", "<sys/fanotify.h>"},
+ {"sys/file.h$", "<sys/file.h>"},
+ {"sys/fsuid.h$", "<sys/fsuid.h>"},
+ {"sys/gmon.h$", "<sys/gmon.h>"},
+ {"sys/gmon_out.h$", "<sys/gmon_out.h>"},
+ {"sys/inotify.h$", "<sys/inotify.h>"},
+ {"sys/io.h$", "<sys/io.h>"},
+ {"sys/ioctl.h$", "<sys/ioctl.h>"},
+ {"sys/ipc.h$", "<sys/ipc.h>"},
+ {"sys/kd.h$", "<sys/kd.h>"},
+ {"sys/kdaemon.h$", "<sys/kdaemon.h>"},
+ {"sys/klog.h$", "<sys/klog.h>"},
+ {"sys/mman.h$", "<sys/mman.h>"},
+ {"sys/mount.h$", "<sys/mount.h>"},
+ {"sys/msg.h$", "<sys/msg.h>"},
+ {"sys/mtio.h$", "<sys/mtio.h>"},
+ {"sys/param.h$", "<sys/param.h>"},
+ {"sys/pci.h$", "<sys/pci.h>"},
+ {"sys/perm.h$", "<sys/perm.h>"},
+ {"sys/personality.h$", "<sys/personality.h>"},
+ {"sys/poll.h$", "<sys/poll.h>"},
+ {"sys/prctl.h$", "<sys/prctl.h>"},
+ {"sys/procfs.h$", "<sys/procfs.h>"},
+ {"sys/profil.h$", "<sys/profil.h>"},
+ {"sys/ptrace.h$", "<sys/ptrace.h>"},
+ {"sys/queue.h$", "<sys/queue.h>"},
+ {"sys/quota.h$", "<sys/quota.h>"},
+ {"sys/raw.h$", "<sys/raw.h>"},
+ {"sys/reboot.h$", "<sys/reboot.h>"},
+ {"sys/reg.h$", "<sys/reg.h>"},
+ {"sys/resource.h$", "<sys/resource.h>"},
+ {"sys/select.h$", "<sys/select.h>"},
+ {"sys/sem.h$", "<sys/sem.h>"},
+ {"sys/sendfile.h$", "<sys/sendfile.h>"},
+ {"sys/shm.h$", "<sys/shm.h>"},
+ {"sys/signalfd.h$", "<sys/signalfd.h>"},
+ {"sys/socket.h$", "<sys/socket.h>"},
+ {"sys/stat.h$", "<sys/stat.h>"},
+ {"sys/statfs.h$", "<sys/statfs.h>"},
+ {"sys/statvfs.h$", "<sys/statvfs.h>"},
+ {"sys/swap.h$", "<sys/swap.h>"},
+ {"sys/syscall.h$", "<sys/syscall.h>"},
+ {"sys/sysctl.h$", "<sys/sysctl.h>"},
+ {"sys/sysinfo.h$", "<sys/sysinfo.h>"},
+ {"sys/syslog.h$", "<sys/syslog.h>"},
+ {"sys/sysmacros.h$", "<sys/sysmacros.h>"},
+ {"sys/termios.h$", "<sys/termios.h>"},
+ {"sys/time.h$", "<sys/select.h>"},
+ {"sys/timeb.h$", "<sys/timeb.h>"},
+ {"sys/timerfd.h$", "<sys/timerfd.h>"},
+ {"sys/times.h$", "<sys/times.h>"},
+ {"sys/timex.h$", "<sys/timex.h>"},
+ {"sys/ttychars.h$", "<sys/ttychars.h>"},
+ {"sys/ttydefaults.h$", "<sys/ttydefaults.h>"},
+ {"sys/types.h$", "<sys/types.h>"},
+ {"sys/ucontext.h$", "<sys/ucontext.h>"},
+ {"sys/uio.h$", "<sys/uio.h>"},
+ {"sys/un.h$", "<sys/un.h>"},
+ {"sys/user.h$", "<sys/user.h>"},
+ {"sys/ustat.h$", "<sys/ustat.h>"},
+ {"sys/utsname.h$", "<sys/utsname.h>"},
+ {"sys/vlimit.h$", "<sys/vlimit.h>"},
+ {"sys/vm86.h$", "<sys/vm86.h>"},
+ {"sys/vtimes.h$", "<sys/vtimes.h>"},
+ {"sys/wait.h$", "<sys/wait.h>"},
+ {"sys/xattr.h$", "<sys/xattr.h>"},
+ {"bits/epoll.h$", "<sys/epoll.h>"},
+ {"bits/eventfd.h$", "<sys/eventfd.h>"},
+ {"bits/inotify.h$", "<sys/inotify.h>"},
+ {"bits/ipc.h$", "<sys/ipc.h>"},
+ {"bits/ipctypes.h$", "<sys/ipc.h>"},
+ {"bits/mman-linux.h$", "<sys/mman.h>"},
+ {"bits/mman.h$", "<sys/mman.h>"},
+ {"bits/msq.h$", "<sys/msg.h>"},
+ {"bits/resource.h$", "<sys/resource.h>"},
+ {"bits/sem.h$", "<sys/sem.h>"},
+ {"bits/shm.h$", "<sys/shm.h>"},
+ {"bits/signalfd.h$", "<sys/signalfd.h>"},
+ {"bits/statfs.h$", "<sys/statfs.h>"},
+ {"bits/statvfs.h$", "<sys/statvfs.h>"},
+ {"bits/timerfd.h$", "<sys/timerfd.h>"},
+ {"bits/utsname.h$", "<sys/utsname.h>"},
+ {"bits/auxv.h$", "<sys/auxv.h>"},
+ {"bits/byteswap-16.h$", "<byteswap.h>"},
+ {"bits/byteswap.h$", "<byteswap.h>"},
+ {"bits/confname.h$", "<unistd.h>"},
+ {"bits/dirent.h$", "<dirent.h>"},
+ {"bits/dlfcn.h$", "<dlfcn.h>"},
+ {"bits/elfclass.h$", "<link.h>"},
+ {"bits/endian.h$", "<endian.h>"},
+ {"bits/environments.h$", "<unistd.h>"},
+ {"bits/fcntl-linux.h$", "<fcntl.h>"},
+ {"bits/fcntl.h$", "<fcntl.h>"},
+ {"bits/in.h$", "<netinet/in.h>"},
+ {"bits/ioctl-types.h$", "<sys/ioctl.h>"},
+ {"bits/ioctls.h$", "<sys/ioctl.h>"},
+ {"bits/link.h$", "<link.h>"},
+ {"bits/mqueue.h$", "<mqueue.h>"},
+ {"bits/netdb.h$", "<netdb.h>"},
+ {"bits/param.h$", "<sys/param.h>"},
+ {"bits/poll.h$", "<sys/poll.h>"},
+ {"bits/posix_opt.h$", "<bits/posix_opt.h>"},
+ {"bits/pthreadtypes.h$", "<pthread.h>"},
+ {"bits/sched.h$", "<sched.h>"},
+ {"bits/select.h$", "<sys/select.h>"},
+ {"bits/semaphore.h$", "<semaphore.h>"},
+ {"bits/sigthread.h$", "<pthread.h>"},
+ {"bits/sockaddr.h$", "<sys/socket.h>"},
+ {"bits/socket.h$", "<sys/socket.h>"},
+ {"bits/socket_type.h$", "<sys/socket.h>"},
+ {"bits/stab.def$", "<stab.h>"},
+ {"bits/stat.h$", "<sys/stat.h>"},
+ {"bits/stropts.h$", "<stropts.h>"},
+ {"bits/syscall.h$", "<sys/syscall.h>"},
+ {"bits/syslog-path.h$", "<sys/syslog.h>"},
+ {"bits/termios.h$", "<termios.h>"},
+ {"bits/types.h$", "<sys/types.h>"},
+ {"bits/typesizes.h$", "<sys/types.h>"},
+ {"bits/uio.h$", "<sys/uio.h>"},
+ {"bits/ustat.h$", "<sys/ustat.h>"},
+ {"bits/utmp.h$", "<utmp.h>"},
+ {"bits/utmpx.h$", "<utmpx.h>"},
+ {"bits/waitflags.h$", "<sys/wait.h>"},
+ {"bits/waitstatus.h$", "<sys/wait.h>"},
+ {"bits/xtitypes.h$", "<stropts.h>"},
+ };
+ return &STLPostfixHeaderMap;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h
new file mode 100644
index 00000000000..49bc5f3037d
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h
@@ -0,0 +1,22 @@
+//===-- STLPostfixHeaderMap.h - hardcoded header map for STL ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
+
+#include "HeaderMapCollector.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+const HeaderMapCollector::RegexHeaderMap *getSTLPostfixHeaderMap();
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_TOOL_STL_POSTFIX_HEADER_MAP_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.cpp
new file mode 100644
index 00000000000..e5b4dba4b7a
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.cpp
@@ -0,0 +1,136 @@
+//===-- SymbolInfo.cpp - Symbol Info ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using llvm::yaml::MappingTraits;
+using llvm::yaml::IO;
+using llvm::yaml::Input;
+using ContextType = clang::find_all_symbols::SymbolInfo::ContextType;
+using clang::find_all_symbols::SymbolInfo;
+using clang::find_all_symbols::SymbolAndSignals;
+using SymbolKind = clang::find_all_symbols::SymbolInfo::SymbolKind;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(SymbolAndSignals)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolInfo::Context)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<SymbolAndSignals> {
+ static void mapping(IO &io, SymbolAndSignals &Symbol) {
+ io.mapRequired("Name", Symbol.Symbol.Name);
+ io.mapRequired("Contexts", Symbol.Symbol.Contexts);
+ io.mapRequired("FilePath", Symbol.Symbol.FilePath);
+ io.mapRequired("Type", Symbol.Symbol.Type);
+ io.mapRequired("Seen", Symbol.Signals.Seen);
+ io.mapRequired("Used", Symbol.Signals.Used);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<ContextType> {
+ static void enumeration(IO &io, ContextType &value) {
+ io.enumCase(value, "Record", ContextType::Record);
+ io.enumCase(value, "Namespace", ContextType::Namespace);
+ io.enumCase(value, "EnumDecl", ContextType::EnumDecl);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolKind> {
+ static void enumeration(IO &io, SymbolKind &value) {
+ io.enumCase(value, "Variable", SymbolKind::Variable);
+ io.enumCase(value, "Function", SymbolKind::Function);
+ io.enumCase(value, "Class", SymbolKind::Class);
+ io.enumCase(value, "TypedefName", SymbolKind::TypedefName);
+ io.enumCase(value, "EnumDecl", SymbolKind::EnumDecl);
+ io.enumCase(value, "EnumConstantDecl", SymbolKind::EnumConstantDecl);
+ io.enumCase(value, "Macro", SymbolKind::Macro);
+ io.enumCase(value, "Unknown", SymbolKind::Unknown);
+ }
+};
+
+template <> struct MappingTraits<SymbolInfo::Context> {
+ static void mapping(IO &io, SymbolInfo::Context &Context) {
+ io.mapRequired("ContextType", Context.first);
+ io.mapRequired("ContextName", Context.second);
+ }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace find_all_symbols {
+
+SymbolInfo::SymbolInfo(llvm::StringRef Name, SymbolKind Type,
+ llvm::StringRef FilePath,
+ const std::vector<Context> &Contexts)
+ : Name(Name), Type(Type), FilePath(FilePath), Contexts(Contexts) {}
+
+bool SymbolInfo::operator==(const SymbolInfo &Symbol) const {
+ return std::tie(Name, Type, FilePath, Contexts) ==
+ std::tie(Symbol.Name, Symbol.Type, Symbol.FilePath, Symbol.Contexts);
+}
+
+bool SymbolInfo::operator<(const SymbolInfo &Symbol) const {
+ return std::tie(Name, Type, FilePath, Contexts) <
+ std::tie(Symbol.Name, Symbol.Type, Symbol.FilePath, Symbol.Contexts);
+}
+
+std::string SymbolInfo::getQualifiedName() const {
+ std::string QualifiedName = Name;
+ for (const auto &Context : Contexts) {
+ if (Context.first == ContextType::EnumDecl)
+ continue;
+ QualifiedName = Context.second + "::" + QualifiedName;
+ }
+ return QualifiedName;
+}
+
+SymbolInfo::Signals &SymbolInfo::Signals::operator+=(const Signals &RHS) {
+ Seen += RHS.Seen;
+ Used += RHS.Used;
+ return *this;
+}
+
+SymbolInfo::Signals SymbolInfo::Signals::operator+(const Signals &RHS) const {
+ Signals Result = *this;
+ Result += RHS;
+ return Result;
+}
+
+bool SymbolInfo::Signals::operator==(const Signals &RHS) const {
+ return std::tie(Seen, Used) == std::tie(RHS.Seen, RHS.Used);
+}
+
+bool SymbolAndSignals::operator==(const SymbolAndSignals& RHS) const {
+ return std::tie(Symbol, Signals) == std::tie(RHS.Symbol, RHS.Signals);
+}
+
+bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
+ const SymbolInfo::SignalMap &Symbols) {
+ llvm::yaml::Output yout(OS);
+ for (const auto &Symbol : Symbols) {
+ SymbolAndSignals S{Symbol.first, Symbol.second};
+ yout << S;
+ }
+ return true;
+}
+
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml) {
+ std::vector<SymbolAndSignals> Symbols;
+ llvm::yaml::Input yin(Yaml);
+ yin >> Symbols;
+ return Symbols;
+}
+
+} // namespace find_all_symbols
+} // namespace clang
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.h
new file mode 100644
index 00000000000..6def1c70218
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolInfo.h
@@ -0,0 +1,142 @@
+//===-- SymbolInfo.h - Symbol Info ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <set>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+/// \brief Describes a named symbol from a header.
+/// Symbols with the same qualified name and type (e.g. function overloads)
+/// that appear in the same header are represented by a single SymbolInfo.
+///
+/// TODO: keep track of instances, e.g. overload locations and signatures.
+class SymbolInfo {
+public:
+ /// \brief The SymbolInfo Type.
+ enum class SymbolKind {
+ Function,
+ Class,
+ Variable,
+ TypedefName,
+ EnumDecl,
+ EnumConstantDecl,
+ Macro,
+ Unknown,
+ };
+
+ /// \brief The Context Type.
+ enum class ContextType {
+ Namespace, // Symbols declared in a namespace.
+ Record, // Symbols declared in a class.
+ EnumDecl, // Enum constants declared in a enum declaration.
+ };
+
+ /// \brief A pair of <ContextType, ContextName>.
+ typedef std::pair<ContextType, std::string> Context;
+
+ // \brief Signals are signals gathered by observing how a symbol is used.
+ // These are used to rank results.
+ struct Signals {
+ Signals() {}
+ Signals(unsigned Seen, unsigned Used) : Seen(Seen), Used(Used) {}
+
+ // Number of times this symbol was visible to a TU.
+ unsigned Seen = 0;
+
+ // Number of times this symbol was referenced a TU's main file.
+ unsigned Used = 0;
+
+ Signals &operator+=(const Signals &RHS);
+ Signals operator+(const Signals &RHS) const;
+ bool operator==(const Signals &RHS) const;
+ };
+
+ using SignalMap = std::map<SymbolInfo, Signals>;
+
+ // The default constructor is required by YAML traits in
+ // LLVM_YAML_IS_DOCUMENT_LIST_VECTOR.
+ SymbolInfo() : Type(SymbolKind::Unknown) {}
+
+ SymbolInfo(llvm::StringRef Name, SymbolKind Type, llvm::StringRef FilePath,
+ const std::vector<Context> &Contexts);
+
+ void SetFilePath(llvm::StringRef Path) { FilePath = Path; }
+
+ /// \brief Get symbol name.
+ llvm::StringRef getName() const { return Name; }
+
+ /// \brief Get the fully-qualified symbol name.
+ std::string getQualifiedName() const;
+
+ /// \brief Get symbol type.
+ SymbolKind getSymbolKind() const { return Type; }
+
+ /// \brief Get a relative file path where symbol comes from.
+ llvm::StringRef getFilePath() const { return FilePath; }
+
+ /// \brief Get symbol contexts.
+ const std::vector<SymbolInfo::Context> &getContexts() const {
+ return Contexts;
+ }
+
+ bool operator<(const SymbolInfo &Symbol) const;
+
+ bool operator==(const SymbolInfo &Symbol) const;
+
+private:
+ friend struct llvm::yaml::MappingTraits<struct SymbolAndSignals>;
+
+ /// \brief Identifier name.
+ std::string Name;
+
+ /// \brief Symbol type.
+ SymbolKind Type;
+
+ /// \brief The file path where the symbol comes from. It's a relative file
+ /// path based on the build directory.
+ std::string FilePath;
+
+ /// \brief Contains information about symbol contexts. Context information is
+ /// stored from the inner-most level to outer-most level.
+ ///
+ /// For example, if a symbol 'x' is declared as:
+ /// namespace na { namespace nb { class A { int x; } } }
+ /// The contexts would be { {RECORD, "A"}, {NAMESPACE, "nb"}, {NAMESPACE,
+ /// "na"} }.
+ /// The name of an anonymous namespace is "".
+ ///
+ /// If the symbol is declared in `TranslationUnitDecl`, it has no context.
+ std::vector<Context> Contexts;
+};
+
+struct SymbolAndSignals {
+ SymbolInfo Symbol;
+ SymbolInfo::Signals Signals;
+ bool operator==(const SymbolAndSignals& RHS) const;
+};
+
+/// \brief Write SymbolInfos to a stream (YAML format).
+bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
+ const SymbolInfo::SignalMap &Symbols);
+
+/// \brief Read SymbolInfos from a YAML document.
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolReporter.h b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolReporter.h
new file mode 100644
index 00000000000..25e86219150
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/SymbolReporter.h
@@ -0,0 +1,29 @@
+//===--- SymbolReporter.h - Symbol Reporter ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
+
+#include "SymbolInfo.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief An interface for classes that collect symbols.
+class SymbolReporter {
+public:
+ virtual ~SymbolReporter() = default;
+
+ virtual void reportSymbols(llvm::StringRef FileName,
+ const SymbolInfo::SignalMap &Symbols) = 0;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt
new file mode 100644
index 00000000000..64278ad1843
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt
@@ -0,0 +1,24 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(find-all-symbols
+ FindAllSymbolsMain.cpp
+ )
+
+target_link_libraries(find-all-symbols
+ PRIVATE
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangFrontend
+ clangLex
+ clangSerialization
+ clangTooling
+ findAllSymbols
+ )
+
+install(TARGETS find-all-symbols
+ RUNTIME DESTINATION bin)
+
+install(PROGRAMS run-find-all-symbols.py
+ DESTINATION share/clang
+ COMPONENT find-all-symbols)
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
new file mode 100644
index 00000000000..dbbe0738d03
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -0,0 +1,151 @@
+//===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbolsAction.h"
+#include "STLPostfixHeaderMap.h"
+#include "SymbolInfo.h"
+#include "SymbolReporter.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
+#include <system_error>
+#include <vector>
+
+using namespace clang::tooling;
+using namespace llvm;
+using SymbolInfo = clang::find_all_symbols::SymbolInfo;
+
+// Apply a custom category to all command-line options so that they are the
+// only ones displayed.
+static cl::OptionCategory FindAllSymbolsCategory("find_all_symbols options");
+
+// CommonOptionsParser declares HelpMessage with a description of the common
+// command-line options related to the compilation database and input files.
+// It's nice to have this help message in all tools.
+static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+
+// A help message for this specific tool can be added afterwards.
+static cl::extrahelp MoreHelp("\nMore help text...");
+
+static cl::opt<std::string> OutputDir("output-dir", cl::desc(R"(
+The output directory for saving the results.)"),
+ cl::init("."),
+ cl::cat(FindAllSymbolsCategory));
+
+static cl::opt<std::string> MergeDir("merge-dir", cl::desc(R"(
+The directory for merging symbols.)"),
+ cl::init(""),
+ cl::cat(FindAllSymbolsCategory));
+namespace clang {
+namespace find_all_symbols {
+
+class YamlReporter : public SymbolReporter {
+public:
+ void reportSymbols(StringRef FileName,
+ const SymbolInfo::SignalMap &Symbols) override {
+ int FD;
+ SmallString<128> ResultPath;
+ llvm::sys::fs::createUniqueFile(
+ OutputDir + "/" + llvm::sys::path::filename(FileName) + "-%%%%%%.yaml",
+ FD, ResultPath);
+ llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
+ WriteSymbolInfosToStream(OS, Symbols);
+ }
+};
+
+bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
+ std::error_code EC;
+ SymbolInfo::SignalMap Symbols;
+ std::mutex SymbolMutex;
+ auto AddSymbols = [&](ArrayRef<SymbolAndSignals> NewSymbols) {
+ // Synchronize set accesses.
+ std::unique_lock<std::mutex> LockGuard(SymbolMutex);
+ for (const auto &Symbol : NewSymbols) {
+ Symbols[Symbol.Symbol] += Symbol.Signals;
+ }
+ };
+
+ // Load all symbol files in MergeDir.
+ {
+ llvm::ThreadPool Pool;
+ for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ // Parse YAML files in parallel.
+ Pool.async(
+ [&AddSymbols](std::string Path) {
+ auto Buffer = llvm::MemoryBuffer::getFile(Path);
+ if (!Buffer) {
+ llvm::errs() << "Can't open " << Path << "\n";
+ return;
+ }
+ std::vector<SymbolAndSignals> Symbols =
+ ReadSymbolInfosFromYAML(Buffer.get()->getBuffer());
+ for (auto &Symbol : Symbols) {
+ // Only count one occurrence per file, to avoid spam.
+ Symbol.Signals.Seen = std::min(Symbol.Signals.Seen, 1u);
+ Symbol.Signals.Used = std::min(Symbol.Signals.Used, 1u);
+ }
+ // FIXME: Merge without creating such a heavy contention point.
+ AddSymbols(Symbols);
+ },
+ Dir->path());
+ }
+ }
+
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
+ if (EC) {
+ llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
+ << '\n';
+ return false;
+ }
+ WriteSymbolInfosToStream(OS, Symbols);
+ return true;
+}
+
+} // namespace clang
+} // namespace find_all_symbols
+
+int main(int argc, const char **argv) {
+ CommonOptionsParser OptionsParser(argc, argv, FindAllSymbolsCategory);
+ ClangTool Tool(OptionsParser.getCompilations(),
+ OptionsParser.getSourcePathList());
+
+ std::vector<std::string> sources = OptionsParser.getSourcePathList();
+ if (sources.empty()) {
+ llvm::errs() << "Must specify at least one one source file.\n";
+ return 1;
+ }
+ if (!MergeDir.empty()) {
+ clang::find_all_symbols::Merge(MergeDir, sources[0]);
+ return 0;
+ }
+
+ clang::find_all_symbols::YamlReporter Reporter;
+
+ auto Factory =
+ llvm::make_unique<clang::find_all_symbols::FindAllSymbolsActionFactory>(
+ &Reporter, clang::find_all_symbols::getSTLPostfixHeaderMap());
+ return Tool.run(Factory.get());
+}
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py
new file mode 100755
index 00000000000..5e9dde72343
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+#
+#=- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python -*-=#
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+#===------------------------------------------------------------------------===#
+
+"""
+Parallel find-all-symbols runner
+================================
+
+Runs find-all-symbols over all files in a compilation database.
+
+Example invocations.
+- Run find-all-symbols on all files in the current working directory.
+ run-find-all-symbols.py <source-file>
+
+Compilation database setup:
+http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+"""
+
+import argparse
+import json
+import multiprocessing
+import os
+import Queue
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+
+
+def find_compilation_database(path):
+ """Adjusts the directory until a compilation database is found."""
+ result = './'
+ while not os.path.isfile(os.path.join(result, path)):
+ if os.path.realpath(result) == '/':
+ print 'Error: could not find compilation database.'
+ sys.exit(1)
+ result += '../'
+ return os.path.realpath(result)
+
+
+def MergeSymbols(directory, args):
+ """Merge all symbol files (yaml) in a given directaory into a single file."""
+ invocation = [args.binary, '-merge-dir='+directory, args.saving_path]
+ subprocess.call(invocation)
+ print 'Merge is finished. Saving results in ' + args.saving_path
+
+
+def run_find_all_symbols(args, tmpdir, build_path, queue):
+ """Takes filenames out of queue and runs find-all-symbols on them."""
+ while True:
+ name = queue.get()
+ invocation = [args.binary, name, '-output-dir='+tmpdir, '-p='+build_path]
+ sys.stdout.write(' '.join(invocation) + '\n')
+ subprocess.call(invocation)
+ queue.task_done()
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Runs find-all-symbols over all'
+ 'files in a compilation database.')
+ parser.add_argument('-binary', metavar='PATH',
+ default='./bin/find-all-symbols',
+ help='path to find-all-symbols binary')
+ parser.add_argument('-j', type=int, default=0,
+ help='number of instances to be run in parallel.')
+ parser.add_argument('-p', dest='build_path',
+ help='path used to read a compilation database.')
+ parser.add_argument('-saving-path', default='./find_all_symbols_db.yaml',
+ help='result saving path')
+ args = parser.parse_args()
+
+ db_path = 'compile_commands.json'
+
+ if args.build_path is not None:
+ build_path = args.build_path
+ else:
+ build_path = find_compilation_database(db_path)
+
+ tmpdir = tempfile.mkdtemp()
+
+ # Load the database and extract all files.
+ database = json.load(open(os.path.join(build_path, db_path)))
+ files = [entry['file'] for entry in database]
+
+ max_task = args.j
+ if max_task == 0:
+ max_task = multiprocessing.cpu_count()
+
+ try:
+ # Spin up a bunch of tidy-launching threads.
+ queue = Queue.Queue(max_task)
+ for _ in range(max_task):
+ t = threading.Thread(target=run_find_all_symbols,
+ args=(args, tmpdir, build_path, queue))
+ t.daemon = True
+ t.start()
+
+ # Fill the queue with files.
+ for name in files:
+ queue.put(name)
+
+ # Wait for all threads to be done.
+ queue.join()
+
+ MergeSymbols(tmpdir, args)
+
+
+ except KeyboardInterrupt:
+ # This is a sad hack. Unfortunately subprocess goes
+ # bonkers with ctrl-c and we start forking merrily.
+ print '\nCtrl-C detected, goodbye.'
+ os.kill(0, 9)
+
+
+if __name__ == '__main__':
+ main()
OpenPOWER on IntegriCloud