Refactor module lookup when looking up a header file, and wire through the requesting module. No functionality change.

llvm-svn: 250554
This commit is contained in:
Richard Smith 2015-10-16 21:42:56 +00:00
parent 83a131fa73
commit 3d5b48c480
5 changed files with 130 additions and 99 deletions

View File

@ -158,6 +158,8 @@ public:
/// SearchPath at which the file was found. This only differs from the
/// Filename for framework includes.
///
/// \param RequestingModule The module in which the lookup was performed.
///
/// \param SuggestedModule If non-null, and the file found is semantically
/// part of a known module, this will be set to the module that should
/// be imported instead of preprocessing/parsing the file found.
@ -172,6 +174,7 @@ public:
const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework,
bool &HasBeenMapped,
@ -182,6 +185,7 @@ private:
StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemHeader) const;

View File

@ -382,7 +382,8 @@ public:
const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule, bool SkipCache = false);
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
/// \brief Look up a subframework for the specified \#include file.
///
@ -391,11 +392,9 @@ public:
/// HIToolbox is a subframework within Carbon.framework. If so, return
/// the FileEntry for the designated file, otherwise return null.
const FileEntry *LookupSubframeworkHeader(
StringRef Filename,
const FileEntry *RelativeFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule);
StringRef Filename, const FileEntry *RelativeFileEnt,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
/// \brief Look up the specified framework name in our framework cache.
/// \returns The DirectoryEntry it is in if we know, null otherwise.
@ -561,6 +560,32 @@ private:
/// of the given search directory.
void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
/// \brief Find and suggest a usable module for the given file.
///
/// \return \c true if the file can be used, \c false if we are not permitted to
/// find this file due to requirements from \p RequestingModule.
bool findUsableModuleForHeader(const FileEntry *File,
const DirectoryEntry *Root,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool IsSystemHeaderDir);
/// \brief Find and suggest a usable module for the given file, which is part of
/// the specified framework.
///
/// \return \c true if the file can be used, \c false if we are not permitted to
/// find this file due to requirements from \p RequestingModule.
bool findUsableModuleForFrameworkHeader(
const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
/// \brief Look up the file with the specified name and determine its owning
/// module.
const FileEntry *
getFileAndSuggestModule(StringRef FileName, const DirectoryEntry *Dir,
bool IsSystemHeaderDir, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule);
public:
/// \brief Retrieve the module map.
ModuleMap &getModuleMap() { return ModMap; }

View File

@ -389,9 +389,10 @@ bool InclusionRewriter::HandleHasInclude(
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1>
Includers;
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
// FIXME: Why don't we call PP.LookupFile here?
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
nullptr, nullptr, false);
nullptr, nullptr, nullptr, false);
FileExists = File != nullptr;
return true;

View File

