[mlir][tensor] fix typo in pad tiling comment
[llvm-project.git] / clang-tools-extra / include-cleaner / lib / Types.cpp
blob7a637639edf8b5a139d3dc780e57f49dcf20eeca
1 //===--- Types.cpp --------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
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/STLExtras.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <vector>
22 namespace clang::include_cleaner {
24 std::string Symbol::name() const {
25 switch (kind()) {
26 case include_cleaner::Symbol::Macro:
27 return macro().Name->getName().str();
28 case include_cleaner::Symbol::Declaration:
29 return llvm::dyn_cast<NamedDecl>(&declaration())
30 ->getQualifiedNameAsString();
32 llvm_unreachable("Unknown symbol kind");
35 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
36 switch (S.kind()) {
37 case Symbol::Declaration:
38 if (const auto *ND = llvm::dyn_cast<NamedDecl>(&S.declaration()))
39 return OS << ND->getQualifiedNameAsString();
40 return OS << S.declaration().getDeclKindName();
41 case Symbol::Macro:
42 return OS << S.macro().Name->getName();
44 llvm_unreachable("Unhandled Symbol kind");
47 llvm::StringRef Header::resolvedPath() const {
48 switch (kind()) {
49 case include_cleaner::Header::Physical:
50 return physical().getName();
51 case include_cleaner::Header::Standard:
52 return standard().name().trim("<>\"");
53 case include_cleaner::Header::Verbatim:
54 return verbatim().trim("<>\"");
56 llvm_unreachable("Unknown header kind");
59 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Header &H) {
60 switch (H.kind()) {
61 case Header::Physical:
62 return OS << H.physical().getName();
63 case Header::Standard:
64 return OS << H.standard().name();
65 case Header::Verbatim:
66 return OS << H.verbatim();
68 llvm_unreachable("Unhandled Header kind");
71 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Include &I) {
72 return OS << I.Line << ": " << I.quote() << " => "
73 << (I.Resolved ? I.Resolved->getName() : "<missing>");
76 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolReference &R) {
77 // We can't decode the Location without SourceManager. Its raw representation
78 // isn't completely useless (and distinguishes SymbolReference from Symbol).
79 return OS << R.RT << " reference to " << R.Target << "@0x"
80 << llvm::utohexstr(
81 R.RefLocation.getRawEncoding(), /*LowerCase=*/false,
82 /*Width=*/CHAR_BIT * sizeof(SourceLocation::UIntTy));
85 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefType T) {
86 switch (T) {
87 case RefType::Explicit:
88 return OS << "explicit";
89 case RefType::Implicit:
90 return OS << "implicit";
91 case RefType::Ambiguous:
92 return OS << "ambiguous";
94 llvm_unreachable("Unexpected RefType");
97 std::string Include::quote() const {
98 return (llvm::StringRef(Angled ? "<" : "\"") + Spelled +
99 (Angled ? ">" : "\""))
100 .str();
103 static llvm::SmallString<128> normalizePath(llvm::StringRef Path) {
104 namespace path = llvm::sys::path;
106 llvm::SmallString<128> P = Path;
107 path::remove_dots(P, /*remove_dot_dot=*/true);
108 path::native(P, path::Style::posix);
109 while (!P.empty() && P.back() == '/')
110 P.pop_back();
111 return P;
114 void Includes::addSearchDirectory(llvm::StringRef Path) {
115 SearchPath.try_emplace(normalizePath(Path));
118 void Includes::add(const Include &I) {
119 namespace path = llvm::sys::path;
121 unsigned Index = All.size();
122 All.push_back(I);
123 auto BySpellingIt = BySpelling.try_emplace(I.Spelled).first;
124 All.back().Spelled = BySpellingIt->first(); // Now we own the backing string.
126 BySpellingIt->second.push_back(Index);
127 ByLine[I.Line] = Index;
129 if (!I.Resolved)
130 return;
131 ByFile[&I.Resolved->getFileEntry()].push_back(Index);
133 // While verbatim headers ideally should match #include spelling exactly,
134 // we want to be tolerant of different spellings of the same file.
136 // If the search path includes "/a/b" and "/a/b/c/d",
137 // verbatim "e/f" should match (spelled=c/d/e/f, resolved=/a/b/c/d/e/f).
138 // We assume entry's (normalized) name will match the search dirs.
139 auto Path = normalizePath(I.Resolved->getName());
140 for (llvm::StringRef Parent = path::parent_path(Path); !Parent.empty();
141 Parent = path::parent_path(Parent)) {
142 if (!SearchPath.contains(Parent))
143 continue;
144 llvm::StringRef Rel =
145 llvm::StringRef(Path).drop_front(Parent.size()).ltrim('/');
146 BySpellingAlternate[Rel].push_back(Index);
150 const Include *Includes::atLine(unsigned OneBasedIndex) const {
151 auto It = ByLine.find(OneBasedIndex);
152 return (It == ByLine.end()) ? nullptr : &All[It->second];
155 llvm::SmallVector<const Include *> Includes::match(Header H) const {
156 llvm::SmallVector<const Include *> Result;
157 switch (H.kind()) {
158 case Header::Physical:
159 for (unsigned I : ByFile.lookup(H.physical()))
160 Result.push_back(&All[I]);
161 break;
162 case Header::Standard:
163 for (unsigned I : BySpelling.lookup(H.standard().name().trim("<>")))
164 Result.push_back(&All[I]);
165 break;
166 case Header::Verbatim: {
167 llvm::StringRef Spelling = H.verbatim().trim("\"<>");
168 for (unsigned I : BySpelling.lookup(Spelling))
169 Result.push_back(&All[I]);
170 for (unsigned I : BySpellingAlternate.lookup(Spelling))
171 if (!llvm::is_contained(Result, &All[I]))
172 Result.push_back(&All[I]);
173 break;
176 return Result;
179 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolLocation &S) {
180 switch (S.kind()) {
181 case SymbolLocation::Physical:
182 // We can't decode the Location without SourceManager. Its raw
183 // representation isn't completely useless (and distinguishes
184 // SymbolReference from Symbol).
185 return OS << "@0x"
186 << llvm::utohexstr(
187 S.physical().getRawEncoding(), /*LowerCase=*/false,
188 /*Width=*/CHAR_BIT * sizeof(SourceLocation::UIntTy));
189 case SymbolLocation::Standard:
190 return OS << S.standard().scope() << S.standard().name();
192 llvm_unreachable("Unhandled Symbol kind");
195 bool Header::operator<(const Header &RHS) const {
196 if (kind() != RHS.kind())
197 return kind() < RHS.kind();
198 switch (kind()) {
199 case Header::Physical:
200 return physical().getName() < RHS.physical().getName();
201 case Header::Standard:
202 return standard().name() < RHS.standard().name();
203 case Header::Verbatim:
204 return verbatim() < RHS.verbatim();
206 llvm_unreachable("unhandled Header kind");
208 } // namespace clang::include_cleaner