[clang-tools-extra] r267719 - [include-fixer] Add a find-all-symbols tool for include-fixer.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 27 07:27:06 PDT 2016


Author: hokein
Date: Wed Apr 27 09:27:05 2016
New Revision: 267719

URL: http://llvm.org/viewvc/llvm-project?rev=267719&view=rev
Log:
[include-fixer] Add a find-all-symbols tool for include-fixer.

Summary:
The find-all-symbols tool generates a yaml symbol database for
include-fixer.

The symbol matcher is originally written by Xiaoyi Liu.

Reviewers: bkramer, djasper

Subscribers: cfe-commits, klimek, ioeric

Differential Revision: http://reviews.llvm.org/D19482

Added:
    clang-tools-extra/trunk/include-fixer/find-all-symbols/
    clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt
      - copied, changed from r267718, clang-tools-extra/trunk/include-fixer/CMakeLists.txt
    clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
    clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h
    clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp
    clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h
    clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/
    clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/CMakeLists.txt
    clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
    clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
    clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/
    clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/CMakeLists.txt
    clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
Modified:
    clang-tools-extra/trunk/include-fixer/CMakeLists.txt
    clang-tools-extra/trunk/unittests/include-fixer/CMakeLists.txt

Modified: clang-tools-extra/trunk/include-fixer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/CMakeLists.txt?rev=267719&r1=267718&r2=267719&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/include-fixer/CMakeLists.txt Wed Apr 27 09:27:05 2016
@@ -18,3 +18,4 @@ add_clang_library(clangIncludeFixer
   )
 
 add_subdirectory(tool)
+add_subdirectory(find-all-symbols)

Copied: clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt (from r267718, clang-tools-extra/trunk/include-fixer/CMakeLists.txt)
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt?p2=clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt&p1=clang-tools-extra/trunk/include-fixer/CMakeLists.txt&r1=267718&r2=267719&rev=267719&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt Wed Apr 27 09:27:05 2016
@@ -1,18 +1,16 @@
 set(LLVM_LINK_COMPONENTS
-  support
+  Support
   )
 
