[clang-tools-extra] r296446 - [include-fixer] Add usage count to find-all-symbols.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 28 00:13:16 PST 2017


Author: sammccall
Date: Tue Feb 28 02:13:15 2017
New Revision: 296446

URL: http://llvm.org/viewvc/llvm-project?rev=296446&view=rev
Log:
[include-fixer] Add usage count to find-all-symbols.

Summary:
Add usage count to find-all-symbols.

FindAllSymbols now finds (most!) main-file usages of the discovered symbols.
The per-TU map output has NumUses=0 or 1 (only one use per file is counted).
The reducer aggregates these to find the number of files that use a symbol.

The NumOccurrences is now set to 1 in the mapper rather than being inferred by
the reducer, for consistency.

The idea here is to use NumUses for ranking: intuitively number of files that
use a symbol is more meaningful than number of files that include the header.

Reviewers: hokein, bkramer

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D30210

Modified:
    clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.cpp
    clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.h
    clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp
    clang-tools-extra/trunk/include-fixer/SymbolIndex.h
    clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp
    clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.cpp
    clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.h
    clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp
    clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h
    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/FindAllSymbolsAction.cpp
    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/SymbolReporter.h
    clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
    clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp
    clang-tools-extra/trunk/test/include-fixer/Inputs/fake_yaml_db.yaml
    clang-tools-extra/trunk/test/include-fixer/Inputs/merge/a.yaml
    clang-tools-extra/trunk/test/include-fixer/Inputs/merge/b.yaml
    clang-tools-extra/trunk/test/include-fixer/merge.test
    clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp
    clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp

Modified: clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.cpp Tue Feb 28 02:13:15 2017
@@ -9,18 +9,18 @@
 
 #include "InMemorySymbolIndex.h"
 
-using clang::find_all_symbols::SymbolInfo;
+using clang::find_all_symbols::SymbolAndSignals;
 
 namespace clang {
 namespace include_fixer {
 
 InMemorySymbolIndex::InMemorySymbolIndex(
-    const std::vector<SymbolInfo> &Symbols) {
+    const std::vector<SymbolAndSignals> &Symbols) {
   for (const auto &Symbol : Symbols)
-    LookupTable[Symbol.getName()].push_back(Symbol);
+    LookupTable[Symbol.Symbol.getName()].push_back(Symbol);
 }
 
-std::vector<SymbolInfo>
+std::vector<SymbolAndSignals>
 InMemorySymbolIndex::search(llvm::StringRef Identifier) {
   auto I = LookupTable.find(Identifier);
   if (I != LookupTable.end())

Modified: clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.h?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.h (original)
+++ clang-tools-extra/trunk/include-fixer/InMemorySymbolIndex.h Tue Feb 28 02:13:15 2017
@@ -21,13 +21,14 @@ namespace include_fixer {
 /// Xref database with fixed content.
 class InMemorySymbolIndex : public SymbolIndex {
 public:
-  InMemorySymbolIndex(const std::vector<find_all_symbols::SymbolInfo> &Symbols);
+  InMemorySymbolIndex(
+      const std::vector<find_all_symbols::SymbolAndSignals> &Symbols);
 
-  std::vector<clang::find_all_symbols::SymbolInfo>
+  std::vector<find_all_symbols::SymbolAndSignals>
   search(llvm::StringRef Identifier) override;
 
 private:
-  std::map<std::string, std::vector<clang::find_all_symbols::SymbolInfo>>
+  std::map<std::string, std::vector<find_all_symbols::SymbolAndSignals>>
       LookupTable;
 };
 

Modified: clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp Tue Feb 28 02:13:15 2017
@@ -334,8 +334,7 @@ IncludeFixerContext IncludeFixerSemaSour
         SourceManager, HeaderSearch);
     SymbolCandidates.emplace_back(Symbol.getName(), Symbol.getSymbolKind(),
                                   MinimizedFilePath, Symbol.getLineNumber(),
-                                  Symbol.getContexts(),
-                                  Symbol.getNumOccurrences());
+                                  Symbol.getContexts());
   }
   return IncludeFixerContext(FilePath, QuerySymbolInfos, SymbolCandidates);
 }

Modified: clang-tools-extra/trunk/include-fixer/SymbolIndex.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/SymbolIndex.h?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/SymbolIndex.h (original)
+++ clang-tools-extra/trunk/include-fixer/SymbolIndex.h Tue Feb 28 02:13:15 2017
@@ -28,7 +28,7 @@ public:
   /// \returns A list of `SymbolInfo` candidates.
   // FIXME: Expose the type name so we can also insert using declarations (or
   // fix the usage)
-  virtual std::vector<clang::find_all_symbols::SymbolInfo>
+  virtual std::vector<find_all_symbols::SymbolAndSignals>
   search(llvm::StringRef Identifier) = 0;
 };
 

