diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Lex/HeaderSearch.cpp | |
parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) |
Notes
Diffstat (limited to 'lib/Lex/HeaderSearch.cpp')
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 111 |
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)); } |