-add_clang_library(clangIncludeFixer
-  IncludeFixer.cpp
-  InMemoryXrefsDB.cpp
+add_clang_library(findAllSymbols
+  FindAllSymbols.cpp
+  SymbolInfo.cpp
 
   LINK_LIBS
   clangAST
+  clangASTMatchers
   clangBasic
   clangFrontend
-  clangLex
-  clangParse
-  clangSema
   clangTooling
   clangToolingCore
   )

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp Wed Apr 27 09:27:05 2016
@@ -0,0 +1,193 @@
+//===-- FindAllSymbols.cpp - find all symbols -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbols.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/Support/FileSystem.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace find_all_symbols {
+namespace {
+void SetContext(const NamedDecl *ND, SymbolInfo *Symbol) {
+  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)) {
+      Symbol->Contexts.emplace_back(
+              SymbolInfo::Namespace,
+                  NSD->isAnonymousNamespace() ? "" : NSD->getName().str());
+    } else {
+      const auto *RD = cast<RecordDecl>(Context);
+      Symbol->Contexts.emplace_back(SymbolInfo::Record, RD->getName().str());
+    }
+  }
+}
+
+bool SetCommonInfo(const MatchFinder::MatchResult &Result,
+                   const NamedDecl *ND, SymbolInfo *Symbol) {
+  SetContext(ND, Symbol);
+
+  Symbol->Name = ND->getNameAsString();
+  SourceLocation Loc = Result.SourceManager->getExpansionLoc(ND->getLocation());
+  if (!Loc.isValid()) {
+    llvm::errs() << "Declaration " << ND->getNameAsString() << "("
+                 << ND->getDeclKindName()
+                 << ") has invalid declaration location.";
+    return false;
+  }
+  std::string FilePath = Result.SourceManager->getFilename(Loc).str();
+  if (FilePath.empty())
+    return false;
+
+  Symbol->FilePath = FilePath;
+  Symbol->LineNumber = Result.SourceManager->getExpansionLineNumber(Loc);
+  return true;
+}
+} // 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(classTemplateSpecializationDecl()),
+            unless(isExplicitTemplateSpecialization()));
+
+  // 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.
+  MatchFinder->addMatcher(varDecl(CommonFilter,
+                                  anyOf(ExternCMatcher, CCMatcher),
+                                  unless(parmVarDecl()))
+                              .bind("decl"),
+                          this);
+
+  // Matchers for C-style record declarations in extern "C" {...}.
+  MatchFinder->addMatcher(
+      recordDecl(CommonFilter, ExternCMatcher, isDefinition()).bind("decl"),
+      this);
+
+  // Matchers for C++ record declarations.
+  auto CxxRecordDecl =
+      cxxRecordDecl(CommonFilter, CCMatcher, isDefinition(),
+                    unless(isExplicitTemplateSpecialization()));
+  MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this);
+
+  // Matchers for function declarations.
+  MatchFinder->addMatcher(
+      functionDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher)).bind("decl"),
+      this);
+
+  // Matcher for typedef and type alias declarations.
+  //
+  // typedef and type alias can come from C-style headers and C++ heaeders.
+  // For C-style header, `DeclContxet` can be either `TranslationUnitDecl`
+  // or `LinkageSpecDecl`.
+  // For C++ header, `DeclContext ` can be one of `TranslationUnitDecl`,
+  // `NamespaceDecl`.
+  // With the following context matcher, we can match `typedefNameDecl` from
+  // both C-style header and C++ header (except for those in classes).
+  // "cc_matchers" are not included since template-related matchers are not
+  // applicable on `TypedefNameDecl`.
+  MatchFinder->addMatcher(
+      typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher,
+                                          hasDeclContext(linkageSpecDecl())))
+          .bind("decl"),
+      this);
+}
+
+void FindAllSymbols::run(const MatchFinder::MatchResult &Result) {
+  // Ignore Results in failing TUs.
+  if (Result.Context->getDiagnostics().hasErrorOccurred()) {
+    return;
+  }
+
+  const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("decl");
+  assert(ND && "Matched declaration must be a NamedDecl!");
+  const SourceManager *SM = Result.SourceManager;
+
+  SymbolInfo Symbol;
+  if (!SetCommonInfo(Result, ND, &Symbol))
+    return;
+
+  if (const auto *VD = llvm::dyn_cast<VarDecl>(ND)) {
+    Symbol.Type = SymbolInfo::Variable;
+    SymbolInfo::VariableInfo VI;
+    VI.Type = VD->getType().getAsString();
+    Symbol.VariableInfos = VI;
+  } else if (const auto *FD = llvm::dyn_cast<FunctionDecl>(ND)) {
+    Symbol.Type = SymbolInfo::Function;
+    SymbolInfo::FunctionInfo FI;
+    FI.ReturnType = FD->getReturnType().getAsString();
+    for (const auto *Param : FD->params())
+      FI.ParameterTypes.push_back(Param->getType().getAsString());
+    Symbol.FunctionInfos = FI;
+  } else if (const auto *TD = llvm::dyn_cast<TypedefNameDecl>(ND)) {
+    Symbol.Type = SymbolInfo::TypedefName;
+    SymbolInfo::TypedefNameInfo TI;
+    TI.UnderlyingType = TD->getUnderlyingType().getAsString();
+    Symbol.TypedefNameInfos = TI;
+  } else {
+    assert(
+        llvm::isa<RecordDecl>(ND) &&
+        "Matched decl must be one of VarDecl, FunctionDecl, and RecordDecl!");
+    // C-style record decl can have empty name, e.g "struct { ... } var;".
+    if (ND->getName().empty())
+      return;
+    Symbol.Type = SymbolInfo::Class;
+  }
+
+  const FileEntry *FE = SM->getFileEntryForID(SM->getMainFileID());
+  Reporter->reportResult(FE->getName(), Symbol);
+}
+
+} // namespace find_all_symbols
+} // namespace clang

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h Wed Apr 27 09:27:05 2016
@@ -0,0 +1,56 @@
+//===-- FindAllSymbols.h - find all symbols----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H
+
+#include "SymbolInfo.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \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 clang::ast_matchers::MatchFinder::MatchCallback {
+public:
+  class ResultReporter {
+  public:
+    virtual ~ResultReporter() = default;
+
+    virtual void reportResult(llvm::StringRef FileName,
+                              const SymbolInfo &Symbol) = 0;
+  };
+
+  explicit FindAllSymbols(ResultReporter *Reporter) : Reporter(Reporter) {}
+
+  void registerMatchers(clang::ast_matchers::MatchFinder *MatchFinder);
+
+  void
+  run(const clang::ast_matchers::MatchFinder::MatchResult &result) override;
+
+private:
+  ResultReporter *const Reporter;
+};
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp Wed Apr 27 09:27:05 2016
@@ -0,0 +1,121 @@
+//===-- SymbolInfo.cpp ----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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 SymbolKind = clang::find_all_symbols::SymbolInfo::SymbolKind;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(SymbolInfo)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolInfo::Context)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<SymbolInfo> {
+  static void mapping(IO &io, SymbolInfo &Symbol) {
+    io.mapRequired("Name", Symbol.Name);
+    io.mapRequired("Contexts", Symbol.Contexts);
+    io.mapRequired("FilePath", Symbol.FilePath);
+    io.mapRequired("LineNumber", Symbol.LineNumber);
+    io.mapRequired("Type", Symbol.Type);
+    io.mapOptional("Variable", Symbol.VariableInfos);
+    io.mapOptional("Function", Symbol.FunctionInfos);
+    io.mapOptional("TypedefName", Symbol.TypedefNameInfos);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<ContextType> {
+  static void enumeration(IO &io, ContextType &value) {
+    io.enumCase(value, "Record", ContextType::Record);
+    io.enumCase(value, "Namespace", ContextType::Namespace);
+  }
+};
+
+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);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo::Context> {
+  static void mapping(IO &io, SymbolInfo::Context &Context) {
+    io.mapRequired("ContextType", Context.first);
+    io.mapRequired("ContextName", Context.second);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo::FunctionInfo> {
+  static void mapping(IO &io, SymbolInfo::FunctionInfo &Value) {
+    io.mapRequired("ReturnType", Value.ReturnType);
+    io.mapRequired("ParameterTypes", Value.ParameterTypes);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo::VariableInfo> {
+  static void mapping(IO &io, SymbolInfo::VariableInfo &Value) {
+    io.mapRequired("VariableType", Value.Type);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo::TypedefNameInfo> {
+  static void mapping(IO &io, SymbolInfo::TypedefNameInfo &Value) {
+    io.mapRequired("TypedefNameType", Value.UnderlyingType);
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace find_all_symbols {
+
+bool SymbolInfo::operator==(const SymbolInfo &Symbol) const {
+  return Name == Symbol.Name && FilePath == Symbol.FilePath &&
+         LineNumber == Symbol.LineNumber && Contexts == Symbol.Contexts;
+}
+
+bool SymbolInfo::operator<(const SymbolInfo &Symbol) const {
+  return std::tie(Name, FilePath, LineNumber) <
+         std::tie(Symbol.Name, Symbol.FilePath, Symbol.LineNumber);
+}
+
+bool WriteSymboInfosToFile(llvm::StringRef FilePath,
+                           const std::set<SymbolInfo> &Symbols) {
+  int FD = 0;
+  if (llvm::sys::fs::openFileForWrite(FilePath, FD, llvm::sys::fs::F_None))
+    return false;
+  llvm::raw_fd_ostream OS(FD, true);
+  llvm::yaml::Output yout(OS);
+  for (auto Symbol : Symbols)
+    yout << Symbol;
+  OS.close();
+  return true;
+}
+
+std::vector<SymbolInfo> ReadSymbolInfosFromYAML(llvm::StringRef Yaml) {
+  std::vector<SymbolInfo> Symbols;
+  llvm::yaml::Input yin(Yaml);
+  yin >> Symbols;
+  return Symbols;
+}
+
+} // namespace find_all_symbols
+} // namespace clang

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h Wed Apr 27 09:27:05 2016
@@ -0,0 +1,100 @@
+//===-- SymbolInfo.h - find all symbols--------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOL_INFO_H
+#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOL_INFO_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <set>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace find_all_symbols {
+
+/// \brief Contains all information for a Symbol.
+struct SymbolInfo {
+  enum SymbolKind {
+    Function,
+    Class,
+    Variable,
+    TypedefName,
+  };
+
+  enum ContextType {
+    Namespace, // Symbols declared in a namespace.
+    Record,    // Symbols declared in a class.
+  };
+
+  /// \brief Identifier name.
+  std::string Name;
+
+  /// \brief Symbol type.
+  SymbolKind Type;
+
+  /// \brief The file path where the symbol comes from.
+  std::string FilePath;
+
+  /// \brief A pair of <ContextType, ContextName>.
+  typedef std::pair<ContextType, std::string> Context;
+
+  /// \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;
+
+  /// \brief The 1-based line number of of the symbol's declaration.
+  int LineNumber;
+
+  struct FunctionInfo {
+    std::string ReturnType;
+    std::vector<std::string> ParameterTypes;
+  };
+
+  struct TypedefNameInfo {
+    std::string UnderlyingType;
+  };
+
+  struct VariableInfo {
+    std::string Type;
+  };
+
+  /// \brief The function information.
+  llvm::Optional<FunctionInfo> FunctionInfos;
+
+  /// \brief The typedef information.
+  llvm::Optional<TypedefNameInfo> TypedefNameInfos;
+
+  /// \brief The variable information.
+  llvm::Optional<VariableInfo> VariableInfos;
+
+  bool operator==(const SymbolInfo &Symbol) const;
+
+  bool operator<(const SymbolInfo &Symbol) const;
+};
+
+/// \brief Write SymbolInfos to a single file (YAML format).
+bool WriteSymboInfosToFile(llvm::StringRef FilePath,
+                           const std::set<SymbolInfo> &Symbols);
+
+/// \brief Read SymbolInfos from a YAML document.
+std::vector<SymbolInfo> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);
+
+} // namespace find_all_symbols
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOL_INFO_H

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/CMakeLists.txt?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/CMakeLists.txt (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/CMakeLists.txt Wed Apr 27 09:27:05 2016
@@ -0,0 +1,13 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_clang_executable(find-all-symbols FindAllSymbolsMain.cpp)
+target_link_libraries(find-all-symbols
+
+  clangASTMatchers
+  clangBasic
+  clangDynamicASTMatchers
+  clangFrontend
+  clangQuery
+  clangTooling
+  findAllSymbols
+  )

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp Wed Apr 27 09:27:05 2016
@@ -0,0 +1,122 @@
+//===-- FindAllSymbolsMain.cpp --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbols.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Path.h"
+
+#include <map>
+#include <string>
+#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 clang::find_all_symbols::FindAllSymbols::ResultReporter {
+public:
+  ~YamlReporter() {}
+
+  void reportResult(StringRef FileName, const SymbolInfo &Symbol) override {
+    Symbols[FileName].insert(Symbol);
+  }
+
+  void Write(const std::string &Dir) {
+    for (const auto &Symbol : Symbols) {
+      SmallString<256> FilePath(Dir);
+      llvm::sys::path::append(
+          FilePath, llvm::sys::path::filename(Symbol.first) + ".yaml");
+      WriteSymboInfosToFile(FilePath, Symbol.second);
+    }
+  }
+
+private:
+  std::map<std::string, std::set<SymbolInfo>> Symbols;
+};
+
+bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
+  std::error_code EC;
+  std::set<SymbolInfo> UniqueSymbols;
+  // Load all symbol files in MergeDir.
+  for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd;
+       Dir != DirEnd && !EC; Dir.increment(EC)) {
+    int ReadFD = 0;
+    if (llvm::sys::fs::openFileForRead(Dir->path(), ReadFD)) {
+      llvm::errs() << "Cann't open " << Dir->path() << "\n";
+      continue;
+    }
+    auto Buffer = llvm::MemoryBuffer::getOpenFile(ReadFD, Dir->path(), -1);
+    if (!Buffer)
+      continue;
+    std::vector<SymbolInfo> Symbols =
+        ReadSymbolInfosFromYAML(Buffer.get()->getBuffer());
+    for (const auto &Symbol : Symbols)
+      UniqueSymbols.insert(Symbol);
+  }
+
+  WriteSymboInfosToFile(OutputFile, UniqueSymbols);
+  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;
+  clang::find_all_symbols::FindAllSymbols Matcher(&Reporter);
+  clang::ast_matchers::MatchFinder MatchFinder;
+  Matcher.registerMatchers(&MatchFinder);
+  Tool.run(newFrontendActionFactory(&MatchFinder).get());
+  Reporter.Write(OutputDir);
+  return 0;
+}

Added: clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/run-find-all-symbols.py?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/run-find-all-symbols.py (added)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/run-find-all-symbols.py Wed Apr 27 09:27:05 2016
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+#
+#=- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python  -*-=#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+"""
+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()

Modified: clang-tools-extra/trunk/unittests/include-fixer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/include-fixer/CMakeLists.txt?rev=267719&r1=267718&r2=267719&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/include-fixer/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/unittests/include-fixer/CMakeLists.txt Wed Apr 27 09:27:05 2016
@@ -23,3 +23,5 @@ target_link_libraries(IncludeFixerTests
   clangTooling
   clangToolingCore
   )
+
+add_subdirectory(find-all-symbols)

Added: clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/CMakeLists.txt?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/CMakeLists.txt (added)
+++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/CMakeLists.txt Wed Apr 27 09:27:05 2016
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+get_filename_component(INCLUDE_FIXER_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../../include-fixer/find-all-symbols REALPATH)
+include_directories(
+  ${INCLUDE_FIXER_SOURCE_DIR}
+  )
+
+add_extra_unittest(FindAllSymbolsTests
+  FindAllSymbolsTests.cpp
+  )
+
+target_link_libraries(FindAllSymbolsTests
+  clangBasic
+  clangFrontend
+  clangTooling
+  clangToolingCore
+  findAllSymbols
+  )

Added: clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp?rev=267719&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp (added)
+++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp Wed Apr 27 09:27:05 2016
@@ -0,0 +1,364 @@
+//===-- FindAllSymbolsTests.cpp - find all symbols unit tests -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FindAllSymbols.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace find_all_symbols {
+
+static const char HeaderName[] = "symbols.h";
+
+class MockReporter
+    : public clang::find_all_symbols::FindAllSymbols::ResultReporter {
+public:
+  ~MockReporter() {}
+
+  void reportResult(llvm::StringRef FileName,
+                    const SymbolInfo &Symbol) override {
+    Symbols.push_back(Symbol);
+  }
+
+  bool hasSymbol(const SymbolInfo &Symbol) {
+    for (const auto &S : Symbols) {
+      if (S == Symbol)
+        return true;
+    }
+    return false;
+  }
+
+  bool getSymbolExtraInfo(SymbolInfo *Symbol) {
+    for (const auto &S : Symbols) {
+      if (S == *Symbol) {
+        Symbol->FunctionInfos = S.FunctionInfos;
+        Symbol->TypedefNameInfos = S.TypedefNameInfos;
+        Symbol->VariableInfos = S.VariableInfos;
+        return true;
+      }
+    }
+    return false;
+  }
+
+private:
+  std::vector<SymbolInfo> Symbols;
+};
+
+class FindAllSymbolsTest : public ::testing::Test {
+public:
+  bool hasSymbol(const SymbolInfo &Symbol) {
+    return Reporter.hasSymbol(Symbol);
+  }
+
+  bool getSymbolExtraInfo(SymbolInfo &Symbol) {
+    return Reporter.getSymbolExtraInfo(&Symbol);
+  }
+
+  bool runFindAllSymbols(StringRef Code) {
+    FindAllSymbols matcher(&Reporter);
+    clang::ast_matchers::MatchFinder MatchFinder;
+    matcher.registerMatchers(&MatchFinder);
+
+    llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+        new vfs::InMemoryFileSystem);
+    llvm::IntrusiveRefCntPtr<FileManager> Files(
+        new FileManager(FileSystemOptions(), InMemoryFileSystem));
+
+    std::string FileName = "symbol.cc";
+    std::unique_ptr<clang::tooling::FrontendActionFactory> Factory =
+        clang::tooling::newFrontendActionFactory(&MatchFinder);
+    tooling::ToolInvocation Invocation(
+        {std::string("find_all_symbols"), std::string("-fsyntax-only"),
+         FileName},
+        Factory->create(), Files.get(),
+        std::make_shared<PCHContainerOperations>());
+
+    InMemoryFileSystem->addFile(HeaderName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(Code));
+
+    std::string Content = "#include\"" + std::string(HeaderName) + "\"";
+    InMemoryFileSystem->addFile(FileName, 0,
+                                llvm::MemoryBuffer::getMemBuffer(Content));
+    Invocation.run();
+    return true;
+  }
+
+private:
+  MockReporter Reporter;
+};
+
+SymbolInfo
+CreateSymbolInfo(StringRef Name, SymbolInfo::SymbolKind Type,
+                 const std::string FilePath, int LineNumber,
+                 const std::vector<SymbolInfo::Context> &Contexts) {
+  SymbolInfo Symbol;
+  Symbol.Name = Name;
+  Symbol.Type = Type;
+  Symbol.FilePath = FilePath;
+  Symbol.LineNumber = LineNumber;
+  Symbol.Contexts = Contexts;
+  return Symbol;
+}
+
+TEST_F(FindAllSymbolsTest, VariableSymbols) {
+  static const char Code[] = R"(
+      extern int xargc;
+      namespace na {
+      static bool SSSS = false;
+      namespace nb { const long long *XXXX; }
+      })";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("xargc", SymbolInfo::Variable, HeaderName, 2, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.VariableInfos.getValue().Type);
+  }
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("SSSS", SymbolInfo::Variable, HeaderName, 4,
+                         {{SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("_Bool", Symbol.VariableInfos.getValue().Type);
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo(
+        "XXXX", SymbolInfo::Variable, HeaderName, 5,
+        {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("const long long *", Symbol.VariableInfos.getValue().Type);
+  }
+}
+
+TEST_F(FindAllSymbolsTest, ExternCSymbols) {
+  static const char Code[] = R"(
+      extern "C" {
+      int C_Func() { return 0; }
+      struct C_struct {
+        int Member;
+      };
+      })";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("C_Func", SymbolInfo::Function, HeaderName, 3, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.FunctionInfos.getValue().ReturnType);
+    EXPECT_TRUE(Symbol.FunctionInfos.getValue().ParameterTypes.empty());
+  }
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("C_struct", SymbolInfo::Class, HeaderName, 4, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+  }
+}
+
+TEST_F(FindAllSymbolsTest, CXXRecordSymbols) {
+  static const char Code[] = R"(
+      struct Glob {};
+      struct A; // Not a defintion, ignored.
+      class NOP; // Not a defintion, ignored
+      namespace na {
+      struct A {
+        struct AAAA {};
+        int x;
+        int y;
+        void f() {}
+      };
+      };  //
+      )";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("Glob", SymbolInfo::Class, HeaderName, 2, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo("A", SymbolInfo::Class, HeaderName, 6,
+                                         {{SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+  }
+}
+
+TEST_F(FindAllSymbolsTest, CXXRecordSymbolsTemplate) {
+  static const char Code[] = R"(
+      template <typename T>
+      class T_TEMP {
+        template <typename _Tp1>
+        struct rebind { typedef T_TEMP<_Tp1> other; };
+      };
+      // Ignore specialization.
+      template class T_TEMP<char>;
+
+      template <typename T>
+      class Observer {
+      };
+      // Ignore specialization.
+      template <> class Observer<int> {};
+      )";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("T_TEMP", SymbolInfo::Class, HeaderName, 3, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+  }
+}
+
+TEST_F(FindAllSymbolsTest, FunctionSymbols) {
+  static const char Code[] = R"(
+      namespace na {
+      int gg(int);
+      int f(const int &a) { int Local; static int StaticLocal; return 0; }
+      static void SSSFFF() {}
+      }  // namespace na
+      namespace na {
+      namespace nb {
+      template<typename T>
+      void fun(T t) {};
+      } // namespace nb
+      } // namespace na";
+      )";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol = CreateSymbolInfo("gg", SymbolInfo::Class, HeaderName, 3,
+                                         {{SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.FunctionInfos.getValue().ReturnType);
+    EXPECT_EQ(1, Symbol.FunctionInfos.getValue().ParameterTypes.size());
+    EXPECT_EQ("int", Symbol.FunctionInfos.getValue().ParameterTypes[0]);
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo("f", SymbolInfo::Class, HeaderName, 4,
+                                         {{SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.FunctionInfos.getValue().ReturnType);
+    EXPECT_EQ(1, Symbol.FunctionInfos.getValue().ParameterTypes.size());
+    EXPECT_EQ("const int &", Symbol.FunctionInfos.getValue().ParameterTypes[0]);
+  }
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("SSSFFF", SymbolInfo::Class, HeaderName, 5,
+                         {{SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("void", Symbol.FunctionInfos.getValue().ReturnType);
+    EXPECT_TRUE(Symbol.FunctionInfos.getValue().ParameterTypes.empty());
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo(
+        "fun", SymbolInfo::Class, HeaderName, 10,
+        {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, "na"}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("void", Symbol.FunctionInfos.getValue().ReturnType);
+    EXPECT_EQ(1, Symbol.FunctionInfos.getValue().ParameterTypes.size());
+    EXPECT_EQ("T", Symbol.FunctionInfos.getValue().ParameterTypes[0]);
+  }
+}
+
+TEST_F(FindAllSymbolsTest, NamespaceTest) {
+  static const char Code[] = R"(
+      int X1;
+      namespace { int X2; }
+      namespace { namespace { int X3; } }
+      namespace { namespace nb { int X4;} }
+      )";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("X1", SymbolInfo::Variable, HeaderName, 2, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.VariableInfos.getValue().Type);
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo("X2", SymbolInfo::Variable, HeaderName,
+                                         3, {{SymbolInfo::Namespace, ""}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.VariableInfos.getValue().Type);
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo(
+        "X3", SymbolInfo::Variable, HeaderName, 4,
+        {{SymbolInfo::Namespace, ""}, {SymbolInfo::Namespace, ""}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.VariableInfos.getValue().Type);
+  }
+  {
+    SymbolInfo Symbol = CreateSymbolInfo(
+        "X4", SymbolInfo::Variable, HeaderName, 5,
+        {{SymbolInfo::Namespace, "nb"}, {SymbolInfo::Namespace, ""}});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("int", Symbol.VariableInfos.getValue().Type);
+  }
+}
+
+TEST_F(FindAllSymbolsTest, DecayedTypeTest) {
+  static const char Code[] = "void DecayedFunc(int x[], int y[10]) {}";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+      CreateSymbolInfo("DecayedFunc", SymbolInfo::Class, HeaderName, 1, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  getSymbolExtraInfo(Symbol);
+  EXPECT_EQ("void", Symbol.FunctionInfos.getValue().ReturnType);
+  EXPECT_EQ(2, Symbol.FunctionInfos.getValue().ParameterTypes.size());
+  EXPECT_EQ("int *", Symbol.FunctionInfos.getValue().ParameterTypes[0]);
+  EXPECT_EQ("int *", Symbol.FunctionInfos.getValue().ParameterTypes[1]);
+}
+
+TEST_F(FindAllSymbolsTest, CTypedefTest) {
+  static const char Code[] = R"(
+      typedef unsigned size_t;
+      typedef struct { int x; } X;
+      using XX = X;
+      )";
+  runFindAllSymbols(Code);
+
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("size_t", SymbolInfo::TypedefName, HeaderName, 2, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("unsigned int",
+              Symbol.TypedefNameInfos.getValue().UnderlyingType);
+  }
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("X", SymbolInfo::TypedefName, HeaderName, 3, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("struct X", Symbol.TypedefNameInfos.getValue().UnderlyingType);
+  }
+  {
+    SymbolInfo Symbol =
+        CreateSymbolInfo("XX", SymbolInfo::TypedefName, HeaderName, 4, {});
+    EXPECT_TRUE(hasSymbol(Symbol));
+    getSymbolExtraInfo(Symbol);
+    EXPECT_EQ("X", Symbol.TypedefNameInfos.getValue().UnderlyingType);
+  }
+}
+
+} // namespace find_all_symbols
+} // namespace clang




More information about the cfe-commits mailing list