Skip to content
Snippets Groups Projects
Commit ae39224b authored by Ben Langmuir's avatar Ben Langmuir
Browse files

Move search for header in umbrella directories into its own function

No functional change intended.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205942 91177308-0d34-0410-b5e6-96231b3b80d8
parent b622f9d0
No related branches found
No related tags found
No related merge requests found
...@@ -182,6 +182,15 @@ private: ...@@ -182,6 +182,15 @@ private:
/// associated with a specific module (e.g. in /usr/include). /// associated with a specific module (e.g. in /usr/include).
HeadersMap::iterator findKnownHeader(const FileEntry *File); HeadersMap::iterator findKnownHeader(const FileEntry *File);
/// \brief Searches for a module whose umbrella directory contains \p File.
///
/// \param File The header to search for.
///
/// \param IntermediateDirs On success, contains the set of directories
/// searched before finding \p File.
KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
public: public:
/// \brief Construct a new module map. /// \brief Construct a new module map.
/// ///
......
...@@ -170,6 +170,38 @@ ModuleMap::findKnownHeader(const FileEntry *File) { ...@@ -170,6 +170,38 @@ ModuleMap::findKnownHeader(const FileEntry *File) {
return Known; return Known;
} }
ModuleMap::KnownHeader
ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
const DirectoryEntry *Dir = File->getDir();
assert(Dir && "file in no directory");
// Note: as an egregious but useful hack we use the real path here, because
// frameworks moving from top-level frameworks to embedded frameworks tend
// to be symlinked from the top-level location to the embedded location,
// and we need to resolve lookups as if we had found the embedded location.
StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
// Keep walking up the directory hierarchy, looking for a directory with
// an umbrella header.
do {
auto KnownDir = UmbrellaDirs.find(Dir);
if (KnownDir != UmbrellaDirs.end())
return KnownHeader(KnownDir->second, NormalHeader);
IntermediateDirs.push_back(Dir);
// Retrieve our parent path.
DirName = llvm::sys::path::parent_path(DirName);
if (DirName.empty())
break;
// Resolve the parent path to a directory entry.
Dir = SourceMgr.getFileManager().getDirectory(DirName);
} while (Dir);
return KnownHeader();
}
// Returns 'true' if 'RequestingModule directly uses 'RequestedModule'. // Returns 'true' if 'RequestingModule directly uses 'RequestedModule'.
static bool directlyUses(const Module *RequestingModule, static bool directlyUses(const Module *RequestingModule,
const Module *RequestedModule) { const Module *RequestedModule) {
...@@ -305,92 +337,68 @@ ModuleMap::findModuleForHeader(const FileEntry *File, ...@@ -305,92 +337,68 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
return Result; return Result;
} }
const DirectoryEntry *Dir = File->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs; SmallVector<const DirectoryEntry *, 2> SkippedDirs;
KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
// Note: as an egregious but useful hack we use the real path here, because if (H) {
// frameworks moving from top-level frameworks to embedded frameworks tend Module *Result = H.getModule();
// to be symlinked from the top-level location to the embedded location,
// and we need to resolve lookups as if we had found the embedded location. // Search up the module stack until we find a module with an umbrella
StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); // directory.
Module *UmbrellaModule = Result;
// Keep walking up the directory hierarchy, looking for a directory with while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
// an umbrella header. UmbrellaModule = UmbrellaModule->Parent;
do {
llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir if (UmbrellaModule->InferSubmodules) {
= UmbrellaDirs.find(Dir); // Infer submodules for each of the directories we found between
if (KnownDir != UmbrellaDirs.end()) { // the directory of the umbrella header and the directory where
Module *Result = KnownDir->second; // the actual header is located.
bool Explicit = UmbrellaModule->InferExplicitSubmodules;
// Search up the module stack until we find a module with an umbrella
// directory. for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Module *UmbrellaModule = Result; // Find or create the module that corresponds to this directory name.
while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
UmbrellaModule = UmbrellaModule->Parent;
if (UmbrellaModule->InferSubmodules) {
// Infer submodules for each of the directories we found between
// the directory of the umbrella header and the directory where
// the actual header is located.
bool Explicit = UmbrellaModule->InferExplicitSubmodules;
for (unsigned I = SkippedDirs.size(); I != 0; --I) {
// Find or create the module that corresponds to this directory name.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
NameBuf);
Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Explicit).first;
// Associate the module and the directory.
UmbrellaDirs[SkippedDirs[I-1]] = Result;
// If inferred submodules export everything they import, add a
// wildcard to the set of exports.
if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Result->Exports.push_back(Module::ExportDecl(0, true));
}
// Infer a submodule with the same name as this header file.
SmallString<32> NameBuf; SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier( StringRef Name = sanitizeFilenameAsIdentifier(
llvm::sys::path::stem(File->getName()), NameBuf); llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Explicit).first; Explicit).first;
Result->addTopHeader(File);
// Associate the module and the directory.
// If inferred submodules export everything they import, add a UmbrellaDirs[SkippedDirs[I-1]] = Result;
// If inferred submodules export everything they import, add a
// wildcard to the set of exports. // wildcard to the set of exports.
if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Result->Exports.push_back(Module::ExportDecl(0, true)); Result->Exports.push_back(Module::ExportDecl(0, true));
} else {
// Record each of the directories we stepped through as being part of
// the module we found, since the umbrella header covers them all.
for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
UmbrellaDirs[SkippedDirs[I]] = Result;
} }
Headers[File].push_back(KnownHeader(Result, NormalHeader));
// If a header corresponds to an unavailable module, don't report
// that it maps to anything.
if (!Result->isAvailable())
return KnownHeader();
return Headers[File].back(); // Infer a submodule with the same name as this header file.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
llvm::sys::path::stem(File->getName()), NameBuf);
Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Explicit).first;
Result->addTopHeader(File);
// If inferred submodules export everything they import, add a
// wildcard to the set of exports.
if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Result->Exports.push_back(Module::ExportDecl(0, true));
} else {
// Record each of the directories we stepped through as being part of
// the module we found, since the umbrella header covers them all.
for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
UmbrellaDirs[SkippedDirs[I]] = Result;
} }
SkippedDirs.push_back(Dir); Headers[File].push_back(KnownHeader(Result, NormalHeader));
// Retrieve our parent path. // If a header corresponds to an unavailable module, don't report
DirName = llvm::sys::path::parent_path(DirName); // that it maps to anything.
if (DirName.empty()) if (!Result->isAvailable())
break; return KnownHeader();
// Resolve the parent path to a directory entry. return Headers[File].back();
Dir = SourceMgr.getFileManager().getDirectory(DirName); }
} while (Dir);
return KnownHeader(); return KnownHeader();
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment