Move search for header in umbrella directories into its own function

No functional change intended.

llvm-svn: 205942
This commit is contained in:
Ben Langmuir 2014-04-10 00:39:10 +00:00
parent 83b44e1e21
commit 4469138e98
2 changed files with 88 additions and 71 deletions

View File

@ -182,6 +182,15 @@ private:
/// associated with a specific module (e.g. in /usr/include).
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:
/// \brief Construct a new module map.
///

View File

@ -170,6 +170,38 @@ ModuleMap::findKnownHeader(const FileEntry *File) {
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'.
static bool directlyUses(const Module *RequestingModule,
const Module *RequestedModule) {
@ -305,22 +337,10 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
return Result;
}
const DirectoryEntry *Dir = File->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
// 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 {
llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
= UmbrellaDirs.find(Dir);
if (KnownDir != UmbrellaDirs.end()) {
Module *Result = KnownDir->second;
KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
if (H) {
Module *Result = H.getModule();
// Search up the module stack until we find a module with an umbrella
// directory.
@ -338,8 +358,7 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
// 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);
llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Explicit).first;
@ -381,17 +400,6 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
return Headers[File].back();
}
SkippedDirs.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();
}