Revert "[clang][lex] Keep references to `DirectoryLookup` objects up-to-date"

This reverts commit 8503c688. This patch causes some issues with `#include_next`: https://github.com/llvm/llvm-project/issues/53161
This commit is contained in:
Jan Svoboda 2022-01-13 16:29:10 +01:00
parent 01494c6a73
commit ccd7e7830f
3 changed files with 73 additions and 150 deletions

View File

@ -171,23 +171,22 @@ class HeaderSearch {
/// Header-search options used to initialize this header search.
std::shared_ptr<HeaderSearchOptions> HSOpts;
/// Mapping from SearchDir to HeaderSearchOptions::UserEntries indices.
llvm::DenseMap<unsigned, unsigned> SearchDirToHSEntry;
DiagnosticsEngine &Diags;
FileManager &FileMgr;
/// The allocator owning search directories.
llvm::SpecificBumpPtrAllocator<DirectoryLookup> SearchDirsAlloc;
/// \#include search path information. Requests for \#include "x" search the
/// directory of the \#including file first, then each directory in SearchDirs
/// consecutively. Requests for <x> search the current dir first, then each
/// directory in SearchDirs, starting at AngledDirIdx, consecutively. If
/// NoCurDirSearch is true, then the check for the file in the current
/// directory is suppressed.
std::vector<DirectoryLookup *> SearchDirs;
/// Set of SearchDirs that have been successfully used to lookup a file.
llvm::DenseSet<const DirectoryLookup *> UsedSearchDirs;
/// Mapping from SearchDir to HeaderSearchOptions::UserEntries indices.
llvm::DenseMap<const DirectoryLookup *, unsigned> SearchDirToHSEntry;
std::vector<DirectoryLookup> SearchDirs;
/// Whether the DirectoryLookup at the corresponding index in SearchDirs has
/// been successfully used to lookup a file.
std::vector<bool> SearchDirsUsage;
unsigned AngledDirIdx = 0;
unsigned SystemDirIdx = 0;
bool NoCurDirSearch = false;
@ -295,7 +294,8 @@ public:
/// Add an additional system search path.
void AddSystemSearchPath(const DirectoryLookup &dir) {
SearchDirs.push_back(storeSearchDir(dir));
SearchDirs.push_back(dir);
SearchDirsUsage.push_back(false);
}
/// Set the list of system header prefixes.
@ -499,11 +499,7 @@ public:
/// Determine which HeaderSearchOptions::UserEntries have been successfully
/// used so far and mark their index with 'true' in the resulting bit vector.
// TODO: Use llvm::BitVector instead.
std::vector<bool> computeUserEntryUsage() const;
/// Return a bit vector of length \c SearchDirs.size() that indicates for each
/// search directory whether it was used.
std::vector<bool> getSearchDirUsage() const;
/// This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
@ -633,11 +629,6 @@ public:
void loadTopLevelSystemModules();
private:
/// Stores the given search directory and returns a stable pointer.
DirectoryLookup *storeSearchDir(const DirectoryLookup &Dir) {
return new (SearchDirsAlloc.Allocate()) DirectoryLookup(Dir);
}
/// Lookup a module with the given module name and search-name.
///
/// \param ModuleName The name of the module we're looking for.
@ -724,9 +715,8 @@ private:
void cacheLookupSuccess(LookupFileCacheInfo &CacheLookup, unsigned HitIdx,
SourceLocation IncludeLoc);
/// Note that a lookup at the given include location was successful using the
/// given search path.
void noteLookupUsage(const DirectoryLookup *SearchDir,
SourceLocation IncludeLoc);
/// search path at index `HitIdx`.
void noteLookupUsage(unsigned HitIdx, SourceLocation IncludeLoc);
public:
/// Retrieve the module map.
@ -749,8 +739,7 @@ public:
bool WantExternal = true) const;
// Used by external tools
using search_dir_iterator =
llvm::pointee_iterator<decltype(SearchDirs)::const_iterator>;
using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator;
search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
@ -778,6 +767,9 @@ public:
search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
/// Get the index of the given search directory.
Optional<unsigned> searchDirIdx(const DirectoryLookup &DL) const;
/// Retrieve a uniqued framework name.
StringRef getUniqueFrameworkName(StringRef Framework);

View File