Modified: clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp Tue Feb 28 02:13:15 2017
@@ -19,7 +19,8 @@
 namespace clang {
 namespace include_fixer {
 
-using clang::find_all_symbols::SymbolInfo;
+using find_all_symbols::SymbolInfo;
+using find_all_symbols::SymbolAndSignals;
 
 // Calculate a score based on whether we think the given header is closely
 // related to the given source file.
@@ -45,26 +46,26 @@ static double similarityScore(llvm::Stri
   return MaxSegments;
 }
 
-static void rank(std::vector<SymbolInfo> &Symbols,
+static void rank(std::vector<SymbolAndSignals> &Symbols,
                  llvm::StringRef FileName) {
   llvm::DenseMap<llvm::StringRef, double> Score;
-  for (const SymbolInfo &Symbol : Symbols) {
+  for (const auto &Symbol : Symbols) {
     // Calculate a score from the similarity of the header the symbol is in
     // with the current file and the popularity of the symbol.
-    double NewScore = similarityScore(FileName, Symbol.getFilePath()) *
-                      (1.0 + std::log2(1 + Symbol.getNumOccurrences()));
-    double &S = Score[Symbol.getFilePath()];
+    double NewScore = similarityScore(FileName, Symbol.Symbol.getFilePath()) *
+                      (1.0 + std::log2(1 + Symbol.Signals.Seen));
+    double &S = Score[Symbol.Symbol.getFilePath()];
     S = std::max(S, NewScore);
   }
   // Sort by the gathered scores. Use file name as a tie breaker so we can
   // deduplicate.
   std::sort(Symbols.begin(), Symbols.end(),
-            [&](const SymbolInfo &A, const SymbolInfo &B) {
-              auto AS = Score[A.getFilePath()];
-              auto BS = Score[B.getFilePath()];
+            [&](const SymbolAndSignals &A, const SymbolAndSignals &B) {
+              auto AS = Score[A.Symbol.getFilePath()];
+              auto BS = Score[B.Symbol.getFilePath()];
               if (AS != BS)
                 return AS > BS;
-              return A.getFilePath() < B.getFilePath();
+              return A.Symbol.getFilePath() < B.Symbol.getFilePath();
             });
 }
 
@@ -88,9 +89,9 @@ SymbolIndexManager::search(llvm::StringR
   // Eventually we will either hit a class (namespaces aren't in the database
   // either) and can report that result.
   bool TookPrefix = false;
-  std::vector<clang::find_all_symbols::SymbolInfo> MatchedSymbols;
+  std::vector<SymbolAndSignals> MatchedSymbols;
   do {
-    std::vector<clang::find_all_symbols::SymbolInfo> Symbols;
+    std::vector<SymbolAndSignals> Symbols;
     for (const auto &DB : SymbolIndices) {
       auto Res = DB.get()->search(Names.back());
       Symbols.insert(Symbols.end(), Res.begin(), Res.end());
@@ -99,7 +100,8 @@ SymbolIndexManager::search(llvm::StringR
     DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got "
                        << Symbols.size() << " results...\n");
 
-    for (const auto &Symbol : Symbols) {
+    for (auto &SymAndSig : Symbols) {
+      const SymbolInfo &Symbol = SymAndSig.Symbol;
       // Match the identifier name without qualifier.
       if (Symbol.getName() == Names.back()) {
         bool IsMatched = true;
@@ -139,7 +141,7 @@ SymbolIndexManager::search(llvm::StringR
                Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Macro))
             continue;
 
-          MatchedSymbols.push_back(Symbol);
+          MatchedSymbols.push_back(std::move(SymAndSig));
         }
       }
     }
@@ -148,7 +150,11 @@ SymbolIndexManager::search(llvm::StringR
   } while (MatchedSymbols.empty() && !Names.empty() && IsNestedSearch);
 
   rank(MatchedSymbols, FileName);
-  return MatchedSymbols;
+  // Strip signals, they are no longer needed.
+  std::vector<SymbolInfo> Res;
+  for (const auto &SymAndSig : MatchedSymbols)
+    Res.push_back(std::move(SymAndSig.Symbol));
+  return Res;
 }
 
 } // namespace include_fixer

Modified: clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.cpp Tue Feb 28 02:13:15 2017
@@ -17,6 +17,7 @@
 #include <vector>
 
 using clang::find_all_symbols::SymbolInfo;
+using clang::find_all_symbols::SymbolAndSignals;
 
 namespace clang {
 namespace include_fixer {
@@ -27,9 +28,8 @@ YamlSymbolIndex::createFromFile(llvm::St
   if (!Buffer)
     return Buffer.getError();
 
-  return std::unique_ptr<YamlSymbolIndex>(
-      new YamlSymbolIndex(clang::find_all_symbols::ReadSymbolInfosFromYAML(
-          Buffer.get()->getBuffer())));
+  return std::unique_ptr<YamlSymbolIndex>(new YamlSymbolIndex(
+      find_all_symbols::ReadSymbolInfosFromYAML(Buffer.get()->getBuffer())));
 }
 
 llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
@@ -47,10 +47,11 @@ YamlSymbolIndex::createFromDirectory(llv
   return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
 }
 
-std::vector<SymbolInfo> YamlSymbolIndex::search(llvm::StringRef Identifier) {
-  std::vector<SymbolInfo> Results;
+std::vector<SymbolAndSignals>
+YamlSymbolIndex::search(llvm::StringRef Identifier) {
+  std::vector<SymbolAndSignals> Results;
   for (const auto &Symbol : Symbols) {
-    if (Symbol.getName() == Identifier)
+    if (Symbol.Symbol.getName() == Identifier)
       Results.push_back(Symbol);
   }
   return Results;

Modified: clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.h?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.h (original)
+++ clang-tools-extra/trunk/include-fixer/YamlSymbolIndex.h Tue Feb 28 02:13:15 2017
@@ -29,15 +29,15 @@ public:
   static llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
   createFromDirectory(llvm::StringRef Directory, llvm::StringRef Name);
 
-  std::vector<clang::find_all_symbols::SymbolInfo>
+  std::vector<find_all_symbols::SymbolAndSignals>
   search(llvm::StringRef Identifier) override;
 
 private:
   explicit YamlSymbolIndex(
-      std::vector<clang::find_all_symbols::SymbolInfo> Symbols)
+      std::vector<find_all_symbols::SymbolAndSignals> Symbols)
       : Symbols(std::move(Symbols)) {}
 
-  std::vector<clang::find_all_symbols::SymbolInfo> Symbols;
+  std::vector<find_all_symbols::SymbolAndSignals> Symbols;
 };
 
 } // namespace include_fixer

Modified: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp Tue Feb 28 02:13:15 2017
@@ -13,24 +13,58 @@
 #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,
+                    SM->getSpellingLineNumber(info->getDefinitionLoc()), {});
+}
+
 void FindAllMacros::MacroDefined(const Token &MacroNameTok,
                                  const MacroDirective *MD) {
-  SourceLocation Loc = SM->getExpansionLoc(MacroNameTok.getLocation());
-  std::string FilePath = getIncludePath(*SM, Loc, Collector);
-  if (FilePath.empty()) return;
+  if (auto Symbol = CreateMacroSymbol(MacroNameTok, MD->getMacroInfo()))
+    ++FileSymbols[*Symbol].Seen;
+}
 
-  SymbolInfo Symbol(MacroNameTok.getIdentifierInfo()->getName(),
-                    SymbolInfo::SymbolKind::Macro, FilePath,
-                    SM->getSpellingLineNumber(Loc), {});
+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);
+}
 
-  Reporter->reportSymbol(SM->getFileEntryForID(SM->getMainFileID())->getName(),
-                         Symbol);
+void FindAllMacros::EndOfMainFile() {
+  Reporter->reportSymbols(SM->getFileEntryForID(SM->getMainFileID())->getName(),
+                          FileSymbols);
+  FileSymbols.clear();
 }
 
 } // namespace find_all_symbols

Modified: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h Tue Feb 28 02:13:15 2017
@@ -16,6 +16,7 @@
 #include "clang/Lex/PPCallbacks.h"
 
 namespace clang {
+class MacroInfo;
 namespace find_all_symbols {
 
 class HeaderMapCollector;
@@ -32,7 +33,24 @@ public:
   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;

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp Tue Feb 28 02:13:15 2017
@@ -154,64 +154,84 @@ void FindAllSymbols::registerMatchers(Ma
   // 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);
+  auto Vars = varDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher),
+                      unless(parmVarDecl()));
 
   // Matchers for C-style record declarations in extern "C" {...}.
-  MatchFinder->addMatcher(
-      recordDecl(CommonFilter, ExternCMatcher, isDefinition()).bind("decl"),
-      this);
-
+  auto CRecords = recordDecl(CommonFilter, ExternCMatcher, isDefinition());
   // Matchers for C++ record declarations.
-  auto CxxRecordDecl =
-      cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
-  MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this);
+  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`.
-  MatchFinder->addMatcher(functionDecl(CommonFilter,
-                                       unless(hasParent(friendDecl())),
-                                       anyOf(ExternCMatcher, CCMatcher))
-                              .bind("decl"),
-                          this);
+  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++ heaeders.
-  // For C-style header, `DeclContxet` can be either `TranslationUnitDecl`
+  // 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++ header, `DeclContext ` can be one of `TranslationUnitDecl`,
-  // `NamespaceDecl`.
+  // For C++ headers, `DeclContext ` can be either `TranslationUnitDecl`
+  // or `NamespaceDecl`.
   // With the following context matcher, we can match `typedefNameDecl` from
-  // both C-style header and C++ header (except for those in classes).
+  // 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`.
-  MatchFinder->addMatcher(
+  auto Typedefs =
       typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher,
-                                          hasDeclContext(linkageSpecDecl())))
-          .bind("decl"),
-      this);
+                                          hasDeclContext(linkageSpecDecl())));
 
   // Matchers for enum declarations.