@ -250,31 +250,20 @@ const char *DirectoryLookup::getName() const {
return getHeaderMap()->getFileName();
}
static const FileEntry *
getFileAndSuggestModule(HeaderSearch &HS, StringRef FileName,
const DirectoryEntry *Dir, bool IsSystemHeaderDir,
ModuleMap::KnownHeader *SuggestedModule) {
const FileEntry *HeaderSearch::getFileAndSuggestModule(
StringRef FileName, const DirectoryEntry *Dir, bool IsSystemHeaderDir,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
// If we have a module map that might map this header, load it and
// check whether we'll have a suggestion for a module.
HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir);
if (SuggestedModule) {
const FileEntry *File = HS.getFileMgr().getFile(FileName,
/*OpenFile=*/false);
if (File) {
// If there is a module that corresponds to this header, suggest it.
*SuggestedModule = HS.findModuleForHeader(File);
const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true);
// FIXME: This appears to be a no-op. We loaded the module map for this
// directory at the start of this function.
if (!SuggestedModule->getModule() &&
HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir))
*SuggestedModule = HS.findModuleForHeader(File);
}
// If there is a module that corresponds to this header, suggest it.
if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(),
RequestingModule, SuggestedModule,
IsSystemHeaderDir))
return nullptr;
return File;
}
return HS.getFileMgr().getFile(FileName, /*openFile=*/true);
return File;
}
/// LookupFile - Lookup the specified file in this search path, returning it
@ -284,6 +273,7 @@ const FileEntry *DirectoryLookup::LookupFile(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework,
bool &HasBeenMapped,
@ -306,14 +296,15 @@ const FileEntry *DirectoryLookup::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
return getFileAndSuggestModule(HS, TmpDir, getDir(),
isSystemHeaderDirectory(),
SuggestedModule);
return HS.getFileAndSuggestModule(TmpDir, getDir(),
isSystemHeaderDirectory(),
RequestingModule, SuggestedModule);
}
if (isFramework())
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
SuggestedModule, InUserSpecifiedSystemFramework);
RequestingModule, SuggestedModule,
InUserSpecifiedSystemFramework);
assert(isHeaderMap() && "Unknown directory lookup");
const HeaderMap *HM = getHeaderMap();
@ -405,13 +396,10 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
StringRef Filename,
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const
{
bool &InUserSpecifiedSystemFramework) const {
FileManager &FileMgr = HS.getFileMgr();
// Framework names must have a '/' in the filename.
@ -523,27 +511,15 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
break;
} while (true);
bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
if (FoundFramework) {
// Find the top-level framework based on this framework.
SmallVector<std::string, 4> SubmodulePath;
const DirectoryEntry *TopFrameworkDir
= ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath);
// Determine the name of the top-level framework.
StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
// Load this framework module. If that succeeds, find the suggested module
// for this header, if any.
bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem);
// FIXME: This can find a module not part of ModuleName, which is
// important so that we're consistent about whether this header
// corresponds to a module. Possibly we should lock down framework modules
// so that this is not possible.
*SuggestedModule = HS.findModuleForHeader(FE);
if (!HS.findUsableModuleForFrameworkHeader(
FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem))
return nullptr;
} else {
*SuggestedModule = HS.findModuleForHeader(FE);
if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule,
SuggestedModule, IsSystem))
return nullptr;
}
}
return FE;
@ -589,7 +565,8 @@ const FileEntry *HeaderSearch::LookupFile(
const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
@ -607,13 +584,9 @@ const FileEntry *HeaderSearch::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
// Otherwise, just return the file.
const FileEntry *File = FileMgr.getFile(Filename, /*openFile=*/true);
if (File && SuggestedModule) {
// If there is a module that corresponds to this header, suggest it.
hasModuleMap(Filename, File->getDir(), /*SystemHeaderDir*/false);
*SuggestedModule = findModuleForHeader(File);
}
return File;
return getFileAndSuggestModule(Filename, nullptr,
/*IsSystemHeaderDir*/false,
RequestingModule, SuggestedModule);
}
// This is the header that MSVC's header search would have found.
@ -647,8 +620,8 @@ const FileEntry *HeaderSearch::LookupFile(
bool IncluderIsSystemHeader =
Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
if (const FileEntry *FE = getFileAndSuggestModule(
*this, TmpDir, IncluderAndDir.second,
IncluderIsSystemHeader, SuggestedModule)) {
TmpDir, IncluderAndDir.second, IncluderIsSystemHeader,
RequestingModule, SuggestedModule)) {
if (!Includer) {
assert(First && "only first includer can have no file");
return FE;
@ -737,10 +710,10 @@ const FileEntry *HeaderSearch::LookupFile(
for (; i != SearchDirs.size(); ++i) {
bool InUserSpecifiedSystemFramework = false;
bool HasBeenMapped = false;
const FileEntry *FE =
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
SuggestedModule, InUserSpecifiedSystemFramework,
HasBeenMapped, MappedName);
const FileEntry *FE = SearchDirs[i].LookupFile(
Filename, *this, SearchPath, RelativePath, RequestingModule,
SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped,
MappedName);
if (HasBeenMapped) {
CacheLookup.MappedName =
copyString(Filename, LookupFileCache.getAllocator());
@ -804,9 +777,10 @@ const FileEntry *HeaderSearch::LookupFile(
ScratchFilename += '/';
ScratchFilename += Filename;
const FileEntry *FE = LookupFile(
ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
Includers.front(), SearchPath, RelativePath, SuggestedModule);
const FileEntry *FE =
LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir,
CurDir, Includers.front(), SearchPath, RelativePath,
RequestingModule, SuggestedModule);
if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
if (SuggestedModule)
@ -842,6 +816,7 @@ LookupSubframeworkHeader(StringRef Filename,
const FileEntry *ContextFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule) {
assert(ContextFileEnt && "No context file?");
@ -933,24 +908,10 @@ LookupSubframeworkHeader(StringRef Filename,
unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
getFileInfo(FE).DirInfo = DirInfo;
// If we're supposed to suggest a module, look for one now.
if (SuggestedModule) {
// Find the top-level framework based on this framework.
FrameworkName.pop_back(); // remove the trailing '/'
SmallVector<std::string, 4> SubmodulePath;
const DirectoryEntry *TopFrameworkDir
= ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
// Determine the name of the top-level framework.
StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
// Load this framework module. If that succeeds, find the suggested module
// for this header, if any.
bool IsSystem = false;
if (loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
*SuggestedModule = findModuleForHeader(FE);
}
}
FrameworkName.pop_back(); // remove the trailing '/'
if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule,
SuggestedModule, /*IsSystem*/ false))
return nullptr;
return FE;
}
@ -1183,6 +1144,43 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const {
return ModMap.findModuleForHeader(File);
}
bool HeaderSearch::findUsableModuleForHeader(
const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
if (File && SuggestedModule) {
// If there is a module that corresponds to this header, suggest it.
hasModuleMap(File->getName(), Root, IsSystemHeaderDir);
*SuggestedModule = findModuleForHeader(File);
}
return true;
}
bool HeaderSearch::findUsableModuleForFrameworkHeader(
const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
// If we're supposed to suggest a module, look for one now.
if (SuggestedModule) {
// Find the top-level framework based on this framework.
SmallVector<std::string, 4> SubmodulePath;
const DirectoryEntry *TopFrameworkDir
= ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
// Determine the name of the top-level framework.
StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
// Load this framework module. If that succeeds, find the suggested module
// for this header, if any.
loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework);
// FIXME: This can find a module not part of ModuleName, which is
// important so that we're consistent about whether this header
// corresponds to a module. Possibly we should lock down framework modules
// so that this is not possible.
*SuggestedModule = findModuleForHeader(File);
}
return true;
}
static const FileEntry *getPrivateModuleMap(const FileEntry *File,
FileManager &FileMgr) {
StringRef Filename = llvm::sys::path::filename(File->getName());

View File

@ -611,6 +611,8 @@ const FileEntry *Preprocessor::LookupFile(
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
Module *RequestingModule = getModuleForLocation(FilenameLoc);
// If the header lookup mechanism may be relative to the current inclusion
// stack, record the parent #includes.
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
@ -664,8 +666,8 @@ const FileEntry *Preprocessor::LookupFile(
const DirectoryLookup *TmpFromDir = nullptr;
while (const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
Includers, SearchPath, RelativePath, SuggestedModule,
SkipCache)) {
Includers, SearchPath, RelativePath, RequestingModule,
SuggestedModule, SkipCache)) {
// Keep looking as if this file did a #include_next.
TmpFromDir = TmpCurDir;
++TmpFromDir;
@ -681,11 +683,11 @@ const FileEntry *Preprocessor::LookupFile(
// Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
RelativePath, SuggestedModule, SkipCache);
RelativePath, RequestingModule, SuggestedModule, SkipCache);
if (FE) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
@ -697,10 +699,11 @@ const FileEntry *Preprocessor::LookupFile(
if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
SearchPath, RelativePath,
RequestingModule,
SuggestedModule))) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
}
@ -713,10 +716,10 @@ const FileEntry *Preprocessor::LookupFile(
SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(
Filename, CurFileEnt, SearchPath, RelativePath,
SuggestedModule))) {
RequestingModule, SuggestedModule))) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
}