diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h index a03b30e87d1aba..e33693c59566d3 100644 --- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h +++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h @@ -26,6 +26,9 @@ #include #include +namespace llvm { +class raw_ostream; +} // namespace llvm namespace clang { class Decl; class FileEntry; @@ -33,28 +36,58 @@ namespace include_cleaner { /// An entity that can be referenced in the code. struct Symbol { - Symbol(Decl &D) : Storage(&D) {} + enum Kind { + /// A canonical clang declaration. + Declaration, + /// A recognized symbol from the standard library, like std::string. + Standard, + }; + + Symbol(const Decl &D) : Storage(&D) {} Symbol(tooling::stdlib::Symbol S) : Storage(S) {} + Kind kind() const { return static_cast(Storage.index()); } + bool operator==(const Symbol &RHS) const { return Storage == RHS.Storage; } + + tooling::stdlib::Symbol standard() const { + return std::get(Storage); + } + const Decl &declaration() const { return *std::get(Storage); } + private: // FIXME: Add support for macros. + // Order must match Kind enum! std::variant Storage; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &); /// Represents a file that provides some symbol. Might not be includeable, e.g. /// built-in or main-file itself. struct Header { - /// A physical (or logical, in case of a builtin) file. + enum Kind { + /// A source file parsed by clang. (May also be a buffer). + Physical, + /// A recognized standard library header, like . + Standard, + }; + Header(const FileEntry *FE) : Storage(FE) {} - /// A logical file representing a stdlib header. Header(tooling::stdlib::Header H) : Storage(H) {} + Kind kind() const { return static_cast(Storage.index()); } bool operator==(const Header &RHS) const { return Storage == RHS.Storage; } + const FileEntry *physical() const { return std::get(Storage); } + tooling::stdlib::Header standard() const { + return std::get(Storage); + } + private: // FIXME: Handle verbatim spellings. + // Order must match Kind enum! std::variant Storage; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Header &); } // namespace include_cleaner } // namespace clang diff --git a/clang-tools-extra/include-cleaner/lib/CMakeLists.txt b/clang-tools-extra/include-cleaner/lib/CMakeLists.txt index 759261e90499a8..62c61f44a0faa9 100644 --- a/clang-tools-extra/include-cleaner/lib/CMakeLists.txt +++ b/clang-tools-extra/include-cleaner/lib/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(clangIncludeCleaner Analysis.cpp HTMLReport.cpp Record.cpp + Types.cpp WalkAST.cpp LINK_LIBS diff --git a/clang-tools-extra/include-cleaner/lib/Types.cpp b/clang-tools-extra/include-cleaner/lib/Types.cpp new file mode 100644 index 00000000000000..1b673ab7bfdee6 --- /dev/null +++ b/clang-tools-extra/include-cleaner/lib/Types.cpp @@ -0,0 +1,38 @@ +//===--- Types.cpp --------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang-include-cleaner/Types.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/FileEntry.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang::include_cleaner { + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) { + switch (S.kind()) { + case Symbol::Declaration: + if (const auto *ND = llvm::dyn_cast(&S.declaration())) + return OS << ND->getNameAsString(); + return OS << S.declaration().getDeclKindName(); + case Symbol::Standard: + return OS << S.standard().scope() << S.standard().name(); + } + llvm_unreachable("Unhandled Symbol kind"); +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Header &H) { + switch (H.kind()) { + case Header::Physical: + return OS << H.physical()->getName(); + case Header::Standard: + return OS << H.standard().name(); + } + llvm_unreachable("Unhandled Header kind"); +} + +} // namespace clang::include_cleaner