diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-01-27 22:06:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-01-27 22:06:42 +0000 |
commit | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (patch) | |
tree | a1fd89b864d9b93e2ad68fe1dcf7afee2e3c8d76 /clang/lib/Lex/HeaderSearch.cpp | |
parent | 77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (diff) | |
download | src-6f8fc217eaa12bf657be1c6468ed9938d10168b3.tar.gz src-6f8fc217eaa12bf657be1c6468ed9938d10168b3.zip |
Diffstat (limited to 'clang/lib/Lex/HeaderSearch.cpp')
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 156 |
1 files changed, 108 insertions, 48 deletions
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index a0b60118a1a8..39c125c395ef 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -29,6 +29,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/Errc.h" @@ -89,16 +90,10 @@ HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, void HeaderSearch::PrintStats() { llvm::errs() << "\n*** HeaderSearch Stats:\n" << FileInfo.size() << " files tracked.\n"; - unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; - for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { + unsigned NumOnceOnlyFiles = 0; + for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport); - if (MaxNumIncludes < FileInfo[i].NumIncludes) - MaxNumIncludes = FileInfo[i].NumIncludes; - NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; - } - llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n" - << " " << NumSingleIncludedFiles << " included exactly once.\n" - << " " << MaxNumIncludes << " max times a file is included.\n"; + llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n"; llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n" << " " << NumMultiIncludeFileOptzn @@ -108,6 +103,30 @@ void HeaderSearch::PrintStats() { << NumSubFrameworkLookups << " subframework lookups.\n"; } +void HeaderSearch::SetSearchPaths( + std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx, + unsigned int systemDirIdx, bool noCurDirSearch, + llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) { + assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() && + "Directory indices are unordered"); + SearchDirs = std::move(dirs); + SearchDirsUsage.assign(SearchDirs.size(), false); + AngledDirIdx = angledDirIdx; + SystemDirIdx = systemDirIdx; + NoCurDirSearch = noCurDirSearch; + SearchDirToHSEntry = std::move(searchDirToHSEntry); + //LookupFileCache.clear(); +} + +void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) { + unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; + SearchDirs.insert(SearchDirs.begin() + idx, dir); + SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false); + if (!isAngled) + AngledDirIdx++; + SystemDirIdx++; +} + std::vector<bool> HeaderSearch::computeUserEntryUsage() const { std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size()); for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) { @@ -720,7 +739,8 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { } static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, - SmallVectorImpl<char> &FrameworkName) { + SmallVectorImpl<char> &FrameworkName, + SmallVectorImpl<char> &IncludeSpelling) { using namespace llvm::sys; path::const_iterator I = path::begin(Path); path::const_iterator E = path::end(Path); @@ -736,15 +756,22 @@ static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, // and some other variations among these lines. int FoundComp = 0; while (I != E) { - if (*I == "Headers") + if (*I == "Headers") { ++FoundComp; - if (I->endswith(".framework")) { - FrameworkName.append(I->begin(), I->end()); - ++FoundComp; - } - if (*I == "PrivateHeaders") { + } else if (*I == "PrivateHeaders") { ++FoundComp; IsPrivateHeader = true; + } else if (I->endswith(".framework")) { + StringRef Name = I->drop_back(10); // Drop .framework + // Need to reset the strings and counter to support nested frameworks. + FrameworkName.clear(); + FrameworkName.append(Name.begin(), Name.end()); + IncludeSpelling.clear(); + IncludeSpelling.append(Name.begin(), Name.end()); + FoundComp = 1; + } else if (FoundComp >= 2) { + IncludeSpelling.push_back('/'); + IncludeSpelling.append(I->begin(), I->end()); } ++I; } @@ -759,20 +786,24 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, bool FoundByHeaderMap = false) { bool IsIncluderPrivateHeader = false; SmallString<128> FromFramework, ToFramework; - if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework)) + SmallString<128> FromIncludeSpelling, ToIncludeSpelling; + if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework, + FromIncludeSpelling)) return; bool IsIncludeePrivateHeader = false; - bool IsIncludeeInFramework = isFrameworkStylePath( - IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework); + bool IsIncludeeInFramework = + isFrameworkStylePath(IncludeFE->getName(), IsIncludeePrivateHeader, + ToFramework, ToIncludeSpelling); if (!isAngled && !FoundByHeaderMap) { SmallString<128> NewInclude("<"); if (IsIncludeeInFramework) { - NewInclude += ToFramework.str().drop_back(10); // drop .framework - NewInclude += "/"; + NewInclude += ToIncludeSpelling; + NewInclude += ">"; + } else { + NewInclude += IncludeFilename; + NewInclude += ">"; } - NewInclude += IncludeFilename; - NewInclude += ">"; Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) << IncludeFilename << FixItHint::CreateReplacement(IncludeLoc, NewInclude); @@ -794,12 +825,15 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, /// search is needed. Microsoft mode will pass all \#including files. Optional<FileEntryRef> HeaderSearch::LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, - const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, + const DirectoryLookup *FromDir, const DirectoryLookup **CurDirArg, ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, bool BuildSystemModule) { + const DirectoryLookup *CurDirLocal = nullptr; + const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal; + if (IsMapped) *IsMapped = false; @@ -1046,7 +1080,7 @@ Optional<FileEntryRef> HeaderSearch::LookupFile( ScratchFilename += Filename; Optional<FileEntryRef> File = LookupFile( - ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, + ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir, Includers.front(), SearchPath, RelativePath, RequestingModule, SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); @@ -1203,7 +1237,6 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI, HFI.isImport |= OtherHFI.isImport; HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; HFI.isModuleHeader |= OtherHFI.isModuleHeader; - HFI.NumIncludes += OtherHFI.NumIncludes; if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { HFI.ControllingMacro = OtherHFI.ControllingMacro; @@ -1364,7 +1397,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, FileInfo.isImport = true; // Has this already been #import'ed or #include'd? - if (FileInfo.NumIncludes && !TryEnterImported()) + if (PP.alreadyIncluded(File) && !TryEnterImported()) return false; } else { // Otherwise, if this is a #include of a file that was previously #import'd @@ -1387,10 +1420,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, } } - // Increment the number of times this file has been included. - ++FileInfo.NumIncludes; - - IsFirstIncludeOfFile = FileInfo.NumIncludes == 1; + IsFirstIncludeOfFile = PP.markIncluded(File); return true; } @@ -1779,11 +1809,8 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { } // Populate the list of modules. - for (ModuleMap::module_iterator M = ModMap.module_begin(), - MEnd = ModMap.module_end(); - M != MEnd; ++M) { - Modules.push_back(M->getValue()); - } + llvm::transform(ModMap.modules(), std::back_inserter(Modules), + [](const auto &NameAndMod) { return NameAndMod.second; }); } void HeaderSearch::loadTopLevelSystemModules() { @@ -1843,9 +1870,9 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( using namespace llvm::sys; unsigned BestPrefixLength = 0; - // 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. + // Checks whether `Dir` is a strict path prefix of `File`. If so 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)) @@ -1880,26 +1907,48 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( path::is_separator(NI->front()) && path::is_separator(DI->front())) continue; + // Special case Apple .sdk folders since the search path is typically a + // symlink like `iPhoneSimulator14.5.sdk` while the file is instead + // located in `iPhoneSimulator.sdk` (the real folder). + if (NI->endswith(".sdk") && DI->endswith(".sdk")) { + StringRef NBasename = path::stem(*NI); + StringRef DBasename = path::stem(*DI); + if (DBasename.startswith(NBasename)) + continue; + } + if (*NI != *DI) break; } return false; }; + bool BestPrefixIsFramework = false; for (unsigned I = 0; I != SearchDirs.size(); ++I) { - // FIXME: Support this search within frameworks. - if (!SearchDirs[I].isNormalDir()) - continue; - - StringRef Dir = SearchDirs[I].getDir()->getName(); - if (CheckDir(Dir) && IsSystem) - *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false; + if (SearchDirs[I].isNormalDir()) { + StringRef Dir = SearchDirs[I].getDir()->getName(); + if (CheckDir(Dir)) { + if (IsSystem) + *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false; + BestPrefixIsFramework = false; + } + } else if (SearchDirs[I].isFramework()) { + StringRef Dir = SearchDirs[I].getFrameworkDir()->getName(); + if (CheckDir(Dir)) { + if (IsSystem) + *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false; + BestPrefixIsFramework = true; + } + } } // 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; + if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) { + if (IsSystem) + *IsSystem = false; + BestPrefixIsFramework = false; + } // Try resolving resulting filename via reverse search in header maps, // key from header name is user prefered name for the include file. @@ -1912,8 +1961,19 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( SearchDirs[I].getHeaderMap()->reverseLookupFilename(Filename); if (!SpelledFilename.empty()) { Filename = SpelledFilename; + BestPrefixIsFramework = false; break; } } + + // If the best prefix is a framework path, we need to compute the proper + // include spelling for the framework header. + bool IsPrivateHeader; + SmallString<128> FrameworkName, IncludeSpelling; + if (BestPrefixIsFramework && + isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName, + IncludeSpelling)) { + Filename = IncludeSpelling; + } return path::convert_to_slash(Filename); } |