-  MatchFinder->addMatcher(enumDecl(CommonFilter, isDefinition(),
-                                   anyOf(HasNSOrTUCtxMatcher, ExternCMatcher))
-                              .bind("decl"),
-                          this);
+  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, Typedefs));
+  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(
-      enumConstantDecl(
-          CommonFilter,
-          unless(isInScopedEnum()),
-          anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher))
-          .bind("decl"),
+      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 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(
+                  classTemplateDecl(has(CXXRecords.bind("use"))))))),
       this);
 }
 
@@ -221,15 +241,28 @@ void FindAllSymbols::run(const MatchFind
     return;
   }
 
-  const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("decl");
-  assert(ND && "Matched declaration must be a NamedDecl!");
+  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;
+  }
+}
 
-  llvm::Optional<SymbolInfo> Symbol =
-      CreateSymbolInfo(ND, *SM, Collector);
-  if (Symbol)
-    Reporter->reportSymbol(
-        SM->getFileEntryForID(SM->getMainFileID())->getName(), *Symbol);
+void FindAllSymbols::onEndOfTranslationUnit() {
+  if (Filename != "") {
+    Reporter->reportSymbols(Filename, FileSymbols);
+    FileSymbols.clear();
+    Filename = "";
+  }
 }
 
 } // namespace find_all_symbols

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h Tue Feb 28 02:13:15 2017
@@ -32,18 +32,24 @@ class HeaderMapCollector;
 ///   through the class. #include fixer only needs the class name to find
 ///   headers.
 ///
