Skip to content

Commit e7dcf09

Browse files
committed
[clang][lex] Use SearchDirIterator types in for loops
This patch replaces a lot of index-based loops with iterators and ranges. Depends on D117566. Reviewed By: ahoppen Differential Revision: https://reviews.llvm.org/D119722
1 parent 17c9fcd commit e7dcf09

File tree

2 files changed

+83
-62
lines changed

2 files changed

+83
-62
lines changed

clang/include/clang/Lex/HeaderSearch.h

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,54 +163,79 @@ struct FrameworkCacheEntry {
163163
bool IsUserSpecifiedSystemFramework;
164164
};
165165

166-
/// Forward iterator over the search directories of \c HeaderSearch.
167-
struct ConstSearchDirIterator
168-
: llvm::iterator_facade_base<ConstSearchDirIterator,
166+
namespace detail {
167+
template <bool Const, typename T>
168+
using Qualified = std::conditional_t<Const, const T, T>;
169+
170+
/// Forward iterator over the search directories of HeaderSearch.
171+
/// Does not get invalidated by \c HeaderSearch::Add{,System}SearchPath.
172+
template <bool IsConst>
173+
struct SearchDirIteratorImpl
174+
: llvm::iterator_facade_base<SearchDirIteratorImpl<IsConst>,
169175
std::forward_iterator_tag,
170-
const DirectoryLookup> {
171-
ConstSearchDirIterator(const ConstSearchDirIterator &) = default;
176+
Qualified<IsConst, DirectoryLookup>> {
177+
/// Const -> non-const iterator conversion.
178+
template <typename Enable = std::enable_if<IsConst, bool>>
179+
SearchDirIteratorImpl(const SearchDirIteratorImpl<false> &Other)
180+
: HS(Other.HS), Idx(Other.Idx) {}
172181

173-
ConstSearchDirIterator &operator=(const ConstSearchDirIterator &) = default;
182+
SearchDirIteratorImpl(const SearchDirIteratorImpl &) = default;
174183

175-
bool operator==(const ConstSearchDirIterator &RHS) const {
184+
SearchDirIteratorImpl &operator=(const SearchDirIteratorImpl &) = default;
185+
186+
bool operator==(const SearchDirIteratorImpl &RHS) const {
176187
return HS == RHS.HS && Idx == RHS.Idx;
177188
}
178189

179-
ConstSearchDirIterator &operator++() {
190+
SearchDirIteratorImpl &operator++() {
180191
assert(*this && "Invalid iterator.");
181192
++Idx;
182193
return *this;
183194
}
184195

185-
const DirectoryLookup &operator*() const;
196+
Qualified<IsConst, DirectoryLookup> &operator*() const {
197+
assert(*this && "Invalid iterator.");
198+
return HS->SearchDirs[Idx];
199+
}
186200

187201
/// Creates an invalid iterator.
188-
ConstSearchDirIterator(std::nullptr_t) : HS(nullptr), Idx(0) {}
202+
SearchDirIteratorImpl(std::nullptr_t) : HS(nullptr), Idx(0) {}
189203

190204
/// Checks whether the iterator is valid.
191205
explicit operator bool() const { return HS != nullptr; }
192206

193207
private:
194208
/// The parent \c HeaderSearch. This is \c nullptr for invalid iterator.
195-
const HeaderSearch *HS;
209+
Qualified<IsConst, HeaderSearch> *HS;
196210

197211
/// The index of the current element.
198212
size_t Idx;
199213

200214
/// The constructor that creates a valid iterator.
201-
ConstSearchDirIterator(const HeaderSearch &HS, size_t Idx)
215+
SearchDirIteratorImpl(Qualified<IsConst, HeaderSearch> &HS, size_t Idx)
202216
: HS(&HS), Idx(Idx) {}
203217

204218
/// Only HeaderSearch is allowed to instantiate valid iterators.
205219
friend HeaderSearch;
220+
221+
/// Enables const -> non-const conversion.
222+
friend SearchDirIteratorImpl<!IsConst>;
206223
};
224+
} // namespace detail
225+
226+
using ConstSearchDirIterator = detail::SearchDirIteratorImpl<true>;
227+
using SearchDirIterator = detail::SearchDirIteratorImpl<false>;
228+
229+
using ConstSearchDirRange = llvm::iterator_range<ConstSearchDirIterator>;
230+
using SearchDirRange = llvm::iterator_range<SearchDirIterator>;
207231

208232
/// Encapsulates the information needed to find the file referenced
209233
/// by a \#include or \#include_next, (sub-)framework lookup, etc.
210234
class HeaderSearch {
211235
friend class DirectoryLookup;
212236

213237
friend ConstSearchDirIterator;
238+
friend SearchDirIterator;
214239

215240
/// Header-search options used to initialize this header search.
216241
std::shared_ptr<HeaderSearchOptions> HSOpts;
@@ -778,8 +803,17 @@ class HeaderSearch {
778803
const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
779804
bool WantExternal = true) const;
780805

806+
SearchDirIterator search_dir_begin() { return {*this, 0}; }
807+
SearchDirIterator search_dir_end() { return {*this, SearchDirs.size()}; }
808+
SearchDirRange search_dir_range() {
809+
return {search_dir_begin(), search_dir_end()};
810+
}
811+
781812
ConstSearchDirIterator search_dir_begin() const { return quoted_dir_begin(); }
782813
ConstSearchDirIterator search_dir_end() const { return system_dir_end(); }
814+
ConstSearchDirRange search_dir_range() const {
815+
return {search_dir_begin(), search_dir_end()};
816+
}
783817

784818
unsigned search_dir_size() const { return SearchDirs.size(); }
785819

@@ -799,7 +833,7 @@ class HeaderSearch {
799833
}
800834

801835
/// Get the index of the given search directory.
802-
Optional<unsigned> searchDirIdx(const DirectoryLookup &DL) const;
836+
unsigned searchDirIdx(const DirectoryLookup &DL) const;
803837

804838
/// Retrieve a uniqued framework name.
805839
StringRef getUniqueFrameworkName(StringRef Framework);

clang/lib/Lex/HeaderSearch.cpp

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
7979

8080
ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;
8181

82-
const DirectoryLookup &ConstSearchDirIterator::operator*() const {
83-
assert(*this && "Invalid iterator.");
84-
return HS->SearchDirs[Idx];
85-
}
86-
8782
HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
8883
SourceManager &SourceMgr, DiagnosticsEngine &Diags,
8984
const LangOptions &LangOpts,
@@ -304,21 +299,20 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
304299
SourceLocation ImportLoc,
305300
bool AllowExtraModuleMapSearch) {
306301
Module *Module = nullptr;
307-
unsigned Idx;
302+
SearchDirIterator It = nullptr;
308303

309304
// Look through the various header search paths to load any available module
310305
// maps, searching for a module map that describes this module.
311-
for (Idx = 0; Idx != SearchDirs.size(); ++Idx) {
312-
if (SearchDirs[Idx].isFramework()) {
306+
for (It = search_dir_begin(); It != search_dir_end(); ++It) {
307+
if (It->isFramework()) {
313308
// Search for or infer a module map for a framework. Here we use
314309
// SearchName rather than ModuleName, to permit finding private modules
315310
// named FooPrivate in buggy frameworks named Foo.
316311
SmallString<128> FrameworkDirName;
317-
FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
312+
FrameworkDirName += It->getFrameworkDir()->getName();
318313
llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
319314
if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) {
320-
bool IsSystem
321-
= SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
315+
bool IsSystem = It->getDirCharacteristic() != SrcMgr::C_User;
322316
Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
323317
if (Module)
324318
break;
@@ -328,12 +322,12 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
328322
// FIXME: Figure out how header maps and module maps will work together.
329323

330324
// Only deal with normal search directories.
331-
if (!SearchDirs[Idx].isNormalDir())
325+
if (!It->isNormalDir())
332326
continue;
333327

334-
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
328+
bool IsSystem = It->isSystemHeaderDirectory();
335329
// Search for a module map file in this directory.
336-
if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
330+
if (loadModuleMapFile(It->getDir(), IsSystem,
337331
/*IsFramework*/false) == LMM_NewlyLoaded) {
338332
// We just loaded a module map file; check whether the module is
339333
// available now.
@@ -345,7 +339,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
345339
// Search for a module map in a subdirectory with the same name as the
346340
// module.
347341
SmallString<128> NestedModuleMapDirName;
348-
NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName();
342+
NestedModuleMapDirName = It->getDir()->getName();
349343
llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
350344
if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
351345
/*IsFramework*/false) == LMM_NewlyLoaded){
@@ -357,13 +351,13 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
357351

358352
// If we've already performed the exhaustive search for module maps in this
359353
// search directory, don't do it again.
360-
if (SearchDirs[Idx].haveSearchedAllModuleMaps())
354+
if (It->haveSearchedAllModuleMaps())
361355
continue;
362356

363357
// Load all module maps in the immediate subdirectories of this search
364358
// directory if ModuleName was from @import.
365359
if (AllowExtraModuleMapSearch)
366-
loadSubdirectoryModuleMaps(SearchDirs[Idx]);
360+
loadSubdirectoryModuleMaps(*It);
367361

368362
// Look again for the module.
369363
Module = ModMap.findModule(ModuleName);
@@ -372,7 +366,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
372366
}
373367

374368
if (Module)
375-
noteLookupUsage(Idx, ImportLoc);
369+
noteLookupUsage(It.Idx, ImportLoc);
376370

377371
return Module;
378372
}
@@ -498,7 +492,7 @@ Optional<FileEntryRef> DirectoryLookup::LookupFile(
498492
// The case where the target file **exists** is handled by callee of this
499493
// function as part of the regular logic that applies to include search paths.
500494
// The case where the target file **does not exist** is handled here:
501-
HS.noteLookupUsage(*HS.searchDirIdx(*this), IncludeLoc);
495+
HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);
502496
return None;
503497
}
504498

@@ -1452,11 +1446,8 @@ size_t HeaderSearch::getTotalMemory() const {
14521446
+ FrameworkMap.getAllocator().getTotalMemory();
14531447
}
14541448

1455-
Optional<unsigned> HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
1456-
for (unsigned I = 0; I < SearchDirs.size(); ++I)
1457-
if (&SearchDirs[I] == &DL)
1458-
return I;
1459-
return None;
1449+
unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
1450+
return &DL - &*SearchDirs.begin();
14601451
}
14611452

14621453
StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
@@ -1785,13 +1776,12 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
17851776

17861777
if (HSOpts->ImplicitModuleMaps) {
17871778
// Load module maps for each of the header search directories.
1788-
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
1789-
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
1790-
if (SearchDirs[Idx].isFramework()) {
1779+
for (DirectoryLookup &DL : search_dir_range()) {
1780+
bool IsSystem = DL.isSystemHeaderDirectory();
1781+
if (DL.isFramework()) {
17911782
std::error_code EC;
17921783
SmallString<128> DirNative;
1793-
llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(),
1794-
DirNative);
1784+
llvm::sys::path::native(DL.getFrameworkDir()->getName(), DirNative);
17951785

17961786
// Search each of the ".framework" directories to load them as modules.
17971787
llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
@@ -1814,16 +1804,15 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
18141804
}
18151805

18161806
// FIXME: Deal with header maps.
1817-
if (SearchDirs[Idx].isHeaderMap())
1807+
if (DL.isHeaderMap())
18181808
continue;
18191809

18201810
// Try to load a module map file for the search directory.
1821-
loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
1822-
/*IsFramework*/ false);
1811+
loadModuleMapFile(DL.getDir(), IsSystem, /*IsFramework*/ false);
18231812

18241813
// Try to load module map files for immediate subdirectories of this
18251814
// search directory.
1826-
loadSubdirectoryModuleMaps(SearchDirs[Idx]);
1815+
loadSubdirectoryModuleMaps(DL);
18271816
}
18281817
}
18291818

@@ -1837,16 +1826,14 @@ void HeaderSearch::loadTopLevelSystemModules() {
18371826
return;
18381827

18391828
// Load module maps for each of the header search directories.
1840-
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
1829+
for (const DirectoryLookup &DL : search_dir_range()) {
18411830
// We only care about normal header directories.
1842-
if (!SearchDirs[Idx].isNormalDir()) {
1831+
if (!DL.isNormalDir())
18431832
continue;
1844-
}
18451833

18461834
// Try to load a module map file for the search directory.
1847-
loadModuleMapFile(SearchDirs[Idx].getDir(),
1848-
SearchDirs[Idx].isSystemHeaderDirectory(),
1849-
SearchDirs[Idx].isFramework());
1835+
loadModuleMapFile(DL.getDir(), DL.isSystemHeaderDirectory(),
1836+
DL.isFramework());
18501837
}
18511838
}
18521839

@@ -1943,19 +1930,19 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
19431930
};
19441931

19451932
bool BestPrefixIsFramework = false;
1946-
for (unsigned I = 0; I != SearchDirs.size(); ++I) {
1947-
if (SearchDirs[I].isNormalDir()) {
1948-
StringRef Dir = SearchDirs[I].getDir()->getName();
1933+
for (const DirectoryLookup &DL : search_dir_range()) {
1934+
if (DL.isNormalDir()) {
1935+
StringRef Dir = DL.getDir()->getName();
19491936
if (CheckDir(Dir)) {
19501937
if (IsSystem)
1951-
*IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
1938+
*IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
19521939
BestPrefixIsFramework = false;
19531940
}
1954-
} else if (SearchDirs[I].isFramework()) {
1955-
StringRef Dir = SearchDirs[I].getFrameworkDir()->getName();
1941+
} else if (DL.isFramework()) {
1942+
StringRef Dir = DL.getFrameworkDir()->getName();
19561943
if (CheckDir(Dir)) {
19571944
if (IsSystem)
1958-
*IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
1945+
*IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
19591946
BestPrefixIsFramework = true;
19601947
}
19611948
}
@@ -1972,12 +1959,12 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
19721959
// Try resolving resulting filename via reverse search in header maps,
19731960
// key from header name is user prefered name for the include file.
19741961
StringRef Filename = File.drop_front(BestPrefixLength);
1975-
for (unsigned I = 0; I != SearchDirs.size(); ++I) {
1976-
if (!SearchDirs[I].isHeaderMap())
1962+
for (const DirectoryLookup &DL : search_dir_range()) {
1963+
if (!DL.isHeaderMap())
19771964
continue;
19781965

19791966
StringRef SpelledFilename =
1980-
SearchDirs[I].getHeaderMap()->reverseLookupFilename(Filename);
1967+
DL.getHeaderMap()->reverseLookupFilename(Filename);
19811968
if (!SpelledFilename.empty()) {
19821969
Filename = SpelledFilename;
19831970
BestPrefixIsFramework = false;

0 commit comments

Comments
 (0)