Module: add -fprebuilt-module-path to support loading prebuilt modules.
In this mode, there is no need to load any module map and the programmer can simply use "@import" syntax to load the module directly from a prebuilt module path. When loading from prebuilt module path, we don't support rebuilding of the module files and we ignore compatible configuration mismatches. rdar://27290316 Differential Revision: http://reviews.llvm.org/D23125 llvm-svn: 279096
This commit is contained in:
parent
c948d182e1
commit
11f2a47772
|
@ -213,6 +213,9 @@ Command-line parameters
|
|||
``-fmodule-file=<file>``
|
||||
Load the given precompiled module file.
|
||||
|
||||
``-fprebuilt-module-path=<directory>``
|
||||
Specify the path to the prebuilt modules. If specified, we will look for modules in this directory for a given top-level module name. We don't need a module map for loading prebuilt modules in this directory and the compiler will not try to rebuild these modules. This can be specified multiple times.
|
||||
|
||||
Module Semantics
|
||||
================
|
||||
|
||||
|
|
|
@ -94,6 +94,8 @@ def err_module_lock_timeout : Error<
|
|||
"timed out waiting to acquire lock file for module '%0'">, DefaultFatal;
|
||||
def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
|
||||
DefaultFatal;
|
||||
def err_module_prebuilt : Error<
|
||||
"error in loading module '%0' from prebuilt module path">, DefaultFatal;
|
||||
def note_pragma_entered_here : Note<"#pragma entered here">;
|
||||
def note_decl_hiding_tag_type : Note<
|
||||
"%1 %0 is hidden by a non-type declaration of %0 here">;
|
||||
|
|
|
@ -840,6 +840,9 @@ def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
|
|||
def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>,
|
||||
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
|
||||
HelpText<"Specify the module user build path">;
|
||||
def fprebuilt_module_path : Joined<["-"], "fprebuilt-module-path=">, Group<i_Group>,
|
||||
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
|
||||
HelpText<"Specify the prebuilt module path">;
|
||||
def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
|
||||
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
|
||||
HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">;
|
||||
|
|
|
@ -481,9 +481,12 @@ public:
|
|||
/// \param ModuleMapPath A path that when combined with \c ModuleName
|
||||
/// uniquely identifies this module. See Module::ModuleMap.
|
||||
///
|
||||
/// \param UsePrebuiltPath Whether we should use the prebuilt module path.
|
||||
///
|
||||
/// \returns The name of the module file that corresponds to this module,
|
||||
/// or an empty string if this module does not correspond to any module file.
|
||||
std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
|
||||
std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath,
|
||||
bool UsePrebuiltPath);
|
||||
|
||||
/// \brief Lookup a module Search for a module with the given name.
|
||||
///
|
||||
|
|
|
@ -93,6 +93,9 @@ public:
|
|||
/// \brief The directory used for a user build.
|
||||
std::string ModuleUserBuildPath;
|
||||
|
||||
/// \brief The directories used to load prebuilt module files.
|
||||
std::vector<std::string> PrebuiltModulePaths;
|
||||
|
||||
/// The module/pch container format.
|
||||
std::string ModuleFormat;
|
||||
|
||||
|
@ -201,6 +204,10 @@ public:
|
|||
void AddVFSOverlayFile(StringRef Name) {
|
||||
VFSOverlayFiles.push_back(Name);
|
||||
}
|
||||
|
||||
void AddPrebuiltModulePath(StringRef Name) {
|
||||
PrebuiltModulePaths.push_back(Name);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -48,7 +48,8 @@ enum ModuleKind {
|
|||
MK_ExplicitModule, ///< File is an explicitly-loaded module.
|
||||
MK_PCH, ///< File is a PCH file treated as such.
|
||||
MK_Preamble, ///< File is a PCH file treated as the preamble.
|
||||
MK_MainFile ///< File is a PCH file treated as the actual main file.
|
||||
MK_MainFile, ///< File is a PCH file treated as the actual main file.
|
||||
MK_PrebuiltModule ///< File is from a prebuilt module path.
|
||||
};
|
||||
|
||||
/// \brief The input file that has been loaded from this AST file, along with
|
||||
|
@ -447,7 +448,8 @@ public:
|
|||
|
||||
/// \brief Is this a module file for a module (rather than a PCH or similar).
|
||||
bool isModule() const {
|
||||
return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule;
|
||||
return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule ||
|
||||
Kind == MK_PrebuiltModule;
|
||||
}
|
||||
|
||||
/// \brief Dump debugging output for this module.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -39,6 +39,13 @@
|
|||
// RUN: %clang -fmodules-disable-diagnostic-validation -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION %s
|
||||
// MODULES_DISABLE_DIAGNOSTIC_VALIDATION: -fmodules-disable-diagnostic-validation
|
||||
|
||||
// RUN: %clang -fmodules -### %s 2>&1 | FileCheck -check-prefix=MODULES_PREBUILT_PATH_DEFAULT %s
|
||||
// MODULES_PREBUILT_PATH_DEFAULT-NOT: -fprebuilt-module-path
|
||||
|
||||
// RUN: %clang -fmodules -fprebuilt-module-path=foo -fprebuilt-module-path=bar -### %s 2>&1 | FileCheck -check-prefix=MODULES_PREBUILT_PATH %s
|
||||
// MODULES_PREBUILT_PATH: "-fprebuilt-module-path=foo"
|
||||
// MODULES_PREBUILT_PATH: "-fprebuilt-module-path=bar"
|
||||
|
||||
// RUN: %clang -fmodules -fmodule-map-file=foo.map -fmodule-map-file=bar.map -### %s 2>&1 | FileCheck -check-prefix=CHECK-MODULE-MAP-FILES %s
|
||||
// CHECK-MODULE-MAP-FILES: "-fmodules"
|
||||
// CHECK-MODULE-MAP-FILES: "-fmodule-map-file=foo.map"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
const int a = 1;
|
|
@ -0,0 +1 @@
|
|||
module prebuilt { header "a.h" }
|
|
@ -0,0 +1,10 @@
|
|||
// RUN: rm -rf %t
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -x objective-c -I %S/Inputs/prebuilt-module -triple %itanium_abi_triple -emit-module %S/Inputs/prebuilt-module/module.modulemap -fmodule-name=prebuilt -o %t/prebuilt.pcm
|
||||
// RUN: %clang_cc1 -fmodules -fprebuilt-module-path=%t/ -fdisable-module-hash %s -verify
|
||||
|
||||
// expected-no-diagnostics
|
||||
@import prebuilt;
|
||||
int test() {
|
||||
return a;
|
||||
}
|
Loading…
Reference in New Issue