-class FindAllSymbols : public clang::ast_matchers::MatchFinder::MatchCallback {
+class FindAllSymbols : public ast_matchers::MatchFinder::MatchCallback {
 public:
   explicit FindAllSymbols(SymbolReporter *Reporter,
                           HeaderMapCollector *Collector = nullptr)
       : Reporter(Reporter), Collector(Collector) {}
 
-  void registerMatchers(clang::ast_matchers::MatchFinder *MatchFinder);
+  void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
 
-  void
-  run(const clang::ast_matchers::MatchFinder::MatchResult &result) override;
+  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

Modified: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp Tue Feb 28 02:13:15 2017
@@ -24,8 +24,8 @@ FindAllSymbolsAction::FindAllSymbolsActi
   Matcher.registerMatchers(&MatchFinder);
 }
 
-std::unique_ptr<clang::ASTConsumer>
-FindAllSymbolsAction::CreateASTConsumer(clang::CompilerInstance &Compiler,
+std::unique_ptr<ASTConsumer>
+FindAllSymbolsAction::CreateASTConsumer(CompilerInstance &Compiler,
                                         StringRef InFile) {
   Compiler.getPreprocessor().addCommentHandler(&Handler);
   Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique<FindAllMacros>(

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp Tue Feb 28 02:13:15 2017
@@ -18,22 +18,24 @@ 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(SymbolInfo)
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(SymbolAndSignals)
 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.mapRequired("NumOccurrences", Symbol.NumOccurrences);
+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("LineNumber", Symbol.Symbol.LineNumber);
+    io.mapRequired("Type", Symbol.Symbol.Type);
+    io.mapRequired("Seen", Symbol.Signals.Seen);
+    io.mapRequired("Used", Symbol.Signals.Used);
   }
 };
 
@@ -73,10 +75,9 @@ namespace find_all_symbols {
 
 SymbolInfo::SymbolInfo(llvm::StringRef Name, SymbolKind Type,
                        llvm::StringRef FilePath, int LineNumber,
-                       const std::vector<Context> &Contexts,
-                       unsigned NumOccurrences)
+                       const std::vector<Context> &Contexts)
     : Name(Name), Type(Type), FilePath(FilePath), Contexts(Contexts),
-      LineNumber(LineNumber), NumOccurrences(NumOccurrences) {}
+      LineNumber(LineNumber) {}
 
 bool SymbolInfo::operator==(const SymbolInfo &Symbol) const {
   return std::tie(Name, Type, FilePath, LineNumber, Contexts) ==
@@ -100,16 +101,30 @@ std::string SymbolInfo::getQualifiedName
   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 WriteSymbolInfosToStream(llvm::raw_ostream &OS,
-                              const std::set<SymbolInfo> &Symbols) {
+                              const SymbolInfo::SignalMap &Symbols) {
   llvm::yaml::Output yout(OS);
-  for (auto Symbol : Symbols)
-    yout << Symbol;
+  for (const auto &Symbol : Symbols) {
+    SymbolAndSignals S{Symbol.first, Symbol.second};
+    yout << S;
+  }
   return true;
 }
 
-std::vector<SymbolInfo> ReadSymbolInfosFromYAML(llvm::StringRef Yaml) {
-  std::vector<SymbolInfo> Symbols;
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml) {
+  std::vector<SymbolAndSignals> Symbols;
   llvm::yaml::Input yin(Yaml);
   yin >> Symbols;
   return Symbols;

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h Tue Feb 28 02:13:15 2017
@@ -20,7 +20,6 @@
 
 namespace clang {
 namespace find_all_symbols {
-
 /// \brief Contains all information for a Symbol.
 class SymbolInfo {
 public:
@@ -46,13 +45,30 @@ public:
   /// \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;
+  };
+
+  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), LineNumber(-1) {}
 
   SymbolInfo(llvm::StringRef Name, SymbolKind Type, llvm::StringRef FilePath,
-             int LineNumber, const std::vector<Context> &Contexts,
-             unsigned NumOccurrences = 0);
+             int LineNumber, const std::vector<Context> &Contexts);
 
   void SetFilePath(llvm::StringRef Path) { FilePath = Path; }
 
@@ -76,15 +92,12 @@ public:
   /// \brief Get a 1-based line number of the symbol's declaration.
   int getLineNumber() const { return LineNumber; }
 
-  /// \brief The number of times this symbol was found during an indexing run.
-  unsigned getNumOccurrences() const { return NumOccurrences; }
-
   bool operator<(const SymbolInfo &Symbol) const;
 
   bool operator==(const SymbolInfo &Symbol) const;
 
 private:
-  friend struct llvm::yaml::MappingTraits<SymbolInfo>;
+  friend struct llvm::yaml::MappingTraits<struct SymbolAndSignals>;
 
   /// \brief Identifier name.
   std::string Name;
@@ -110,18 +123,19 @@ private:
 
   /// \brief The 1-based line number of of the symbol's declaration.
   int LineNumber;
+};
 
-  /// \brief The number of times this symbol was found during an indexing
-  /// run. Populated by the reducer and used to rank results.
-  unsigned NumOccurrences;
+struct SymbolAndSignals {
+  SymbolInfo Symbol;
+  SymbolInfo::Signals Signals;
 };
 
 /// \brief Write SymbolInfos to a stream (YAML format).
 bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
-                              const std::set<SymbolInfo> &Symbols);
+                              const SymbolInfo::SignalMap &Symbols);
 
 /// \brief Read SymbolInfos from a YAML document.
-std::vector<SymbolInfo> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);
+std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);
 
 } // namespace find_all_symbols
 } // namespace clang

Modified: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h Tue Feb 28 02:13:15 2017
@@ -20,8 +20,8 @@ class SymbolReporter {
 public:
   virtual ~SymbolReporter() = default;
 
-  virtual void reportSymbol(llvm::StringRef FileName,
-                            const SymbolInfo &Symbol) = 0;
+  virtual void reportSymbols(llvm::StringRef FileName,
+                             const SymbolInfo::SignalMap &Symbols) = 0;
 };
 
 } // namespace find_all_symbols

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp Tue Feb 28 02:13:15 2017
@@ -62,38 +62,30 @@ The directory for merging symbols.)"),
 namespace clang {
 namespace find_all_symbols {
 
-class YamlReporter : public clang::find_all_symbols::SymbolReporter {
+class YamlReporter : public SymbolReporter {
 public:
-  ~YamlReporter() override {
-    for (const auto &Symbol : Symbols) {
-      int FD;
-      SmallString<128> ResultPath;
-      llvm::sys::fs::createUniqueFile(
-          OutputDir + "/" + llvm::sys::path::filename(Symbol.first) +
-              "-%%%%%%.yaml",
-          FD, ResultPath);
-      llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
-      WriteSymbolInfosToStream(OS, Symbol.second);
-    }
-  }
-
-  void reportSymbol(StringRef FileName, const SymbolInfo &Symbol) override {
-    Symbols[FileName].insert(Symbol);
+  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);
   }
-
-private:
-  std::map<std::string, std::set<SymbolInfo>> Symbols;
 };
 
 bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
   std::error_code EC;
-  std::map<SymbolInfo, int> SymbolToNumOccurrences;
+  SymbolInfo::SignalMap Symbols;
   std::mutex SymbolMutex;
-  auto AddSymbols = [&](ArrayRef<SymbolInfo> Symbols) {
+  auto AddSymbols = [&](ArrayRef<SymbolAndSignals> NewSymbols) {
     // Synchronize set accesses.
     std::unique_lock<std::mutex> LockGuard(SymbolMutex);
-    for (const auto &Symbol : Symbols)
-      ++SymbolToNumOccurrences[Symbol];
+    for (const auto &Symbol : NewSymbols) {
+      Symbols[Symbol.Symbol] += Symbol.Signals;
+    }
   };
 
   // Load all symbol files in MergeDir.
@@ -109,8 +101,13 @@ bool Merge(llvm::StringRef MergeDir, llv
               llvm::errs() << "Can't open " << Path << "\n";
               return;
             }
-            std::vector<SymbolInfo> Symbols =
+            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);
           },
@@ -124,14 +121,7 @@ bool Merge(llvm::StringRef MergeDir, llv
                  << '\n';
     return false;
   }
-  std::set<SymbolInfo> Result;
-  for (const auto &Entry : SymbolToNumOccurrences) {
-    const auto &Symbol = Entry.first;
-    Result.insert(SymbolInfo(Symbol.getName(), Symbol.getSymbolKind(),
-                             Symbol.getFilePath(), Symbol.getLineNumber(),
-                             Symbol.getContexts(), Entry.second));
-  }
-  WriteSymbolInfosToStream(OS, Result);
+  WriteSymbolInfosToStream(OS, Symbols);
   return true;
 }
 

