summaryrefslogtreecommitdiff
path: root/lib/Lex/HeaderSearch.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Lex/HeaderSearch.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Notes
Diffstat (limited to 'lib/Lex/HeaderSearch.cpp')
-rw-r--r--lib/Lex/HeaderSearch.cpp111
1 files changed, 69 insertions, 42 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index c65fb47c0fe5..108630cc26f6 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -1,9 +1,8 @@
//===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -335,6 +334,7 @@ const FileEntry *DirectoryLookup::LookupFile(
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework,
+ bool &IsFrameworkFound,
bool &HasBeenMapped,
SmallVectorImpl<char> &MappedName) const {
InUserSpecifiedSystemFramework = false;
@@ -363,7 +363,7 @@ const FileEntry *DirectoryLookup::LookupFile(
if (isFramework())
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
RequestingModule, SuggestedModule,
- InUserSpecifiedSystemFramework);
+ InUserSpecifiedSystemFramework, IsFrameworkFound);
assert(isHeaderMap() && "Unknown directory lookup");
const HeaderMap *HM = getHeaderMap();
@@ -463,7 +463,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework) const {
+ bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
FileManager &FileMgr = HS.getFileMgr();
// Framework names must have a '/' in the filename.
@@ -472,7 +472,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// Find out if this is the home for the specified framework, by checking
// HeaderSearch. Possible answers are yes/no and unknown.
- HeaderSearch::FrameworkCacheEntry &CacheEntry =
+ FrameworkCacheEntry &CacheEntry =
HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
// If it is known and in some other directory, fail.
@@ -517,8 +517,9 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
}
}
- // Set the 'user-specified system framework' flag.
+ // Set out flags.
InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
+ IsFrameworkFound = CacheEntry.Directory;
if (RelativePath) {
RelativePath->clear();
@@ -538,7 +539,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
const FileEntry *FE = FileMgr.getFile(FrameworkName,
- /*openFile=*/!SuggestedModule);
+ /*OpenFile=*/!SuggestedModule);
if (!FE) {
// Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
const char *Private = "Private";
@@ -548,7 +549,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
Private+strlen(Private));
- FE = FileMgr.getFile(FrameworkName, /*openFile=*/!SuggestedModule);
+ FE = FileMgr.getFile(FrameworkName, /*OpenFile=*/!SuggestedModule);
}
// If we found the header and are allowed to suggest a module, do so now.
@@ -697,10 +698,14 @@ const FileEntry *HeaderSearch::LookupFile(
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
- bool *IsMapped, bool SkipCache, bool BuildSystemModule) {
+ bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
+ bool BuildSystemModule) {
if (IsMapped)
*IsMapped = false;
+ if (IsFrameworkFound)
+ *IsFrameworkFound = false;
+
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
@@ -852,16 +857,22 @@ const FileEntry *HeaderSearch::LookupFile(
for (; i != SearchDirs.size(); ++i) {
bool InUserSpecifiedSystemFramework = false;
bool HasBeenMapped = false;
+ bool IsFrameworkFoundInDir = false;
const FileEntry *FE = SearchDirs[i].LookupFile(
Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
- SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped,
- MappedName);
+ SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
+ HasBeenMapped, MappedName);
if (HasBeenMapped) {
CacheLookup.MappedName =
copyString(Filename, LookupFileCache.getAllocator());
if (IsMapped)
*IsMapped = true;
}
+ if (IsFrameworkFound)
+ // Because we keep a filename remapped for subsequent search directory
+ // lookups, ignore IsFrameworkFoundInDir after the first remapping and not
+ // just for remapping in a current search directory.
+ *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
if (!FE) continue;
CurDir = &SearchDirs[i];
@@ -927,10 +938,10 @@ const FileEntry *HeaderSearch::LookupFile(
ScratchFilename += '/';
ScratchFilename += Filename;
- const FileEntry *FE =
- LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir,
- CurDir, Includers.front(), SearchPath, RelativePath,
- RequestingModule, SuggestedModule, IsMapped);
+ const FileEntry *FE = LookupFile(
+ ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
+ Includers.front(), SearchPath, RelativePath, RequestingModule,
+ SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr);
if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
if (SuggestedModule)
@@ -1036,7 +1047,7 @@ LookupSubframeworkHeader(StringRef Filename,
}
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
- if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true))) {
+ if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) {
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
HeadersFilename += "PrivateHeaders/";
@@ -1047,7 +1058,7 @@ LookupSubframeworkHeader(StringRef Filename,
}
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
- if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true)))
+ if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true)))
return nullptr;
}
@@ -1571,7 +1582,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
DirNative);
// Search each of the ".framework" directories to load them as modules.
- llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
@@ -1642,7 +1653,7 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
FileMgr.makeAbsolutePath(Dir);
SmallString<128> DirNative;
llvm::sys::path::native(Dir, DirNative);
- llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
@@ -1654,34 +1665,30 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
SearchDir.setSearchedAllModuleMaps(true);
}
-std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
- bool *IsSystem) {
+std::string HeaderSearch::suggestPathToFileForDiagnostics(
+ const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) {
// FIXME: We assume that the path name currently cached in the FileEntry is
// the most appropriate one for this analysis (and that it's spelled the
// same way as the corresponding header search path).
- return suggestPathToFileForDiagnostics(File->getName(), /*BuildDir=*/"",
- IsSystem);
+ return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"",
+ MainFile, IsSystem);
}
std::string HeaderSearch::suggestPathToFileForDiagnostics(
- llvm::StringRef File, llvm::StringRef WorkingDir, bool *IsSystem) {
+ llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
+ bool *IsSystem) {
using namespace llvm::sys;
unsigned BestPrefixLength = 0;
- unsigned BestSearchDir;
-
- for (unsigned I = 0; I != SearchDirs.size(); ++I) {
- // FIXME: Support this search within frameworks and header maps.
- if (!SearchDirs[I].isNormalDir())
- continue;
-
- StringRef Dir = SearchDirs[I].getDir()->getName();
+ // Checks whether Dir and File shares a common prefix, if they do and that's
+ // the longest prefix we've seen so for it returns true and updates the
+ // BestPrefixLength accordingly.
+ auto CheckDir = [&](llvm::StringRef Dir) -> bool {
llvm::SmallString<32> DirPath(Dir.begin(), Dir.end());
- if (!WorkingDir.empty() && !path::is_absolute(Dir)) {
+ if (!WorkingDir.empty() && !path::is_absolute(Dir))
fs::make_absolute(WorkingDir, DirPath);
- path::remove_dots(DirPath, /*remove_dot_dot=*/true);
- Dir = DirPath;
- }
+ path::remove_dots(DirPath, /*remove_dot_dot=*/true);
+ Dir = DirPath;
for (auto NI = path::begin(File), NE = path::end(File),
DI = path::begin(Dir), DE = path::end(Dir);
/*termination condition in loop*/; ++NI, ++DI) {
@@ -1700,17 +1707,37 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
unsigned PrefixLength = NI - path::begin(File);
if (PrefixLength > BestPrefixLength) {
BestPrefixLength = PrefixLength;
- BestSearchDir = I;
+ return true;
}
break;
}
+ // Consider all path separators equal.
+ if (NI->size() == 1 && DI->size() == 1 &&
+ path::is_separator(NI->front()) && path::is_separator(DI->front()))
+ continue;
+
if (*NI != *DI)
break;
}
+ return false;
+ };
+
+ for (unsigned I = 0; I != SearchDirs.size(); ++I) {
+ // FIXME: Support this search within frameworks and header maps.
+ if (!SearchDirs[I].isNormalDir())
+ continue;
+
+ StringRef Dir = SearchDirs[I].getDir()->getName();
+ if (CheckDir(Dir) && IsSystem)
+ *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
}
- if (IsSystem)
- *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false;
- return File.drop_front(BestPrefixLength);
+ // Try to shorten include path using TUs directory, if we couldn't find any
+ // suitable prefix in include search paths.
+ if (!BestPrefixLength && CheckDir(path::parent_path(MainFile)) && IsSystem)
+ *IsSystem = false;
+
+
+ return path::convert_to_slash(File.drop_front(BestPrefixLength));
}