Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(findAllSymbols FindAllSymbols.cpp + FindAllMacros.cpp PragmaCommentHandler.cpp SymbolInfo.cpp Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.h @@ -0,0 +1,48 @@ +//===-- FindAllMacros.h - find all macros -----------------------*- 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_FIND_ALL_MACROS_H +#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H + +#include "SymbolInfo.h" +#include "SymbolReporter.h" +#include "clang/Lex/PPCallbacks.h" + +namespace clang { +namespace find_all_symbols { + +class HeaderMapCollector; + +/// \brief A preprocessor that collects all macro symbols. +/// The contexts of a macro will be ignored since they are not available during +/// preprocessing period. +class FindAllMacros : public clang::PPCallbacks { +public: + explicit FindAllMacros(SymbolReporter *Reporter, + HeaderMapCollector *Collector, SourceManager *SM) + : Reporter(Reporter), Collector(Collector), SM(SM) {} + + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override; + +private: + // Reporter for SymbolInfo. + SymbolReporter *const Reporter; + // A remapping header file collector allowing clients to include a different + // header. + HeaderMapCollector *const Collector; + + SourceManager *const SM; +}; + +} // namespace find_all_symbols +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_FIND_ALL_MACROS_H Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllMacros.cpp @@ -0,0 +1,45 @@ +//===-- FindAllMacros.cpp - find all macros ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "FindAllMacros.h" +#include "HeaderMapCollector.h" +#include "SymbolInfo.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Token.h" + +namespace clang { +namespace find_all_symbols { + +void FindAllMacros::MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) { + SourceLocation Loc = SM->getExpansionLoc(MacroNameTok.getLocation()); + if (Loc.isInvalid() || SM->isInMainFile(Loc)) + return; + + llvm::StringRef FilePath = SM->getFilename(Loc); + if (FilePath.empty()) + return; + + // Check pragma remapping header. + auto HeaderMappingTable = Collector->getHeaderMappingTable(); + auto Iter = HeaderMappingTable.find(FilePath); + if (Iter != HeaderMappingTable.end()) + FilePath = Iter->second; + + SymbolInfo Symbol(MacroNameTok.getIdentifierInfo()->getName(), + SymbolInfo::SymbolKind::Macro, FilePath.str(), + SM->getSpellingLineNumber(Loc), {}); + + Reporter->reportSymbol(SM->getFileEntryForID(SM->getMainFileID())->getName(), + Symbol); +} + +} // namespace find_all_symbols +} // namespace clang Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_MATCHER_H #include "SymbolInfo.h" +#include "SymbolReporter.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include @@ -33,15 +34,7 @@ /// 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, + explicit FindAllSymbols(SymbolReporter *Reporter, HeaderMapCollector *Collector) : Reporter(Reporter), Collector(Collector) {} @@ -52,7 +45,7 @@ private: // Reporter for SymbolInfo. - ResultReporter *const Reporter; + SymbolReporter *const Reporter; // A remapping header file collector allowing clients include a different // header. HeaderMapCollector *const Collector; Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp @@ -1,4 +1,4 @@ -//===-- FindAllSymbols.cpp - find all symbols -----------------------------===// +//===-- FindAllSymbols.cpp - find all symbols--------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -217,7 +217,7 @@ llvm::Optional Symbol = CreateSymbolInfo(ND, *SM, Collector->getHeaderMappingTable()); if (Symbol) - Reporter->reportResult( + Reporter->reportSymbol( SM->getFileEntryForID(SM->getMainFileID())->getName(), *Symbol); } Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.h @@ -1,4 +1,4 @@ -//===-- SymbolInfo.h - find all symbols--------------------------*- C++ -*-===// +//===-- SymbolInfo.h - Symbol Info ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -32,6 +32,7 @@ TypedefName, EnumDecl, EnumConstantDecl, + Macro, Unknown, }; Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolInfo.cpp @@ -1,4 +1,4 @@ -//===-- SymbolInfo.cpp ----------------------------------------------------===// +//===-- SymbolInfo.cpp - Symbol Info ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -52,6 +52,7 @@ io.enumCase(value, "TypedefName", SymbolKind::TypedefName); io.enumCase(value, "EnumDecl", SymbolKind::EnumDecl); io.enumCase(value, "EnumConstantDecl", SymbolKind::EnumConstantDecl); + io.enumCase(value, "Macro", SymbolKind::Macro); io.enumCase(value, "Unknown", SymbolKind::Unknown); } }; Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/SymbolReporter.h @@ -0,0 +1,30 @@ +//===--- SymbolReporter.h - Symbol Reporter ---------------------*- 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_REPORTER_H +#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H + +#include "SymbolInfo.h" + +namespace clang { +namespace find_all_symbols { + +/// \brief An interface for classes that collect symbols. +class SymbolReporter { +public: + virtual ~SymbolReporter() = default; + + virtual void reportSymbol(llvm::StringRef FileName, + const SymbolInfo &Symbol) = 0; +}; + +} // namespace find_all_symbols +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_SYMBOL_REPORTER_H Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp +++ clang-tools-extra/trunk/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp @@ -1,4 +1,4 @@ -//===-- FindAllSymbolsMain.cpp --------------------------------------------===// +//===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "FindAllMacros.h" #include "FindAllSymbols.h" #include "HeaderMapCollector.h" #include "PragmaCommentHandler.h" #include "SymbolInfo.h" +#include "SymbolReporter.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Frontend/CompilerInstance.h" @@ -63,12 +65,11 @@ namespace clang { namespace find_all_symbols { -class YamlReporter - : public clang::find_all_symbols::FindAllSymbols::ResultReporter { +class YamlReporter : public clang::find_all_symbols::SymbolReporter { public: ~YamlReporter() override {} - void reportResult(StringRef FileName, const SymbolInfo &Symbol) override { + void reportSymbol(StringRef FileName, const SymbolInfo &Symbol) override { Symbols[FileName].insert(Symbol); } @@ -88,6 +89,7 @@ std::map> Symbols; }; +// FIXME: Move this out from the main file, make it reusable in unittest. class FindAllSymbolsAction : public clang::ASTFrontendAction { public: FindAllSymbolsAction() @@ -100,6 +102,8 @@ CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef InFile) override { Compiler.getPreprocessor().addCommentHandler(&Handler); + Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique( + &Reporter, &Collector, &Compiler.getSourceManager())); return MatchFinder.newASTConsumer(); } Index: clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp +++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp @@ -1,4 +1,4 @@ -//===-- FindAllSymbolsTests.cpp - find all symbols unit tests -------------===// +//===-- FindAllSymbolsTests.cpp - find all symbols unit tests ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "FindAllMacros.h" #include "FindAllSymbols.h" #include "HeaderMapCollector.h" #include "PragmaCommentHandler.h" #include "SymbolInfo.h" +#include "SymbolReporter.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" @@ -31,17 +33,16 @@ static const char HeaderName[] = "symbols.h"; -class MockReporter - : public clang::find_all_symbols::FindAllSymbols::ResultReporter { +class TestSymbolReporter : public clang::find_all_symbols::SymbolReporter { public: - ~MockReporter() override {} + ~TestSymbolReporter() override {} - void reportResult(llvm::StringRef FileName, + void reportSymbol(llvm::StringRef FileName, const SymbolInfo &Symbol) override { Symbols.push_back(Symbol); } - bool hasSymbol(const SymbolInfo &Symbol) { + bool hasSymbol(const SymbolInfo &Symbol) const { for (const auto &S : Symbols) { if (S == Symbol) return true; @@ -55,8 +56,8 @@ class TestFindAllSymbolsAction : public clang::ASTFrontendAction { public: - TestFindAllSymbolsAction(FindAllSymbols::ResultReporter *Reporter) - : MatchFinder(), Collector(), Handler(&Collector), + TestFindAllSymbolsAction(SymbolReporter *Reporter) + : Reporter(Reporter), MatchFinder(), Collector(), Handler(&Collector), Matcher(Reporter, &Collector) { Matcher.registerMatchers(&MatchFinder); } @@ -65,10 +66,13 @@ CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef InFile) override { Compiler.getPreprocessor().addCommentHandler(&Handler); + Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique( + Reporter, &Collector, &Compiler.getSourceManager())); return MatchFinder.newASTConsumer(); } private: + SymbolReporter *const Reporter; ast_matchers::MatchFinder MatchFinder; HeaderMapCollector Collector; PragmaCommentHandler Handler; @@ -78,14 +82,14 @@ class TestFindAllSymbolsActionFactory : public clang::tooling::FrontendActionFactory { public: - TestFindAllSymbolsActionFactory(MockReporter *Reporter) + TestFindAllSymbolsActionFactory(TestSymbolReporter *Reporter) : Reporter(Reporter) {} clang::FrontendAction *create() override { return new TestFindAllSymbolsAction(Reporter); } private: - MockReporter *const Reporter; + TestSymbolReporter *const Reporter; }; class FindAllSymbolsTest : public ::testing::Test { @@ -122,7 +126,7 @@ } private: - MockReporter Reporter; + TestSymbolReporter Reporter; }; TEST_F(FindAllSymbolsTest, VariableSymbols) { @@ -378,5 +382,42 @@ EXPECT_TRUE(hasSymbol(Symbol)); } +TEST_F(FindAllSymbolsTest, MacroTest) { + static const char Code[] = R"( + #define X + #define Y 1 + #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + )"; + runFindAllSymbols(Code); + SymbolInfo Symbol = + SymbolInfo("X", SymbolInfo::SymbolKind::Macro, HeaderName, 2, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, HeaderName, 3, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, HeaderName, 4, {}); + EXPECT_TRUE(hasSymbol(Symbol)); +} + +TEST_F(FindAllSymbolsTest, MacroTestWithIWYU) { + static const char Code[] = R"( + // IWYU pragma: private, include "bar.h" + #define X + #define Y 1 + #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + )"; + runFindAllSymbols(Code); + SymbolInfo Symbol = + SymbolInfo("X", SymbolInfo::SymbolKind::Macro, "bar.h", 3, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, "bar.h", 4, {}); + EXPECT_TRUE(hasSymbol(Symbol)); + + Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, "bar.h", 5, {}); + EXPECT_TRUE(hasSymbol(Symbol)); +} + } // namespace find_all_symbols } // namespace clang