Modified: clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp (original)
+++ clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp Tue Feb 28 02:13:15 2017
@@ -158,6 +158,8 @@ cl::opt<std::string>
 
 std::unique_ptr<include_fixer::SymbolIndexManager>
 createSymbolIndexManager(StringRef FilePath) {
+  using find_all_symbols::SymbolInfo;
+
   auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
   switch (DatabaseFormat) {
   case fixed: {
@@ -167,17 +169,19 @@ createSymbolIndexManager(StringRef FileP
     std::map<std::string, std::vector<std::string>> SymbolsMap;
     SmallVector<StringRef, 4> SemicolonSplits;
     StringRef(Input).split(SemicolonSplits, ";");
-    std::vector<find_all_symbols::SymbolInfo> Symbols;
+    std::vector<find_all_symbols::SymbolAndSignals> Symbols;
     for (StringRef Pair : SemicolonSplits) {
       auto Split = Pair.split('=');
       std::vector<std::string> Headers;
       SmallVector<StringRef, 4> CommaSplits;
       Split.second.split(CommaSplits, ",");
       for (size_t I = 0, E = CommaSplits.size(); I != E; ++I)
-        Symbols.push_back(find_all_symbols::SymbolInfo(
-            Split.first.trim(),
-            find_all_symbols::SymbolInfo::SymbolKind::Unknown,
-            CommaSplits[I].trim(), 1, {}, /*NumOccurrences=*/E - I));
+        Symbols.push_back(
+            {SymbolInfo(Split.first.trim(), SymbolInfo::SymbolKind::Unknown,
+                        CommaSplits[I].trim(), 1, {}),
+             // Use fake "seen" signal for tests, so first header wins.
+             SymbolInfo::Signals(/*Seen=*/static_cast<unsigned>(E - I),
+                                 /*Used=*/0)});
     }
     SymbolIndexMgr->addSymbolIndex([=]() {
       return llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols);

Modified: clang-tools-extra/trunk/test/include-fixer/Inputs/fake_yaml_db.yaml
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/include-fixer/Inputs/fake_yaml_db.yaml?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/include-fixer/Inputs/fake_yaml_db.yaml (original)
+++ clang-tools-extra/trunk/test/include-fixer/Inputs/fake_yaml_db.yaml Tue Feb 28 02:13:15 2017
@@ -8,7 +8,8 @@ Contexts:
 FilePath:        foo.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            0
 ---
 Name:           bar
 Contexts:
@@ -19,7 +20,8 @@ Contexts:
 FilePath:        ../include/bar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            0
 ---
 Name:           bar
 Contexts:
@@ -30,7 +32,8 @@ Contexts:
 FilePath:        ../include/bar.h
 LineNumber:      2
 Type:            Class
-NumOccurrences:  3
+Seen:            3
+Used:            0
 ---
 Name:           bar
 Contexts:
@@ -41,14 +44,16 @@ Contexts:
 FilePath:        ../include/zbar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  3
+Seen:            3
+Used:            0
 ---
 Name:           b
 Contexts:
 FilePath:        var.h
 LineNumber:      1
 Type:            Variable
-NumOccurrences:  1
+Seen:            1
+Used:            0
 ---
 Name:            bar
 Contexts:
@@ -57,4 +62,5 @@ Contexts:
 FilePath:        test/include-fixer/baz.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            0

Modified: clang-tools-extra/trunk/test/include-fixer/Inputs/merge/a.yaml
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/include-fixer/Inputs/merge/a.yaml?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/include-fixer/Inputs/merge/a.yaml (original)
+++ clang-tools-extra/trunk/test/include-fixer/Inputs/merge/a.yaml Tue Feb 28 02:13:15 2017
@@ -6,7 +6,8 @@ Contexts:
 FilePath:        foo.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            1
 ...
 ---
 Name:           bar
@@ -16,5 +17,6 @@ Contexts:
 FilePath:        ../include/bar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            2
 ...

Modified: clang-tools-extra/trunk/test/include-fixer/Inputs/merge/b.yaml
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/include-fixer/Inputs/merge/b.yaml?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/include-fixer/Inputs/merge/b.yaml (original)
+++ clang-tools-extra/trunk/test/include-fixer/Inputs/merge/b.yaml Tue Feb 28 02:13:15 2017
@@ -6,7 +6,8 @@ Contexts:
 FilePath:        foo.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            2
 ...
 ---
 Name:           bar
@@ -16,5 +17,6 @@ Contexts:
 FilePath:        ../include/barbar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            0
 ...

Modified: clang-tools-extra/trunk/test/include-fixer/merge.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/include-fixer/merge.test?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/include-fixer/merge.test (original)
+++ clang-tools-extra/trunk/test/include-fixer/merge.test Tue Feb 28 02:13:15 2017
@@ -9,7 +9,8 @@ Contexts:
 FilePath:        ../include/bar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            1
 ...
 ---
 Name:            bar
@@ -19,7 +20,8 @@ Contexts:
 FilePath:        ../include/barbar.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  1
+Seen:            1
+Used:            0
 ...
 ---
 Name:            foo
@@ -29,5 +31,6 @@ Contexts:
 FilePath:        foo.h
 LineNumber:      1
 Type:            Class
-NumOccurrences:  2
+Seen:            2
+Used:            2
 ...

Modified: clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp?rev=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp Tue Feb 28 02:13:15 2017
@@ -19,6 +19,7 @@ namespace include_fixer {
 namespace {
 
 using find_all_symbols::SymbolInfo;
+using find_all_symbols::SymbolAndSignals;
 
 static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
                       StringRef FileName,
@@ -52,42 +53,49 @@ static bool runOnCode(tooling::ToolActio
 static std::string runIncludeFixer(
     StringRef Code,
     const std::vector<std::string> &ExtraArgs = std::vector<std::string>()) {
-  std::vector<SymbolInfo> Symbols = {
-      SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>", 1,
-                 {{SymbolInfo::ContextType::Namespace, "std"}}),
-      SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"", 1,
-                 {{SymbolInfo::ContextType::Namespace, "std"}}),
-      SymbolInfo("foo", SymbolInfo::SymbolKind::Class, "\"dir/otherdir/qux.h\"",
-                 1, {{SymbolInfo::ContextType::Namespace, "b"},
-                     {SymbolInfo::ContextType::Namespace, "a"}}),
-      SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"", 1,
-                 {{SymbolInfo::ContextType::Namespace, "b"},
-                  {SymbolInfo::ContextType::Namespace, "a"}}),
-      SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"", 1,
-                 {{SymbolInfo::ContextType::Namespace, "c"},
-                  {SymbolInfo::ContextType::Namespace, "a"}}),
-      SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"", 1,
-                 {{SymbolInfo::ContextType::EnumDecl, "Color"},
-                  {SymbolInfo::ContextType::Namespace, "b"},
-                  {SymbolInfo::ContextType::Namespace, "a"}}),
-      SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 1,
-                 {{SymbolInfo::ContextType::Namespace, "__a"},
-                  {SymbolInfo::ContextType::Namespace, "a"}},
-                 /*num_occurrences=*/2),
-      SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 2,
-                 {{SymbolInfo::ContextType::Namespace, "a"}},
-                 /*num_occurrences=*/1),
-      SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"",
-                 1, {{SymbolInfo::ContextType::Namespace, "str"}}),
-      SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"",
-                 1, {}),
-      SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"",
-                 1, {}),
+  std::vector<SymbolAndSignals> Symbols = {
+      {SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>", 1,
+                  {{SymbolInfo::ContextType::Namespace, "std"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "std"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("foo", SymbolInfo::SymbolKind::Class,
+                  "\"dir/otherdir/qux.h\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "c"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"", 1,
+                  {{SymbolInfo::ContextType::EnumDecl, "Color"},
+                   {SymbolInfo::ContextType::Namespace, "b"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "__a"},
+                   {SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{/*Seen=*/2, 0}},
+      {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 2,
+                  {{SymbolInfo::ContextType::Namespace, "a"}}),
+       SymbolInfo::Signals{/*Seen=*/2, 0}},
+      {SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"", 1,
+                  {{SymbolInfo::ContextType::Namespace, "str"}}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"", 1, {}),
+       SymbolInfo::Signals{}},
+      {SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"", 1, {}),
+       SymbolInfo::Signals{}},
   };
-  auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
-  SymbolIndexMgr->addSymbolIndex([=]() {
-    return llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols);
-  });
+  auto SymbolIndexMgr = llvm::make_unique<SymbolIndexManager>();
+  SymbolIndexMgr->addSymbolIndex(
+      [=]() { return llvm::make_unique<InMemorySymbolIndex>(Symbols); });
 
   std::vector<IncludeFixerContext> FixerContexts;
   IncludeFixerActionFactory Factory(*SymbolIndexMgr, FixerContexts, "llvm");
@@ -96,15 +104,14 @@ static std::string runIncludeFixer(
   assert(FixerContexts.size() == 1);
   if (FixerContexts.front().getHeaderInfos().empty())
     return Code;
-  auto Replaces = clang::include_fixer::createIncludeFixerReplacements(
-      Code, FixerContexts.front());
+  auto Replaces = createIncludeFixerReplacements(Code, FixerContexts.front());
   EXPECT_TRUE(static_cast<bool>(Replaces))
       << llvm::toString(Replaces.takeError()) << "\n";
   if (!Replaces)
     return "";
-  clang::RewriterTestContext Context;
-  clang::FileID ID = Context.createInMemoryFile(FakeFileName, Code);
-  clang::tooling::applyAllReplacements(*Replaces, Context.Rewrite);
+  RewriterTestContext Context;
+  FileID ID = Context.createInMemoryFile(FakeFileName, Code);
+  tooling::applyAllReplacements(*Replaces, Context.Rewrite);
   return Context.getRewrittenText(ID);
 }
 

Modified: 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=296446&r1=296445&r2=296446&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp Tue Feb 28 02:13:15 2017
@@ -19,6 +19,7 @@
 #include "clang/Frontend/PCHContainerOperations.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "gtest/gtest.h"
@@ -31,25 +32,28 @@ namespace find_all_symbols {
 
 static const char HeaderName[] = "symbols.h";
 
-class TestSymbolReporter : public clang::find_all_symbols::SymbolReporter {
+class TestSymbolReporter : public SymbolReporter {
 public:
   ~TestSymbolReporter() override {}
 
-  void reportSymbol(llvm::StringRef FileName,
-                    const SymbolInfo &Symbol) override {
-    Symbols.push_back(Symbol);
+  void reportSymbols(llvm::StringRef FileName,
+                     const SymbolInfo::SignalMap &NewSymbols) override {
+    for (const auto &Entry : NewSymbols)
+      Symbols[Entry.first] += Entry.second;
   }
 
   bool hasSymbol(const SymbolInfo &Symbol) const {
-    for (const auto &S : Symbols) {
-      if (S == Symbol)
-        return true;
-    }
-    return false;
+    auto it = Symbols.find(Symbol);
+    return it != Symbols.end() && it->second.Seen > 0;
+  }
+
+  bool hasUse(const SymbolInfo &Symbol) const {
+    auto it = Symbols.find(Symbol);
+    return it != Symbols.end() && it->second.Used > 0;
   }
 
 private:
-  std::vector<SymbolInfo> Symbols;
+  SymbolInfo::SignalMap Symbols;
 };
 
 class FindAllSymbolsTest : public ::testing::Test {
@@ -58,7 +62,9 @@ public:
     return Reporter.hasSymbol(Symbol);
   }
 
-  bool runFindAllSymbols(StringRef Code) {
+  bool hasUse(const SymbolInfo &Symbol) { return Reporter.hasUse(Symbol); }
+
+  bool runFindAllSymbols(StringRef HeaderCode, StringRef MainCode) {
     llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
         new vfs::InMemoryFileSystem);
     llvm::IntrusiveRefCntPtr<FileManager> Files(
@@ -88,7 +94,7 @@ public:
     InMemoryFileSystem->addFile(InternalHeader, 0,
                                 llvm::MemoryBuffer::getMemBuffer(InternalCode));
 
-    std::unique_ptr<clang::tooling::FrontendActionFactory> Factory(
+    std::unique_ptr<tooling::FrontendActionFactory> Factory(
         new FindAllSymbolsActionFactory(&Reporter, &RegexMap));
 
     tooling::ToolInvocation Invocation(
@@ -98,7 +104,7 @@ public:
         std::make_shared<PCHContainerOperations>());
 
     InMemoryFileSystem->addFile(HeaderName, 0,
-                                llvm::MemoryBuffer::getMemBuffer(Code));
+                                llvm::MemoryBuffer::getMemBuffer(HeaderCode));
 
     std::string Content = "#include\"" + std::string(HeaderName) +
                           "\"\n"
@@ -118,6 +124,7 @@ public:
     SymbolInfo DirtySymbol("ExtraInternal", SymbolInfo::SymbolKind::Class,
                            CleanHeader, 2, {});
 #endif // _MSC_VER && __MINGW32__
+    Content += "\n" + MainCode.str();
     InMemoryFileSystem->addFile(FileName, 0,
                                 llvm::MemoryBuffer::getMemBuffer(Content));
     Invocation.run();
@@ -135,49 +142,64 @@ protected:
 };
 
 TEST_F(FindAllSymbolsTest, VariableSymbols) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       extern int xargc;
       namespace na {
       static bool SSSS = false;
       namespace nb { const long long *XXXX; }
       })";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      auto y = &na::nb::XXXX;
+      int main() { if (na::SSSS) return xargc; }
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("xargc", SymbolInfo::SymbolKind::Variable, HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("SSSS", SymbolInfo::SymbolKind::Variable, HeaderName, 4,
                       {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("XXXX", SymbolInfo::SymbolKind::Variable, HeaderName, 5,
                       {{SymbolInfo::ContextType::Namespace, "nb"},
                        {SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, ExternCSymbols) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       extern "C" {
       int C_Func() { return 0; }
       struct C_struct {
         int Member;
       };
       })";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      C_struct q() {
+        int(*ptr)() = C_Func;
+        return {0};
+      }
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("C_Func", SymbolInfo::SymbolKind::Function, HeaderName, 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol =
       SymbolInfo("C_struct", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, CXXRecordSymbols) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       struct Glob {};
       struct A; // Not a defintion, ignored.
       class NOP; // Not a defintion, ignored
@@ -190,26 +212,33 @@ TEST_F(FindAllSymbolsTest, CXXRecordSymb
       };
       };  //
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      static Glob glob;
+      static na::A::AAAA* a;
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("Glob", SymbolInfo::SymbolKind::Class, HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("A", SymbolInfo::SymbolKind::Class, HeaderName, 6,
                       {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("AAA", SymbolInfo::SymbolKind::Class, HeaderName, 7,
                       {{SymbolInfo::ContextType::Record, "A"},
                        {SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_FALSE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, CXXRecordSymbolsTemplate) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       template <typename T>
-      class T_TEMP {
+      struct T_TEMP {
         template <typename _Tp1>
         struct rebind { typedef T_TEMP<_Tp1> other; };
       };
@@ -222,11 +251,15 @@ TEST_F(FindAllSymbolsTest, CXXRecordSymb
       // Ignore specialization.
       template <> class Observer<int> {};
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      extern T_TEMP<int>::rebind<char> weirdo;
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("T_TEMP", SymbolInfo::SymbolKind::Class, HeaderName, 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
@@ -239,7 +272,7 @@ TEST_F(FindAllSymbolsTest, DontIgnoreTem
       template<class T> void f() {};
       template<> void f<int>() {};
       )";
-  runFindAllSymbols(Code);
+  runFindAllSymbols(Code, "");
   SymbolInfo Symbol =
       SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
   EXPECT_TRUE(hasSymbol(Symbol));
@@ -252,7 +285,7 @@ TEST_F(FindAllSymbolsTest, DontIgnoreTem
 }
 
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       namespace na {
       int gg(int);
       int f(const int &a) { int Local; static int StaticLocal; return 0; }
@@ -265,91 +298,127 @@ TEST_F(FindAllSymbolsTest, FunctionSymbo
       } // namespace nb
       } // namespace na";
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      int(*gg)(int) = &na::gg;
+      int main() {
+        (void)na::SSSFFF;
+        na::nb::fun(0);
+        return na::f(gg(0));
+      }
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("gg", SymbolInfo::SymbolKind::Function, HeaderName, 3,
                  {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 4,
                       {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("SSSFFF", SymbolInfo::SymbolKind::Function, HeaderName, 5,
                       {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("fun", SymbolInfo::SymbolKind::Function, HeaderName, 10,
                       {{SymbolInfo::ContextType::Namespace, "nb"},
                        {SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, NamespaceTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       int X1;
       namespace { int X2; }
       namespace { namespace { int X3; } }
       namespace { namespace nb { int X4; } }
       namespace na { inline namespace __1 { int X5; } }
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      using namespace nb;
+      int main() {
+        X1 = X2;
+        X3 = X4;
+        (void)na::X5;
+      }
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("X1", SymbolInfo::SymbolKind::Variable, HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("X2", SymbolInfo::SymbolKind::Variable, HeaderName, 3,
                       {{SymbolInfo::ContextType::Namespace, ""}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("X3", SymbolInfo::SymbolKind::Variable, HeaderName, 4,
                       {{SymbolInfo::ContextType::Namespace, ""},
                        {SymbolInfo::ContextType::Namespace, ""}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("X4", SymbolInfo::SymbolKind::Variable, HeaderName, 5,
                       {{SymbolInfo::ContextType::Namespace, "nb"},
                        {SymbolInfo::ContextType::Namespace, ""}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("X5", SymbolInfo::SymbolKind::Variable, HeaderName, 6,
                       {{SymbolInfo::ContextType::Namespace, "na"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, DecayedTypeTest) {
-  static const char Code[] = "void DecayedFunc(int x[], int y[10]) {}";
-  runFindAllSymbols(Code);
+  static const char Header[] = "void DecayedFunc(int x[], int y[10]) {}";
+  static const char Main[] = R"(int main() { DecayedFunc(nullptr, nullptr); })";
+  runFindAllSymbols(Header, Main);
   SymbolInfo Symbol = SymbolInfo(
       "DecayedFunc", SymbolInfo::SymbolKind::Function, HeaderName, 1, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, CTypedefTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       typedef unsigned size_t_;
       typedef struct { int x; } X;
       using XX = X;
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      size_t_ f;
+      template<typename T> struct vector{};
+      vector<X> list;
+      void foo(const XX&){}
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol = SymbolInfo("size_t_", SymbolInfo::SymbolKind::TypedefName,
                                  HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol =
       SymbolInfo("X", SymbolInfo::SymbolKind::TypedefName, HeaderName, 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol =
       SymbolInfo("XX", SymbolInfo::SymbolKind::TypedefName, HeaderName, 4, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, EnumTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
       enum Glob_E { G1, G2 };
       enum class Altitude { high='h', low='l'};
       enum { A1, A2 };
@@ -359,42 +428,58 @@ TEST_F(FindAllSymbolsTest, EnumTest) {
       };
       enum DECL : int;
       )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+      static auto flags = G1 | G2;
+      static auto alt = Altitude::high;
+      static auto nested = A::X1;
+      extern DECL whatever;
+      static auto flags2 = A1 | A2;
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("Glob_E", SymbolInfo::SymbolKind::EnumDecl, HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));
 
   Symbol =
       SymbolInfo("G1", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName, 2,
                  {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol =
       SymbolInfo("G2", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName, 2,
                  {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("Altitude", SymbolInfo::SymbolKind::EnumDecl, HeaderName,
                       3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
   Symbol =
       SymbolInfo("high", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
                  3, {{SymbolInfo::ContextType::EnumDecl, "Altitude"}});
   EXPECT_FALSE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));
 
   Symbol = SymbolInfo("A1", SymbolInfo::SymbolKind::EnumConstantDecl,
                       HeaderName, 4, {{SymbolInfo::ContextType::EnumDecl, ""}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
   Symbol = SymbolInfo("A2", SymbolInfo::SymbolKind::EnumConstantDecl,
                       HeaderName, 4, {{SymbolInfo::ContextType::EnumDecl, ""}});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
   Symbol = SymbolInfo("", SymbolInfo::SymbolKind::EnumDecl, HeaderName, 4, {});
   EXPECT_FALSE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));
 
   Symbol = SymbolInfo("A_ENUM", SymbolInfo::SymbolKind::EnumDecl, HeaderName, 7,
                       {{SymbolInfo::ContextType::Record, "A"}});
   EXPECT_FALSE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));
 
   Symbol = SymbolInfo("X1", SymbolInfo::SymbolKind::EnumDecl, HeaderName, 7,
                       {{SymbolInfo::ContextType::EnumDecl, "A_ENUM"},
@@ -407,63 +492,83 @@ TEST_F(FindAllSymbolsTest, EnumTest) {
 }
 
 TEST_F(FindAllSymbolsTest, IWYUPrivatePragmaTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
     // IWYU pragma: private, include "bar.h"
     struct Bar {
     };
   )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+    Bar bar;
+  )";
+  runFindAllSymbols(Header, Main);
 
   SymbolInfo Symbol =
       SymbolInfo("Bar", SymbolInfo::SymbolKind::Class, "bar.h", 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, MacroTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
     #define X
     #define Y 1
     #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
   )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+    #ifdef X
+    int main() { return MAX(0,Y); }
+    #endif
+  )";
+  runFindAllSymbols(Header, Main);
   SymbolInfo Symbol =
       SymbolInfo("X", SymbolInfo::SymbolKind::Macro, HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, HeaderName, 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, HeaderName, 4, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, MacroTestWithIWYU) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
     // IWYU pragma: private, include "bar.h"
-    #define X
+    #define X 1
     #define Y 1
     #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
   )";
-  runFindAllSymbols(Code);
+  static const char Main[] = R"(
+    #ifdef X
+    int main() { return MAX(0,Y); }
+    #endif
+  )";
+  runFindAllSymbols(Header, Main);
   SymbolInfo Symbol =
       SymbolInfo("X", SymbolInfo::SymbolKind::Macro, "bar.h", 3, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, "bar.h", 4, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 
   Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, "bar.h", 5, {});
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_TRUE(hasUse(Symbol));
 }
 
 TEST_F(FindAllSymbolsTest, NoFriendTest) {
-  static const char Code[] = R"(
+  static const char Header[] = R"(
     class WorstFriend {
       friend void Friend();
       friend class BestFriend;
     };
   )";
-  runFindAllSymbols(Code);
+  runFindAllSymbols(Header, "");
   SymbolInfo Symbol = SymbolInfo("WorstFriend", SymbolInfo::SymbolKind::Class,
                                  HeaderName, 2, {});
   EXPECT_TRUE(hasSymbol(Symbol));




More information about the cfe-commits mailing list