@ -115,24 +115,19 @@ void HeaderSearch::SetSearchPaths(
llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
"Directory indices are unordered");
SearchDirsAlloc.DestroyAll();
SearchDirs.clear();
for (const DirectoryLookup &Dir : dirs)
SearchDirs.push_back(storeSearchDir(Dir));
UsedSearchDirs.clear();
SearchDirToHSEntry.clear();
for (const auto &Entry : searchDirToHSEntry)
SearchDirToHSEntry.insert({SearchDirs[Entry.first], Entry.second});
SearchDirs = std::move(dirs);
SearchDirsUsage.assign(SearchDirs.size(), false);
AngledDirIdx = angledDirIdx;
SystemDirIdx = systemDirIdx;
NoCurDirSearch = noCurDirSearch;
SearchDirToHSEntry = std::move(searchDirToHSEntry);
//LookupFileCache.clear();
}
void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
SearchDirs.insert(SearchDirs.begin() + idx, storeSearchDir(dir));
SearchDirs.insert(SearchDirs.begin() + idx, dir);
SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);
if (!isAngled)
AngledDirIdx++;
SystemDirIdx++;
@ -140,9 +135,10 @@ void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
for (const DirectoryLookup *SearchDir : UsedSearchDirs) {
if (UsedSearchDirs.contains(SearchDir)) {
auto UserEntryIdxIt = SearchDirToHSEntry.find(SearchDir);
for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
// Check whether this DirectoryLookup has been successfully used.
if (SearchDirsUsage[I]) {
auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
// Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
if (UserEntryIdxIt != SearchDirToHSEntry.end())
UserEntryUsage[UserEntryIdxIt->second] = true;
@ -151,14 +147,6 @@ std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
return UserEntryUsage;
}
std::vector<bool> HeaderSearch::getSearchDirUsage() const {
std::vector<bool> SearchDirUsage(SearchDirs.size());
for (unsigned I = 0, E = SearchDirs.size(); I < E; ++I)
if (UsedSearchDirs.contains(SearchDirs[I]))
SearchDirUsage[I] = true;
return SearchDirUsage;
}
/// CreateHeaderMap - This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
@ -313,23 +301,21 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
SourceLocation ImportLoc,
bool AllowExtraModuleMapSearch) {
Module *Module = nullptr;
DirectoryLookup *SearchDir = nullptr;
unsigned Idx;
// Look through the various header search paths to load any available module
// maps, searching for a module map that describes this module.
for (unsigned Idx = 0; Idx != SearchDirs.size(); ++Idx) {
SearchDir = SearchDirs[Idx];
if (SearchDirs[Idx]->isFramework()) {
for (Idx = 0; Idx != SearchDirs.size(); ++Idx) {
if (SearchDirs[Idx].isFramework()) {
// Search for or infer a module map for a framework. Here we use
// SearchName rather than ModuleName, to permit finding private modules
// named FooPrivate in buggy frameworks named Foo.
SmallString<128> FrameworkDirName;
FrameworkDirName += SearchDirs[Idx]->getFrameworkDir()->getName();
FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) {
bool IsSystem
= SearchDirs[Idx]->getDirCharacteristic() != SrcMgr::C_User;
= SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
if (Module)
break;
@ -339,12 +325,12 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
// FIXME: Figure out how header maps and module maps will work together.
// Only deal with normal search directories.
if (!SearchDirs[Idx]->isNormalDir())
if (!SearchDirs[Idx].isNormalDir())
continue;
bool IsSystem = SearchDirs[Idx]->isSystemHeaderDirectory();
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
// Search for a module map file in this directory.
if (loadModuleMapFile(SearchDirs[Idx]->getDir(), IsSystem,
if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
/*IsFramework*/false) == LMM_NewlyLoaded) {
// We just loaded a module map file; check whether the module is
// available now.
@ -356,7 +342,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
// Search for a module map in a subdirectory with the same name as the
// module.
SmallString<128> NestedModuleMapDirName;
NestedModuleMapDirName = SearchDirs[Idx]->getDir()->getName();
NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName();
llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
/*IsFramework*/false) == LMM_NewlyLoaded){
@ -368,13 +354,13 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
// If we've already performed the exhaustive search for module maps in this
// search directory, don't do it again.
if (SearchDirs[Idx]->haveSearchedAllModuleMaps())
if (SearchDirs[Idx].haveSearchedAllModuleMaps())
continue;
// Load all module maps in the immediate subdirectories of this search
// directory if ModuleName was from @import.
if (AllowExtraModuleMapSearch)
loadSubdirectoryModuleMaps(*SearchDirs[Idx]);
loadSubdirectoryModuleMaps(SearchDirs[Idx]);
// Look again for the module.
Module = ModMap.findModule(ModuleName);
@ -383,7 +369,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
}
if (Module)
noteLookupUsage(SearchDir, ImportLoc);
noteLookupUsage(Idx, ImportLoc);
return Module;
}
@ -509,7 +495,7 @@ Optional<FileEntryRef> DirectoryLookup::LookupFile(
// The case where the target file **exists** is handled by callee of this
// function as part of the regular logic that applies to include search paths.
// The case where the target file **does not exist** is handled here:
HS.noteLookupUsage(this, IncludeLoc);
HS.noteLookupUsage(*HS.searchDirIdx(*this), IncludeLoc);
return None;
}
@ -717,14 +703,13 @@ Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup(
void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
unsigned HitIdx, SourceLocation Loc) {
CacheLookup.HitIdx = HitIdx;
noteLookupUsage(SearchDirs[HitIdx], Loc);
noteLookupUsage(HitIdx, Loc);
}
void HeaderSearch::noteLookupUsage(const DirectoryLookup *SearchDir,
SourceLocation Loc) {
UsedSearchDirs.insert(SearchDir);
void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
SearchDirsUsage[HitIdx] = true;
auto UserEntryIdxIt = SearchDirToHSEntry.find(SearchDir);
auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
if (UserEntryIdxIt != SearchDirToHSEntry.end())
Diags.Report(Loc, diag::remark_pp_search_path_usage)
<< HSOpts->UserEntries[UserEntryIdxIt->second].Path;
@ -978,7 +963,7 @@ Optional<FileEntryRef> HeaderSearch::LookupFile(
// If this is a #include_next request, start searching after the directory the
// file was found in.
if (FromDir)
i = std::distance(SearchDirs.begin(), llvm::find(SearchDirs, FromDir));
i = FromDir-&SearchDirs[0];
// Cache all of the lookups performed by this method. Many headers are
// multiply included, and the "pragma once" optimization prevents them from
@ -1011,7 +996,7 @@ Optional<FileEntryRef> HeaderSearch::LookupFile(
bool InUserSpecifiedSystemFramework = false;
bool IsInHeaderMap = false;
bool IsFrameworkFoundInDir = false;
Optional<FileEntryRef> File = SearchDirs[i]->LookupFile(
Optional<FileEntryRef> File = SearchDirs[i].LookupFile(
Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
IsInHeaderMap, MappedName);
@ -1033,7 +1018,7 @@ Optional<FileEntryRef> HeaderSearch::LookupFile(
if (!File)
continue;
CurDir = SearchDirs[i];
CurDir = &SearchDirs[i];
// This file is a system header or C++ unfriendly if the dir is.
HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry());
@ -1455,6 +1440,13 @@ size_t HeaderSearch::getTotalMemory() const {
+ FrameworkMap.getAllocator().getTotalMemory();
}
Optional<unsigned> HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
for (unsigned I = 0; I < SearchDirs.size(); ++I)
if (&SearchDirs[I] == &DL)
return I;
return None;
}
StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
return FrameworkNames.insert(Framework).first->first();
}
@ -1782,11 +1774,11 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
if (HSOpts->ImplicitModuleMaps) {
// Load module maps for each of the header search directories.
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
bool IsSystem = SearchDirs[Idx]->isSystemHeaderDirectory();
if (SearchDirs[Idx]->isFramework()) {
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
if (SearchDirs[Idx].isFramework()) {
std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(SearchDirs[Idx]->getFrameworkDir()->getName(),
llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(),
DirNative);
// Search each of the ".framework" directories to load them as modules.
@ -1810,16 +1802,16 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
}
// FIXME: Deal with header maps.
if (SearchDirs[Idx]->isHeaderMap())
if (SearchDirs[Idx].isHeaderMap())
continue;
// Try to load a module map file for the search directory.
loadModuleMapFile(SearchDirs[Idx]->getDir(), IsSystem,
loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
/*IsFramework*/ false);
// Try to load module map files for immediate subdirectories of this
// search directory.
loadSubdirectoryModuleMaps(*SearchDirs[Idx]);
loadSubdirectoryModuleMaps(SearchDirs[Idx]);
}
}
@ -1835,13 +1827,14 @@ void HeaderSearch::loadTopLevelSystemModules() {
// Load module maps for each of the header search directories.
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
// We only care about normal header directories.
if (!SearchDirs[Idx]->isNormalDir())
if (!SearchDirs[Idx].isNormalDir()) {
continue;
}
// Try to load a module map file for the search directory.
loadModuleMapFile(SearchDirs[Idx]->getDir(),
SearchDirs[Idx]->isSystemHeaderDirectory(),
SearchDirs[Idx]->isFramework());
loadModuleMapFile(SearchDirs[Idx].getDir(),
SearchDirs[Idx].isSystemHeaderDirectory(),
SearchDirs[Idx].isFramework());
}
}
@ -1939,15 +1932,15 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
bool BestPrefixIsFramework = false;
for (unsigned I = 0; I != SearchDirs.size(); ++I) {
if (SearchDirs[I]->isNormalDir()) {
StringRef Dir = SearchDirs[I]->getDir()->getName();
if (SearchDirs[I].isNormalDir()) {
StringRef Dir = SearchDirs[I].getDir()->getName();
if (CheckDir(Dir)) {
if (IsSystem)
*IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
BestPrefixIsFramework = false;
}
} else if (SearchDirs[I]->isFramework()) {
StringRef Dir = SearchDirs[I]->getFrameworkDir()->getName();
} else if (SearchDirs[I].isFramework()) {
StringRef Dir = SearchDirs[I].getFrameworkDir()->getName();
if (CheckDir(Dir)) {
if (IsSystem)
*IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
@ -1968,11 +1961,11 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
// key from header name is user prefered name for the include file.
StringRef Filename = File.drop_front(BestPrefixLength);
for (unsigned I = 0; I != SearchDirs.size(); ++I) {
if (!SearchDirs[I]->isHeaderMap())
if (!SearchDirs[I].isHeaderMap())
continue;
StringRef SpelledFilename =
SearchDirs[I]->getHeaderMap()->reverseLookupFilename(Filename);
SearchDirs[I].getHeaderMap()->reverseLookupFilename(Filename);
if (!SpelledFilename.empty()) {
Filename = SpelledFilename;
BestPrefixIsFramework = false;

View File

@ -23,12 +23,6 @@
namespace clang {
namespace {
static std::shared_ptr<TargetOptions> createTargetOptions() {
auto TargetOpts = std::make_shared<TargetOptions>();
TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
return TargetOpts;
}
// The test fixture.
class HeaderSearchTest : public ::testing::Test {
protected:
@ -36,10 +30,12 @@ protected:
: VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS),
DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr), TargetOpts(createTargetOptions()),
Target(TargetInfo::CreateTargetInfo(Diags, TargetOpts)),
SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions),
Search(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags,
LangOpts, Target.get()) {}
LangOpts, Target.get()) {
TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
}
void addSearchDir(llvm::StringRef Dir) {
VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/None,
@ -59,27 +55,6 @@ protected:
Search.AddSystemSearchPath(DL);
}
void setSearchDirs(llvm::ArrayRef<llvm::StringRef> QuotedDirs,
llvm::ArrayRef<llvm::StringRef> AngledDirs) {
auto AddPath = [&](StringRef Dir, bool IsAngled) {
VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/None,
/*Group=*/None, llvm::sys::fs::file_type::directory_file);
auto Group = IsAngled ? frontend::IncludeDirGroup::Angled
: frontend::IncludeDirGroup::Quoted;
Search.getHeaderSearchOpts().AddPath(Dir, Group,
/*IsFramework=*/false,
/*IgnoreSysRoot=*/true);
};
for (llvm::StringRef Dir : QuotedDirs)
AddPath(Dir, /*IsAngled=*/false);
for (llvm::StringRef Dir : AngledDirs)
AddPath(Dir, /*IsAngled=*/true);
clang::ApplyHeaderSearchOptions(Search, Search.getHeaderSearchOpts(),
LangOpts, Target->getTriple());
}
void addHeaderMap(llvm::StringRef Filename,
std::unique_ptr<llvm::MemoryBuffer> Buf,
bool isAngled = false) {
@ -96,17 +71,6 @@ protected:
Search.AddSearchPath(DL, isAngled);
}
void createModule(StringRef Mod) {
std::string ModDir = ("/" + Mod).str();
std::string ModHeader = (Mod + ".h").str();
VFS->addFile(
ModDir + "/module.modulemap", 0,
llvm::MemoryBuffer::getMemBufferCopy(
("module " + Mod + " { header \"" + ModHeader + "\" }").str()));
VFS->addFile(ModDir + "/" + ModHeader, 0,
llvm::MemoryBuffer::getMemBuffer(""));
}
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
FileSystemOptions FileMgrOpts;
FileManager FileMgr;
@ -291,31 +255,5 @@ TEST_F(HeaderSearchTest, HeaderMapFrameworkLookup) {
EXPECT_EQ(FI->Framework.str(), "Foo");
}
TEST_F(HeaderSearchTest, SearchPathUsage) {
Search.getHeaderSearchOpts().ImplicitModuleMaps = true;
setSearchDirs(/*QuotedDirs=*/{"/M0"}, /*AngledDirs=*/{"/M2", "/M3"});
createModule("M0");
createModule("M2");
createModule("M3");
{
Module *M2 = Search.lookupModule("M2");
EXPECT_NE(M2, nullptr);
EXPECT_EQ(Search.getSearchDirUsage(), (std::vector<bool>{0, 1, 0}));
EXPECT_EQ(Search.computeUserEntryUsage(), (std::vector<bool>{0, 1, 0}));
}
addSearchDir("/M1");
createModule("M1");
{
Module *M1 = Search.lookupModule("M1");
EXPECT_NE(M1, nullptr);
EXPECT_EQ(Search.getSearchDirUsage(), (std::vector<bool>{0, 1, 1, 0}));
EXPECT_EQ(Search.computeUserEntryUsage(), (std::vector<bool>{0, 1, 0}));
}
}
} // namespace
} // namespace clang