diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 69 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 2 |
9 files changed, 113 insertions, 32 deletions
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 12d5eabafa1..a814df3c64c 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -5405,6 +5405,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Path)); } + if (HaveModules) { + // -fprebuilt-module-path specifies where to load the prebuilt module files. + for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) + CmdArgs.push_back(Args.MakeArgString( + std::string("-fprebuilt-module-path=") + A->getValue())); + } + // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index aafbb481f0e..3a34f852d89 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -2805,6 +2805,7 @@ const FileEntry *ASTUnit::getPCHFile() { switch (M.Kind) { case serialization::MK_ImplicitModule: case serialization::MK_ExplicitModule: + case serialization::MK_PrebuiltModule: return true; // skip dependencies. case serialization::MK_PCH: Mod = &M; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 3d37a829000..89907f11719 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1436,7 +1436,25 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } else { // Search for a module with the given name. Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); - if (!Module) { + HeaderSearchOptions &HSOpts = + PP->getHeaderSearchInfo().getHeaderSearchOpts(); + + std::string ModuleFileName; + bool LoadFromPrebuiltModulePath = false; + // We try to load the module from the prebuilt module paths. If not + // successful, we then try to find it in the module cache. + if (!HSOpts.PrebuiltModulePaths.empty()) { + // Load the module from the prebuilt module path. + ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName( + ModuleName, "", /*UsePrebuiltPath*/ true); + if (!ModuleFileName.empty()) + LoadFromPrebuiltModulePath = true; + } + if (!LoadFromPrebuiltModulePath && Module) { + // Load the module from the module cache. + ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); + } else if (!LoadFromPrebuiltModulePath) { + // We can't find a module, error out here. getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); @@ -1444,10 +1462,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return ModuleLoadResult(); } - std::string ModuleFileName = - PP->getHeaderSearchInfo().getModuleFileName(Module); if (ModuleFileName.empty()) { - if (Module->HasIncompatibleModuleFile) { + if (Module && Module->HasIncompatibleModuleFile) { // We tried and failed to load a module file for this module. Fall // back to textual inclusion for its headers. return ModuleLoadResult(nullptr, /*missingExpected*/true); @@ -1468,16 +1484,46 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup); llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); - // Try to load the module file. - unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; + // Try to load the module file. If we are trying to load from the prebuilt + // module path, we don't have the module map files and don't know how to + // rebuild modules. + unsigned ARRFlags = LoadFromPrebuiltModulePath ? + ASTReader::ARR_ConfigurationMismatch : + ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; switch (ModuleManager->ReadAST(ModuleFileName, + LoadFromPrebuiltModulePath ? + serialization::MK_PrebuiltModule : serialization::MK_ImplicitModule, - ImportLoc, ARRFlags)) { - case ASTReader::Success: + ImportLoc, + ARRFlags)) { + case ASTReader::Success: { + if (LoadFromPrebuiltModulePath && !Module) { + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + if (!Module || !Module->getASTFile() || + FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { + // Error out if Module does not refer to the file in the prebuilt + // module path. + getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt) + << ModuleName; + ModuleBuildFailed = true; + KnownModules[Path[0].first] = nullptr; + return ModuleLoadResult(); + } + } break; + } case ASTReader::OutOfDate: case ASTReader::Missing: { + if (LoadFromPrebuiltModulePath) { + // We can't rebuild the module without a module map. Since ReadAST + // already produces diagnostics for these two cases, we simply + // error out here. + ModuleBuildFailed = true; + KnownModules[Path[0].first] = nullptr; + return ModuleLoadResult(); + } + // The module file is missing or out-of-date. Build it. assert(Module && "missing module file"); // Check whether there is a cycle in the module graph. @@ -1528,8 +1574,13 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, break; } - case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: + if (LoadFromPrebuiltModulePath) + getDiagnostics().Report(SourceLocation(), + diag::warn_module_config_mismatch) + << ModuleFileName; + // Fall through to error out. + case ASTReader::VersionMismatch: case ASTReader::HadErrors: ModuleLoader::HadFatalFailure = true; // FIXME: The ASTReader will already have complained, but can we shoehorn diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b1e985f077e..69c4593d5f5 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1368,6 +1368,8 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); + for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path)) + Opts.AddPrebuiltModulePath(A->getValue()); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); Opts.ModulesValidateDiagnosticOptions = !Args.hasArg(OPT_fmodules_disable_diagnostic_validation); diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index d83e98fc31a..706ccea59b8 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -391,7 +391,8 @@ GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI, HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); CI.getFrontendOpts().OutputFile = HS.getModuleFileName(CI.getLangOpts().CurrentModule, - ModuleMapForUniquing->getName()); + ModuleMapForUniquing->getName(), + /*UsePrebuiltPath=*/false); } // We use createOutputFile here because this is exposed via libclang, and we diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 77ced234d69..bf266b30e50 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -121,11 +121,29 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { std::string HeaderSearch::getModuleFileName(Module *Module) { const FileEntry *ModuleMap = getModuleMap().getModuleMapFileForUniquing(Module); - return getModuleFileName(Module->Name, ModuleMap->getName()); + return getModuleFileName(Module->Name, ModuleMap->getName(), + /*UsePrebuiltPath*/false); } std::string HeaderSearch::getModuleFileName(StringRef ModuleName, - StringRef ModuleMapPath) { + StringRef ModuleMapPath, + bool UsePrebuiltPath) { + if (UsePrebuiltPath) { + if (HSOpts->PrebuiltModulePaths.empty()) + return std::string(); + + // Go though each prebuilt module path and try to find the pcm file. + for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { + SmallString<256> Result(Dir); + llvm::sys::fs::make_absolute(Result); + + llvm::sys::path::append(Result, ModuleName + ".pcm"); + if (getFileMgr().getFile(Result.str())) + return Result.str().str(); + } + return std::string(); + } + // If we don't have a module cache path or aren't supposed to use one, we // can't do anything. if (getModuleCachePath().empty()) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ec9503aa78f..14d22f6efd9 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1312,8 +1312,7 @@ bool ASTReader::ReadSLocEntry(int ID) { SrcMgr::CharacteristicKind FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); - if (IncludeLoc.isInvalid() && - (F->Kind == MK_ImplicitModule || F->Kind == MK_ExplicitModule)) { + if (IncludeLoc.isInvalid() && F->isModule()) { IncludeLoc = getImportLocation(F); } @@ -1351,7 +1350,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { // Find which module file this entry lands in. ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second; - if (M->Kind != MK_ImplicitModule && M->Kind != MK_ExplicitModule) + if (!M->isModule()) return std::make_pair(SourceLocation(), ""); // FIXME: Can we map this down to a particular submodule? That would be @@ -1861,7 +1860,7 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, // Don't read the directive history for a module; we don't have anywhere // to put it. - if (M.Kind == MK_ImplicitModule || M.Kind == MK_ExplicitModule) + if (M.isModule()) return; // Deserialize the macro directives history in reverse source-order. @@ -2194,7 +2193,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, // All user input files reside at the index range [0, NumUserInputs), and // system input files reside at [NumUserInputs, NumInputs). For explicitly // loaded module files, ignore missing inputs. - if (!DisableValidation && F.Kind != MK_ExplicitModule) { + if (!DisableValidation && F.Kind != MK_ExplicitModule && + F.Kind != MK_PrebuiltModule) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; // If we are reading a module, we will create a verification timestamp, @@ -2225,7 +2225,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool IsSystem = I >= NumUserInputs; InputFileInfo FI = readInputFileInfo(F, I+1); Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden, - F.Kind == MK_ExplicitModule); + F.Kind == MK_ExplicitModule || + F.Kind == MK_PrebuiltModule); } } @@ -2255,7 +2256,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, // // FIXME: Allow this for files explicitly specified with -include-pch. bool AllowCompatibleConfigurationMismatch = - F.Kind == MK_ExplicitModule; + F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule; const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); @@ -2417,7 +2418,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, if (M && M->Directory) { // If we're implicitly loading a module, the base directory can't // change between the build and use. - if (F.Kind != MK_ExplicitModule) { + if (F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) { const DirectoryEntry *BuildDir = PP.getFileManager().getDirectory(Blob); if (!BuildDir || BuildDir != M->Directory) { @@ -3141,7 +3142,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case IMPORTED_MODULES: { - if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) { + if (!F.isModule()) { // If we aren't loading a module (which has its own exports), make // all of the imported modules visible. // FIXME: Deal with macros-only imports. @@ -3225,7 +3226,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, unsigned Idx = 0; F.ModuleMapPath = ReadPath(F, Record, Idx); - if (F.Kind == MK_ExplicitModule) { + if (F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule) { // For an explicitly-loaded module, we don't care whether the original // module map file exists or matches. return Success; @@ -3596,7 +3597,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, } if (!Context.getLangOpts().CPlusPlus || - (Type != MK_ImplicitModule && Type != MK_ExplicitModule)) { + (Type != MK_ImplicitModule && Type != MK_ExplicitModule && + Type != MK_PrebuiltModule)) { // Mark all of the identifiers in the identifier table as being out of date, // so that various accessors know to check the loaded modules when the // identifier is used. @@ -3713,6 +3715,7 @@ static unsigned moduleKindForDiagnostic(ModuleKind Kind) { return 0; // PCH case MK_ImplicitModule: case MK_ExplicitModule: + case MK_PrebuiltModule: return 1; // module case MK_MainFile: case MK_Preamble: @@ -3818,7 +3821,8 @@ ASTReader::ReadASTCore(StringRef FileName, // // FIXME: Should we also perform the converse check? Loading a module as // a PCH file sort of works, but it's a bit wonky. - if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule) && + if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule || + Type == MK_PrebuiltModule) && F.ModuleName.empty()) { auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure; if (Result != OutOfDate || @@ -8364,16 +8368,14 @@ void ASTReader::finishPendingActions() { for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (Info.M->Kind != MK_ImplicitModule && - Info.M->Kind != MK_ExplicitModule) + if (!Info.M->isModule()) resolvePendingMacro(II, Info); } // Handle module imports. for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (Info.M->Kind == MK_ImplicitModule || - Info.M->Kind == MK_ExplicitModule) + if (Info.M->isModule()) resolvePendingMacro(II, Info); } } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index e1859388f57..209f95a5859 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1398,7 +1398,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace)); - if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) + if (!F.isModule()) D->setAnonymousNamespace(Anon); } } @@ -3767,8 +3767,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. - if (ModuleFile.Kind != MK_ImplicitModule && - ModuleFile.Kind != MK_ExplicitModule) { + if (!ModuleFile.isModule()) { if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) TU->setAnonymousNamespace(Anon); else diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 93709c8f2f6..bc57d8cbc7a 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -66,7 +66,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Look for the file entry. This only fails if the expected size or // modification time differ. const FileEntry *Entry; - if (Type == MK_ExplicitModule) { + if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) { // If we're not expecting to pull this file out of the module cache, it // might have a different mtime due to being moved across filesystems in // a distributed build. The size must still match, though. (As must the |