#include <memory>
#include <vector>
+namespace llvm {
+class raw_ostream;
+} // namespace llvm
namespace clang {
class Decl;
class FileEntry;
/// 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<Kind>(Storage.index()); }
+ bool operator==(const Symbol &RHS) const { return Storage == RHS.Storage; }
+
+ tooling::stdlib::Symbol standard() const {
+ return std::get<Standard>(Storage);
+ }
+ const Decl &declaration() const { return *std::get<Declaration>(Storage); }
+
private:
// FIXME: Add support for macros.
+ // Order must match Kind enum!
std::variant<const Decl *, tooling::stdlib::Symbol> 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 <built-in> buffer).
+ Physical,
+ /// A recognized standard library header, like <string>.
+ 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<Kind>(Storage.index()); }
bool operator==(const Header &RHS) const { return Storage == RHS.Storage; }
+ const FileEntry *physical() const { return std::get<Physical>(Storage); }
+ tooling::stdlib::Header standard() const {
+ return std::get<Standard>(Storage);
+ }
+
private:
// FIXME: Handle verbatim spellings.
+ // Order must match Kind enum!
std::variant<const FileEntry *, tooling::stdlib::Header> Storage;
};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Header &);
} // namespace include_cleaner
} // namespace clang
--- /dev/null
+//===--- 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<NamedDecl>(&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