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 --- 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,56 @@ /// An entity that can be referenced in the code. struct Symbol { + enum Kind { + // A canonical clang declaration. + Declaration, + // A recognized symbol from the standard library, like std::string. + Standard, + }; + Symbol(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); + } + Decl &declaration() const { return *std::get(Storage); } + private: // FIXME: Add support for macros. - std::variant Storage; + 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. 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 --- a/clang-tools-extra/include-cleaner/lib/CMakeLists.txt +++ b/clang-tools-extra/include-cleaner/lib/CMakeLists.txt @@ -4,6 +4,7 @@ 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 --- /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