diff --git a/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt b/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt index 730118eb7415cb2cbc70f26c4fa735c627780a8e..94f3b47a095e1af745b1681806f2c60584992caf 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt +++ b/clang-tools-extra/include-fixer/find-all-symbols/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS add_clang_library(findAllSymbols FindAllSymbols.cpp + FindAllMacros.cpp PragmaCommentHandler.cpp SymbolInfo.cpp diff --git a/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.cpp b/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c02765afcd5fa01c897ea3687172bdaa4e5671a --- /dev/null +++ b/clang-tools-extra/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 diff --git a/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.h b/clang-tools-extra/include-fixer/find-all-symbols/FindAllMacros.h new file mode 100644 index 0000000000000000000000000000000000000000..167ea10e552f906baa60fa1241f068519ead88cb --- /dev/null +++ b/clang-tools-extra/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 diff --git a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp index 5bf8309ab2cd49ff4f3e530958f797cb670920dc..927a5fbd8a39a03a53866ac45cb1995154c57ebd 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.cpp +++ b/clang-tools-extra/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 @@ void FindAllSymbols::run(const MatchFinder::MatchResult &Result) { llvm::Optional Symbol = CreateSymbolInfo(ND, *SM, Collector->getHeaderMappingTable()); if (Symbol) - Reporter->reportResult( + Reporter->reportSymbol( SM->getFileEntryForID(SM->getMainFileID())->getName(), *Symbol); } diff --git a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h b/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h index 80d68c0e7033b7456a0dc02dc6424ccff3d4379d..687f7d135959b8aaae3b1ee6f3a21a37ff571a4a 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/FindAllSymbols.h +++ b/clang-tools-extra/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 HeaderMapCollector; /// 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 @@ public: private: // Reporter for SymbolInfo. - ResultReporter *const Reporter; + SymbolReporter *const Reporter; // A remapping header file collector allowing clients include a different // header. HeaderMapCollector *const Collector; diff --git a/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp b/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp index 1313d311c2c4e31346fb6046057308169de83d0b..dfe624a82a7137d2e33aff07aac5434c235dc9d9 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.cpp +++ b/clang-tools-extra/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 @@ template <> struct ScalarEnumerationTraits { 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); } }; diff --git a/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h b/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h index c5ee94045fba6e8a796ce16b0241bbd672d08a91..34d9e104ff4a7af8698242c3743d36026efd5817 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/SymbolInfo.h +++ b/clang-tools-extra/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 @@ public: TypedefName, EnumDecl, EnumConstantDecl, + Macro, Unknown, }; diff --git a/clang-tools-extra/include-fixer/find-all-symbols/SymbolReporter.h b/clang-tools-extra/include-fixer/find-all-symbols/SymbolReporter.h new file mode 100644 index 0000000000000000000000000000000000000000..e066326d62aaf21bbfc78e7d85b7b7364a22e559 --- /dev/null +++ b/clang-tools-extra/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 diff --git a/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp index 5e968f7d555573973da6cf0fa08ef4473f57d050..f15e030dcce2aafc11b22988a8bd96ac98f8f8ba 100644 --- a/clang-tools-extra/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp +++ b/clang-tools-extra/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 @@ The directory for merging symbols.)"), 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 @@ private: 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 @@ public: CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef InFile) override { Compiler.getPreprocessor().addCommentHandler(&Handler); + Compiler.getPreprocessor().addPPCallbacks(llvm::make_unique( + &Reporter, &Collector, &Compiler.getSourceManager())); return MatchFinder.newASTConsumer(); } diff --git a/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp b/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp index 251d52351048b8ec0ddd59d6a483b27331278293..0e799c2edabf0ee8bcf19b86bca70a1a8161741e 100644 --- a/clang-tools-extra/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp +++ b/clang-tools-extra/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 @@ namespace find_all_symbols { 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 @@ private: 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 @@ public: 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 @@ private: 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 @@ public: } private: - MockReporter Reporter; + TestSymbolReporter Reporter; }; TEST_F(FindAllSymbolsTest, VariableSymbols) { @@ -378,5 +382,42 @@ TEST_F(FindAllSymbolsTest, IWYUPrivatePragmaTest) { 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