diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 |
commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp | |
parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp | 281 |
1 files changed, 155 insertions, 126 deletions
diff --git a/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp index ee2cca4e0814..5a1b0a918caa 100644 --- a/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp +++ b/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp @@ -181,7 +181,7 @@ OptionalFileEntryRef ModuleMap::findHeader( Module *M, const Module::UnresolvedHeaderDirective &Header, SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) { // Search for the header file within the module's home directory. - auto *Directory = M->Directory; + auto Directory = M->Directory; SmallString<128> FullPathName(Directory->getName()); auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef { @@ -266,7 +266,8 @@ void ModuleMap::resolveHeader(Module *Mod, << UmbrellaMod->getFullModuleName(); else // Record this umbrella header. - setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str()); + setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName, + RelativePathName.str()); } else { Module::Header H = {Header.FileName, std::string(RelativePathName.str()), *File}; @@ -408,29 +409,27 @@ ModuleMap::findKnownHeader(const FileEntry *File) { return Known; } -ModuleMap::KnownHeader -ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, - SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { +ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs( + FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) { if (UmbrellaDirs.empty()) return {}; - const DirectoryEntry *Dir = File->getDir(); - assert(Dir && "file in no directory"); + OptionalDirectoryEntryRef Dir = File.getDir(); // 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); + 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); + auto KnownDir = UmbrellaDirs.find(*Dir); if (KnownDir != UmbrellaDirs.end()) return KnownHeader(KnownDir->second, NormalHeader); - IntermediateDirs.push_back(Dir); + IntermediateDirs.push_back(*Dir); // Retrieve our parent path. DirName = llvm::sys::path::parent_path(DirName); @@ -438,10 +437,7 @@ ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, break; // Resolve the parent path to a directory entry. - if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) - Dir = *DirEntry; - else - Dir = nullptr; + Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName); } while (Dir); return {}; } @@ -528,8 +524,9 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, // We have found a module, but we don't use it. if (NotUsed) { - Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) - << RequestingModule->getTopLevelModule()->Name << Filename; + Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect) + << RequestingModule->getTopLevelModule()->Name << Filename + << NotUsed->Name; return; } @@ -580,7 +577,7 @@ static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, return false; } -ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, +ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File, bool AllowTextual, bool AllowExcluded) { auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { @@ -610,10 +607,10 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, } ModuleMap::KnownHeader -ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { +ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) { assert(!Headers.count(File) && "already have a module for this header"); - SmallVector<const DirectoryEntry *, 2> SkippedDirs; + SmallVector<DirectoryEntryRef, 2> SkippedDirs; KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); if (H) { Module *Result = H.getModule(); @@ -621,7 +618,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { // Search up the module stack until we find a module with an umbrella // directory. Module *UmbrellaModule = Result; - while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) + while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent) UmbrellaModule = UmbrellaModule->Parent; if (UmbrellaModule->InferSubmodules) { @@ -633,11 +630,11 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { // the actual header is located. bool Explicit = UmbrellaModule->InferExplicitSubmodules; - for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { + for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) { // Find or create the module that corresponds to this directory name. SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( - llvm::sys::path::stem(SkippedDir->getName()), NameBuf); + llvm::sys::path::stem(SkippedDir.getName()), NameBuf); Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Explicit).first; InferredModuleAllowedBy[Result] = UmbrellaModuleMap; @@ -655,7 +652,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { // Infer a submodule with the same name as this header file. SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( - llvm::sys::path::stem(File->getName()), NameBuf); + llvm::sys::path::stem(File.getName()), NameBuf); Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Explicit).first; InferredModuleAllowedBy[Result] = UmbrellaModuleMap; @@ -682,7 +679,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { } ArrayRef<ModuleMap::KnownHeader> -ModuleMap::findAllModulesForHeader(const FileEntry *File) { +ModuleMap::findAllModulesForHeader(FileEntryRef File) { HeadersMap::iterator Known = findKnownHeader(File); if (Known != Headers.end()) return Known->second; @@ -703,13 +700,12 @@ ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const { return It->second; } -bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { +bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const { return isHeaderUnavailableInModule(Header, nullptr); } -bool -ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, - const Module *RequestingModule) const { +bool ModuleMap::isHeaderUnavailableInModule( + FileEntryRef Header, const Module *RequestingModule) const { resolveHeaderDirectives(Header); HeadersMap::const_iterator Known = Headers.find(Header); if (Known != Headers.end()) { @@ -737,8 +733,8 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, return true; } - const DirectoryEntry *Dir = Header->getDir(); - SmallVector<const DirectoryEntry *, 2> SkippedDirs; + OptionalDirectoryEntryRef Dir = Header.getDir(); + SmallVector<DirectoryEntryRef, 2> SkippedDirs; StringRef DirName = Dir->getName(); auto IsUnavailable = [&](const Module *M) { @@ -749,8 +745,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, // Keep walking up the directory hierarchy, looking for a directory with // an umbrella header. do { - llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir - = UmbrellaDirs.find(Dir); + auto KnownDir = UmbrellaDirs.find(*Dir); if (KnownDir != UmbrellaDirs.end()) { Module *Found = KnownDir->second; if (IsUnavailable(Found)) @@ -759,15 +754,16 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, // Search up the module stack until we find a module with an umbrella // directory. Module *UmbrellaModule = Found; - while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) + while (!UmbrellaModule->getEffectiveUmbrellaDir() && + UmbrellaModule->Parent) UmbrellaModule = UmbrellaModule->Parent; if (UmbrellaModule->InferSubmodules) { - for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { + for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) { // Find or create the module that corresponds to this directory name. SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( - llvm::sys::path::stem(SkippedDir->getName()), NameBuf); + llvm::sys::path::stem(SkippedDir.getName()), NameBuf); Found = lookupModuleQualified(Name, Found); if (!Found) return false; @@ -778,7 +774,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, // Infer a submodule with the same name as this header file. SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( - llvm::sys::path::stem(Header->getName()), + llvm::sys::path::stem(Header.getName()), NameBuf); Found = lookupModuleQualified(Name, Found); if (!Found) @@ -788,7 +784,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, return IsUnavailable(Found); } - SkippedDirs.push_back(Dir); + SkippedDirs.push_back(*Dir); // Retrieve our parent path. DirName = llvm::sys::path::parent_path(DirName); @@ -796,10 +792,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, break; // Resolve the parent path to a directory entry. - if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) - Dir = *DirEntry; - else - Dir = nullptr; + Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName); } while (Dir); return false; @@ -854,7 +847,7 @@ Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent) { auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false, /*IsExplicit*/ true, NumCreatedModules++); - Result->Kind = Module::GlobalModuleFragment; + Result->Kind = Module::ExplicitGlobalModuleFragment; // If the created module isn't owned by a parent, send it to PendingSubmodules // to wait for its parent. if (!Result->Parent) @@ -862,6 +855,21 @@ Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, return Result; } +Module *ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit( + SourceLocation Loc, bool IsExported, Module *Parent) { + assert(Parent && "We should only create an implicit global module fragment " + "in a module purview"); + // Note: Here the `IsExplicit` parameter refers to the semantics in clang + // modules. All the non-explicit submodules in clang modules will be exported + // too. Here we simplify the implementation by using the concept. + auto *Result = new Module(IsExported ? "<exported implicit global>" + : "<implicit global>", + Loc, Parent, /*IsFramework*/ false, + /*IsExplicit*/ !IsExported, NumCreatedModules++); + Result->Kind = Module::ImplicitGlobalModuleFragment; + return Result; +} + Module * ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, SourceLocation Loc) { @@ -872,23 +880,30 @@ ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, return Result; } -Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, - StringRef Name) { - assert(LangOpts.CurrentModule == Name && "module name mismatch"); - assert(!Modules[Name] && "redefining existing module"); - +Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name, + Module::ModuleKind Kind) { auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false, /*IsExplicit*/ false, NumCreatedModules++); - Result->Kind = Module::ModuleInterfaceUnit; - Modules[Name] = SourceModule = Result; + Result->Kind = Kind; - // Reparent the current global module fragment as a submodule of this module. + // Reparent any current global module fragment as a submodule of this module. for (auto &Submodule : PendingSubmodules) { Submodule->setParent(Result); Submodule.release(); // now owned by parent } PendingSubmodules.clear(); + return Result; +} + +Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, + StringRef Name) { + assert(LangOpts.CurrentModule == Name && "module name mismatch"); + assert(!Modules[Name] && "redefining existing module"); + + auto *Result = + createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit); + Modules[Name] = SourceModule = Result; // Mark the main source file as being within the newly-created module so that // declarations and macros are properly visibility-restricted to it. @@ -899,6 +914,30 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, return Result; } +Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc, + StringRef Name) { + assert(LangOpts.CurrentModule == Name && "module name mismatch"); + // The interface for this implementation must exist and be loaded. + assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit && + "creating implementation module without an interface"); + + // Create an entry in the modules map to own the implementation unit module. + // User module names must not start with a period (so that this cannot clash + // with any legal user-defined module name). + StringRef IName = ".ImplementationUnit"; + assert(!Modules[IName] && "multiple implementation units?"); + + auto *Result = + createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit); + Modules[IName] = SourceModule = Result; + + // Check that the main file is present. + assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) && + "no input file for module implementation"); + + return Result; +} + Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name, Module::Header H) { assert(LangOpts.CurrentModule == Name && "module name mismatch"); @@ -914,37 +953,23 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name, /// For a framework module, infer the framework against which we /// should link. -static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, - FileManager &FileMgr) { +static void inferFrameworkLink(Module *Mod) { assert(Mod->IsFramework && "Can only infer linking for framework modules"); assert(!Mod->isSubFramework() && "Can only infer linking for top-level frameworks"); - SmallString<128> LibName; - LibName += FrameworkDir->getName(); - llvm::sys::path::append(LibName, Mod->Name); - - // The library name of a framework has more than one possible extension since - // the introduction of the text-based dynamic library format. We need to check - // for both before we give up. - for (const char *extension : {"", ".tbd"}) { - llvm::sys::path::replace_extension(LibName, extension); - if (FileMgr.getFile(LibName)) { - Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, - /*IsFramework=*/true)); - return; - } - } + Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, + /*IsFramework=*/true)); } -Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, +Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, bool IsSystem, Module *Parent) { Attributes Attrs; Attrs.IsSystem = IsSystem; return inferFrameworkModule(FrameworkDir, Attrs, Parent); } -Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, +Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, Attributes Attrs, Module *Parent) { // Note: as an egregious but useful hack we use the real path here, because // we might be looking at an embedded framework that symlinks out to a @@ -975,7 +1000,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (llvm::sys::path::has_parent_path(FrameworkDirName)) { // Figure out the parent path. StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); - if (auto ParentDir = FileMgr.getDirectory(Parent)) { + if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) { // Check whether we have already looked into the parent directory // for a module map. llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator @@ -984,9 +1009,9 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // We haven't looked here before. Load a module map, if there is // one. bool IsFrameworkDir = Parent.endswith(".framework"); - if (const FileEntry *ModMapFile = - HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { - parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); + if (OptionalFileEntryRef ModMapFile = + HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { + parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir); inferred = InferredDirectories.find(*ParentDir); } @@ -1022,7 +1047,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, } // Look for an umbrella header. - SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); + SmallString<128> UmbrellaName = FrameworkDir.getName(); llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName); @@ -1056,7 +1081,8 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, RelativePath = llvm::sys::path::relative_path(RelativePath); // umbrella header "umbrella-header-name" - setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath); + setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h", + RelativePath); // export * Result->Exports.push_back(Module::ExportDecl(nullptr, true)); @@ -1067,8 +1093,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // Look for subframeworks. std::error_code EC; - SmallString<128> SubframeworksDirName - = StringRef(FrameworkDir->getName()); + SmallString<128> SubframeworksDirName = FrameworkDir.getName(); llvm::sys::path::append(SubframeworksDirName, "Frameworks"); llvm::sys::path::native(SubframeworksDirName); llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); @@ -1079,8 +1104,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (!StringRef(Dir->path()).endswith(".framework")) continue; - if (auto SubframeworkDir = - FileMgr.getDirectory(Dir->path())) { + if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) { // Note: as an egregious but useful hack, we use the real path here and // check whether it is actually a subdirectory of the parent directory. // This will not be the case if the 'subframework' is actually a symlink @@ -1113,9 +1137,8 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // If the module is a top-level framework, automatically link against the // framework. - if (!Result->isSubFramework()) { - inferFrameworkLink(Result, FrameworkDir, FileMgr); - } + if (!Result->isSubFramework()) + inferFrameworkLink(Result); return Result; } @@ -1135,11 +1158,11 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, return Result; } -void ModuleMap::setUmbrellaHeader( +void ModuleMap::setUmbrellaHeaderAsWritten( Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory) { Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); - Mod->Umbrella = &UmbrellaHeader.getMapEntry(); + Mod->Umbrella = UmbrellaHeader; Mod->UmbrellaAsWritten = NameAsWritten.str(); Mod->UmbrellaRelativeToRootModuleDirectory = PathRelativeToRootModuleDirectory.str(); @@ -1147,12 +1170,12 @@ void ModuleMap::setUmbrellaHeader( // Notify callbacks that we just added a new header. for (const auto &Cb : Callbacks) - Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); + Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader); } -void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, - const Twine &NameAsWritten, - const Twine &PathRelativeToRootModuleDirectory) { +void ModuleMap::setUmbrellaDirAsWritten( + Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory) { Mod->Umbrella = UmbrellaDir; Mod->UmbrellaAsWritten = NameAsWritten.str(); Mod->UmbrellaRelativeToRootModuleDirectory = @@ -1256,7 +1279,7 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header, // Notify callbacks that we just added a new header. for (const auto &Cb : Callbacks) - Cb->moduleMapAddHeader(Header.Entry->getName()); + Cb->moduleMapAddHeader(Header.Entry.getName()); } OptionalFileEntryRef @@ -1296,24 +1319,14 @@ ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) { } FileManager &FM = SourceMgr.getFileManager(); - auto DirEntry = FM.getDirectory(Dir.empty() ? "." : Dir); + auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir); if (!DirEntry) - return DirEntry.getError(); + return llvm::errorToErrorCode(DirEntry.takeError()); // Canonicalize the directory. StringRef CanonicalDir = FM.getCanonicalName(*DirEntry); - if (CanonicalDir != Dir) { - auto CanonicalDirEntry = FM.getDirectory(CanonicalDir); - // Only use the canonicalized path if it resolves to the same entry as the - // original. This is not true if there's a VFS overlay on top of a FS where - // the directory is a symlink. The overlay would not remap the target path - // of the symlink to the same directory entry in that case. - if (CanonicalDirEntry && *CanonicalDirEntry == *DirEntry) { - bool Done = llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir); - (void)Done; - assert(Done && "Path should always start with Dir"); - } - } + if (CanonicalDir != Dir) + llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir); // In theory, the filename component should also be canonicalized if it // on a case-insensitive filesystem. However, the extra canonicalization is @@ -1485,7 +1498,7 @@ namespace clang { /// The directory that file names in this module map file should /// be resolved relative to. - const DirectoryEntry *Directory; + DirectoryEntryRef Directory; /// Whether this module map is in a system header directory. bool IsSystem; @@ -1551,7 +1564,7 @@ namespace clang { explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, const TargetInfo *Target, DiagnosticsEngine &Diags, ModuleMap &Map, const FileEntry *ModuleMapFile, - const DirectoryEntry *Directory, bool IsSystem) + DirectoryEntryRef Directory, bool IsSystem) : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), ModuleMapFile(ModuleMapFile), Directory(Directory), IsSystem(IsSystem) { @@ -2003,10 +2016,28 @@ void ModuleMapParser::parseModuleDecl() { Module *ShadowingModule = nullptr; if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { // We might see a (re)definition of a module that we already have a - // definition for in two cases: + // definition for in four cases: // - If we loaded one definition from an AST file and we've just found a // corresponding definition in a module map file, or - bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); + bool LoadedFromASTFile = Existing->IsFromModuleFile; + // - If we previously inferred this module from different module map file. + bool Inferred = Existing->IsInferred; + // - If we're building a framework that vends a module map, we might've + // previously seen the one in intermediate products and now the system + // one. + // FIXME: If we're parsing module map file that looks like this: + // framework module FW { ... } + // module FW.Sub { ... } + // We can't check the framework qualifier, since it's not attached to + // the definition of Sub. Checking that qualifier on \c Existing is + // not correct either, since we might've previously seen: + // module FW { ... } + // module FW.Sub { ... } + // We should enforce consistency of redefinitions so that we can rely + // that \c Existing is part of a framework iff the redefinition of FW + // we have just skipped had it too. Once we do that, stop checking + // the local framework qualifier and only rely on \c Existing. + bool PartOfFramework = Framework || Existing->isPartOfFramework(); // - If we're building a (preprocessed) module and we've just loaded the // module map file from which it was created. bool ParsedAsMainInput = @@ -2014,7 +2045,8 @@ void ModuleMapParser::parseModuleDecl() { Map.LangOpts.CurrentModule == ModuleName && SourceMgr.getDecomposedLoc(ModuleNameLoc).first != SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; - if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { + if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) { + ActiveModule = PreviousActiveModule; // Skip the module definition. skipUntil(MMToken::RBrace); if (Tok.is(MMToken::RBrace)) @@ -2169,9 +2201,8 @@ void ModuleMapParser::parseModuleDecl() { // If the active module is a top-level framework, and there are no link // libraries, automatically link against the framework. if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && - ActiveModule->LinkLibraries.empty()) { - inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); - } + ActiveModule->LinkLibraries.empty()) + inferFrameworkLink(ActiveModule); // If the module meets all requirements but is still unavailable, mark the // whole tree as unavailable to prevent it from building. @@ -2222,16 +2253,16 @@ void ModuleMapParser::parseExternModuleDecl() { StringRef FileNameRef = FileName; SmallString<128> ModuleMapFileName; if (llvm::sys::path::is_relative(FileNameRef)) { - ModuleMapFileName += Directory->getName(); + ModuleMapFileName += Directory.getName(); llvm::sys::path::append(ModuleMapFileName, FileName); FileNameRef = ModuleMapFileName; } - if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) + if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) Map.parseModuleMapFile( *File, IsSystem, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory - : (*File)->getDir(), + : File->getDir(), FileID(), nullptr, ExternLoc); } @@ -2444,7 +2475,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, bool NeedsFramework = false; Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); - if (NeedsFramework && ActiveModule) + if (NeedsFramework) Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) << ActiveModule->getFullModuleName() << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); @@ -2481,16 +2512,14 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { } // Look for this file. - const DirectoryEntry *Dir = nullptr; + OptionalDirectoryEntryRef Dir; if (llvm::sys::path::is_absolute(DirName)) { - if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) - Dir = *D; + Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName); } else { SmallString<128> PathName; - PathName = Directory->getName(); + PathName = Directory.getName(); llvm::sys::path::append(PathName, DirName); - if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) - Dir = *D; + Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName); } if (!Dir) { @@ -2511,7 +2540,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; I != E && !EC; I.increment(EC)) { if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) { - Module::Header Header = {"", std::string(I->path()), FE}; + Module::Header Header = {"", std::string(I->path()), *FE}; Headers.push_back(std::move(Header)); } } @@ -2524,7 +2553,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { return; } - if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { + if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) { Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) << OwningModule->getFullModuleName(); HadError = true; @@ -2532,7 +2561,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { } // Record this umbrella directory. - Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName); + Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName); } /// Parse a module export declaration. @@ -2796,7 +2825,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { if (ActiveModule) { // Inferred modules must have umbrella directories. if (!Failed && ActiveModule->IsAvailable && - !ActiveModule->getUmbrellaDir()) { + !ActiveModule->getEffectiveUmbrellaDir()) { Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); Failed = true; } @@ -3050,7 +3079,7 @@ bool ModuleMapParser::parseModuleMapFile() { } bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, FileID ID, + DirectoryEntryRef Dir, FileID ID, unsigned *Offset, SourceLocation ExternModuleLoc) { assert(Target && "Missing target information"); |