1 | //===--- TypesInternal.h - Intermediate structures used for analysis C++-*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef CLANG_INCLUDE_CLEANER_TYPESINTERNAL_H |
10 | #define CLANG_INCLUDE_CLEANER_TYPESINTERNAL_H |
11 | |
12 | #include "clang/Basic/SourceLocation.h" |
13 | #include "clang/Tooling/Inclusions/StandardLibrary.h" |
14 | #include "llvm/ADT/BitmaskEnum.h" |
15 | #include <cstdint> |
16 | #include <utility> |
17 | #include <variant> |
18 | |
19 | namespace llvm { |
20 | class raw_ostream; |
21 | } |
22 | namespace clang::include_cleaner { |
23 | /// A place where a symbol can be provided. |
24 | /// It is either a physical file of the TU (SourceLocation) or a logical |
25 | /// location in the standard library (stdlib::Symbol). |
26 | struct SymbolLocation { |
27 | enum Kind { |
28 | /// A position within a source file (or macro expansion) parsed by clang. |
29 | Physical, |
30 | /// A recognized standard library symbol, like std::string. |
31 | Standard, |
32 | }; |
33 | |
34 | SymbolLocation(SourceLocation S) : Storage(S) {} |
35 | SymbolLocation(tooling::stdlib::Symbol S) : Storage(S) {} |
36 | |
37 | Kind kind() const { return static_cast<Kind>(Storage.index()); } |
38 | bool operator==(const SymbolLocation &RHS) const { |
39 | return Storage == RHS.Storage; |
40 | } |
41 | SourceLocation physical() const { return std::get<Physical>(v: Storage); } |
42 | tooling::stdlib::Symbol standard() const { |
43 | return std::get<Standard>(v: Storage); |
44 | } |
45 | |
46 | private: |
47 | // Order must match Kind enum! |
48 | std::variant<SourceLocation, tooling::stdlib::Symbol> Storage; |
49 | }; |
50 | llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolLocation &); |
51 | |
52 | /// Represents properties of a symbol provider. |
53 | /// |
54 | /// Hints represents the properties of the edges traversed when finding headers |
55 | /// that satisfy an AST node (AST node => symbols => locations => headers). |
56 | /// |
57 | /// Since there can be multiple paths from an AST node to same header, we need |
58 | /// to merge hints. These hints are merged by taking the union of all the |
59 | /// properties along all the paths. We choose the boolean sense accordingly, |
60 | /// e.g. "Public" rather than "Private", because a header is good if it provides |
61 | /// any public definition, even if it also provides private ones. |
62 | /// |
63 | /// Hints are sorted in ascending order of relevance. |
64 | enum class Hints : uint8_t { |
65 | None = 0x00, |
66 | /// Symbol is directly originating from this header, rather than being |
67 | /// exported or included transitively. |
68 | = 1 << 0, |
69 | /// Header providing the symbol is explicitly marked as preferred, with an |
70 | /// IWYU private pragma that points at this provider or header and symbol has |
71 | /// ~the same name. |
72 | = 1 << 1, |
73 | /// Provides a generally-usable definition for the symbol. (a function decl, |
74 | /// or class definition and not a forward declaration of a template). |
75 | CompleteSymbol = 1 << 2, |
76 | /// Symbol is provided by a public file. Only absent in the cases where file |
77 | /// is explicitly marked as such, non self-contained or IWYU private |
78 | /// pragmas. |
79 | = 1 << 3, |
80 | LLVM_MARK_AS_BITMASK_ENUM(PublicHeader), |
81 | }; |
82 | LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); |
83 | /// A wrapper to augment values with hints. |
84 | template <typename T> struct Hinted : public T { |
85 | Hints Hint; |
86 | Hinted(T &&Wrapped, Hints H) : T(std::move(Wrapped)), Hint(H) {} |
87 | |
88 | /// Since hints are sorted by relevance, use it directly. |
89 | bool operator<(const Hinted<T> &Other) const { |
90 | return static_cast<int>(Hint) < static_cast<int>(Other.Hint); |
91 | } |
92 | |
93 | friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, |
94 | const Hinted<T> &H) { |
95 | return OS << static_cast<int>(H.Hint) << " - " << static_cast<T>(H); |
96 | } |
97 | }; |
98 | |
99 | } // namespace clang::include_cleaner |
100 | |
101 | #endif |
102 | |