1 //===--- Types.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang-include-cleaner/Types.h"
10 #include "TypesInternal.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/Basic/FileEntry.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/Support/raw_ostream.h"
16 namespace clang::include_cleaner
{
18 std::string
Symbol::name() const {
20 case include_cleaner::Symbol::Macro
:
21 return macro().Name
->getName().str();
22 case include_cleaner::Symbol::Declaration
:
23 return llvm::dyn_cast
<NamedDecl
>(&declaration())
24 ->getQualifiedNameAsString();
26 llvm_unreachable("Unknown symbol kind");
29 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Symbol
&S
) {
31 case Symbol::Declaration
:
32 if (const auto *ND
= llvm::dyn_cast
<NamedDecl
>(&S
.declaration()))
33 return OS
<< ND
->getQualifiedNameAsString();
34 return OS
<< S
.declaration().getDeclKindName();
36 return OS
<< S
.macro().Name
->getName();
38 llvm_unreachable("Unhandled Symbol kind");
41 llvm::StringRef
Header::resolvedPath() const {
43 case include_cleaner::Header::Physical
:
44 return physical()->tryGetRealPathName();
45 case include_cleaner::Header::Standard
:
46 return standard().name().trim("<>\"");
47 case include_cleaner::Header::Verbatim
:
48 return verbatim().trim("<>\"");
50 llvm_unreachable("Unknown header kind");
53 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Header
&H
) {
55 case Header::Physical
:
56 return OS
<< H
.physical()->getName();
57 case Header::Standard
:
58 return OS
<< H
.standard().name();
59 case Header::Verbatim
:
60 return OS
<< H
.verbatim();
62 llvm_unreachable("Unhandled Header kind");
65 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Include
&I
) {
66 return OS
<< I
.Line
<< ": " << I
.quote() << " => "
67 << (I
.Resolved
? I
.Resolved
->getName() : "<missing>");
70 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const SymbolReference
&R
) {
71 // We can't decode the Location without SourceManager. Its raw representation
72 // isn't completely useless (and distinguishes SymbolReference from Symbol).
73 return OS
<< R
.RT
<< " reference to " << R
.Target
<< "@0x"
75 R
.RefLocation
.getRawEncoding(), /*LowerCase=*/false,
76 /*Width=*/CHAR_BIT
* sizeof(SourceLocation::UIntTy
));
79 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, RefType T
) {
81 case RefType::Explicit
:
82 return OS
<< "explicit";
83 case RefType::Implicit
:
84 return OS
<< "implicit";
85 case RefType::Ambiguous
:
86 return OS
<< "ambiguous";
88 llvm_unreachable("Unexpected RefType");
91 std::string
Include::quote() const {
92 return (llvm::StringRef(Angled
? "<" : "\"") + Spelled
+
93 (Angled
? ">" : "\""))
97 void Includes::add(const Include
&I
) {
98 unsigned Index
= All
.size();
100 auto BySpellingIt
= BySpelling
.try_emplace(I
.Spelled
).first
;
101 All
.back().Spelled
= BySpellingIt
->first(); // Now we own the backing string.
103 BySpellingIt
->second
.push_back(Index
);
105 ByFile
[I
.Resolved
].push_back(Index
);
106 ByLine
[I
.Line
] = Index
;
109 const Include
*Includes::atLine(unsigned OneBasedIndex
) const {
110 auto It
= ByLine
.find(OneBasedIndex
);
111 return (It
== ByLine
.end()) ? nullptr : &All
[It
->second
];
114 llvm::SmallVector
<const Include
*> Includes::match(Header H
) const {
115 llvm::SmallVector
<const Include
*> Result
;
117 case Header::Physical
:
118 for (unsigned I
: ByFile
.lookup(H
.physical()))
119 Result
.push_back(&All
[I
]);
121 case Header::Standard
:
122 for (unsigned I
: BySpelling
.lookup(H
.standard().name().trim("<>")))
123 Result
.push_back(&All
[I
]);
125 case Header::Verbatim
:
126 for (unsigned I
: BySpelling
.lookup(H
.verbatim().trim("\"<>")))
127 Result
.push_back(&All
[I
]);
133 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const SymbolLocation
&S
) {
135 case SymbolLocation::Physical
:
136 // We can't decode the Location without SourceManager. Its raw
137 // representation isn't completely useless (and distinguishes
138 // SymbolReference from Symbol).
141 S
.physical().getRawEncoding(), /*LowerCase=*/false,
142 /*Width=*/CHAR_BIT
* sizeof(SourceLocation::UIntTy
));
143 case SymbolLocation::Standard
:
144 return OS
<< S
.standard().scope() << S
.standard().name();
146 llvm_unreachable("Unhandled Symbol kind");
149 bool Header::operator<(const Header
&RHS
) const {
150 if (kind() != RHS
.kind())
151 return kind() < RHS
.kind();
153 case Header::Physical
:
154 return physical()->getName() < RHS
.physical()->getName();
155 case Header::Standard
:
156 return standard().name() < RHS
.standard().name();
157 case Header::Verbatim
:
158 return verbatim() < RHS
.verbatim();
160 llvm_unreachable("unhandled Header kind");
162 } // namespace clang::include_cleaner