forked from OSchip/llvm-project
[modules] PR22534: Load files specified by -fmodule-file= eagerly. In particular, this avoids the need to re-parse module map files when using such a module.
llvm-svn: 244416
This commit is contained in:
parent
38c1e6d355
commit
0f99d6a441
|
@ -194,9 +194,8 @@ def err_unable_to_make_temp : Error<
|
|||
"unable to make temporary file: %0">;
|
||||
|
||||
// Modules
|
||||
def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
|
||||
def err_module_format_unhandled : Error<
|
||||
"no handler registered for module format '%0'">;
|
||||
"no handler registered for module format '%0'">, DefaultFatal;
|
||||
|
||||
// TransformActions
|
||||
// TODO: Use a custom category name to distinguish rewriter errors.
|
||||
|
|
|
@ -194,16 +194,6 @@ def remark_module_build_done : Remark<"finished building module '%0'">,
|
|||
def err_conflicting_module_names : Error<
|
||||
"conflicting module names specified: '-fmodule-name=%0' and "
|
||||
"'-fmodule-implementation-of %1'">;
|
||||
def err_conflicting_module_files : Error<
|
||||
"module '%0' is defined in both '%1' and '%2'">;
|
||||
def err_module_file_not_found : Error<
|
||||
"module file '%0' not found">, DefaultFatal;
|
||||
def err_module_file_invalid : Error<
|
||||
"file '%0' is not a valid precompiled module file">, DefaultFatal;
|
||||
def note_module_file_imported_by : Note<
|
||||
"imported by %select{|module '%2' in }1'%0'">;
|
||||
def err_module_file_not_module : Error<
|
||||
"AST file '%0' was not built as a module">, DefaultFatal;
|
||||
|
||||
def err_missing_vfs_overlay_file : Error<
|
||||
"virtual filesystem overlay file '%0' not found">, DefaultFatal;
|
||||
|
|
|
@ -53,6 +53,20 @@ def err_pch_different_branch : Error<
|
|||
def err_pch_with_compiler_errors : Error<
|
||||
"PCH file contains compiler errors">;
|
||||
|
||||
def err_module_file_conflict : Error<
|
||||
"module '%0' is defined in both '%1' and '%2'">, DefaultFatal;
|
||||
def err_module_file_not_found : Error<
|
||||
"%select{PCH|module|AST}0 file '%1' not found%select{|: %3}2">, DefaultFatal;
|
||||
def err_module_file_out_of_date : Error<
|
||||
"%select{PCH|module|AST}0 file '%1' is out of date and "
|
||||
"needs to be rebuilt%select{|: %3}2">, DefaultFatal;
|
||||
def err_module_file_invalid : Error<
|
||||
"file '%1' is not a valid precompiled %select{PCH|module|AST}0 file">, DefaultFatal;
|
||||
def note_module_file_imported_by : Note<
|
||||
"imported by %select{|module '%2' in }1'%0'">;
|
||||
def err_module_file_not_module : Error<
|
||||
"AST file '%0' was not built as a module">, DefaultFatal;
|
||||
|
||||
def err_imported_module_not_found : Error<
|
||||
"module '%0' in AST file '%1' (imported by AST file '%2') "
|
||||
"is not defined in any loaded module map file; "
|
||||
|
@ -82,9 +96,6 @@ def err_pch_pp_detailed_record : Error<
|
|||
"'-detailed-preprocessing-record' but %select{precompiled header was not "
|
||||
"built with it|it is not present on the command line}0">;
|
||||
|
||||
def err_not_a_pch_file : Error<
|
||||
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
|
||||
|
||||
def err_module_odr_violation_missing_decl : Error<
|
||||
"%q0 from module '%1' is not present in definition of %q2"
|
||||
"%select{ in module '%4'| provided earlier}3">, NoSFINAE;
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
const std::string &OutputFileName,
|
||||
raw_pwrite_stream *OS,
|
||||
std::shared_ptr<PCHBuffer> Buffer)
|
||||
: Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
|
||||
: Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
|
||||
TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) {
|
||||
// The debug info output isn't affected by CodeModel and
|
||||
// ThreadModel, but the backend expects them to be nonempty.
|
||||
|
@ -71,6 +71,11 @@ public:
|
|||
virtual ~PCHContainerGenerator() {}
|
||||
|
||||
void Initialize(ASTContext &Context) override {
|
||||
if (Ctx) {
|
||||
assert(Ctx == &Context);
|
||||
return;
|
||||
}
|
||||
|
||||
Ctx = &Context;
|
||||
VMContext.reset(new llvm::LLVMContext());
|
||||
M.reset(new llvm::Module(MainFileName, *VMContext));
|
||||
|
|
|
@ -1261,8 +1261,10 @@ void CompilerInstance::createModuleManager() {
|
|||
getASTContext().setExternalSource(ModuleManager);
|
||||
if (hasSema())
|
||||
ModuleManager->InitializeSema(getSema());
|
||||
if (hasASTConsumer())
|
||||
if (hasASTConsumer()) {
|
||||
getASTConsumer().Initialize(getASTContext());
|
||||
ModuleManager->StartTranslationUnit(&getASTConsumer());
|
||||
}
|
||||
|
||||
if (TheDependencyFileGenerator)
|
||||
TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
|
||||
|
@ -1284,86 +1286,44 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
|
|||
// the files we were handed.
|
||||
struct ReadModuleNames : ASTReaderListener {
|
||||
CompilerInstance &CI;
|
||||
std::vector<StringRef> ModuleFileStack;
|
||||
std::vector<StringRef> ModuleNameStack;
|
||||
bool Failed;
|
||||
bool TopFileIsModule;
|
||||
llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
|
||||
|
||||
ReadModuleNames(CompilerInstance &CI)
|
||||
: CI(CI), Failed(false), TopFileIsModule(false) {}
|
||||
|
||||
bool needsImportVisitation() const override { return true; }
|
||||
|
||||
void visitImport(StringRef FileName) override {
|
||||
if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) {
|
||||
if (ModuleFileStack.size() == 0)
|
||||
TopFileIsModule = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ModuleFileStack.push_back(FileName);
|
||||
ModuleNameStack.push_back(StringRef());
|
||||
if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
|
||||
CI.getPCHContainerReader(),
|
||||
*this)) {
|
||||
CI.getDiagnostics().Report(
|
||||
SourceLocation(), CI.getFileManager().getBufferForFile(FileName)
|
||||
? diag::err_module_file_invalid
|
||||
: diag::err_module_file_not_found)
|
||||
<< FileName;
|
||||
for (int I = ModuleFileStack.size() - 2; I >= 0; --I)
|
||||
CI.getDiagnostics().Report(SourceLocation(),
|
||||
diag::note_module_file_imported_by)
|
||||
<< ModuleFileStack[I]
|
||||
<< !ModuleNameStack[I].empty() << ModuleNameStack[I];
|
||||
Failed = true;
|
||||
}
|
||||
ModuleNameStack.pop_back();
|
||||
ModuleFileStack.pop_back();
|
||||
}
|
||||
ReadModuleNames(CompilerInstance &CI) : CI(CI) {}
|
||||
|
||||
void ReadModuleName(StringRef ModuleName) override {
|
||||
if (ModuleFileStack.size() == 1)
|
||||
TopFileIsModule = true;
|
||||
ModuleNameStack.back() = ModuleName;
|
||||
|
||||
auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
|
||||
if (!ModuleFile.empty() &&
|
||||
CI.getFileManager().getFile(ModuleFile) !=
|
||||
CI.getFileManager().getFile(ModuleFileStack.back()))
|
||||
CI.getDiagnostics().Report(SourceLocation(),
|
||||
diag::err_conflicting_module_files)
|
||||
<< ModuleName << ModuleFile << ModuleFileStack.back();
|
||||
ModuleFile = ModuleFileStack.back();
|
||||
LoadedModules.push_back(
|
||||
CI.getPreprocessor().getIdentifierInfo(ModuleName));
|
||||
}
|
||||
} RMN(*this);
|
||||
|
||||
void registerAll() {
|
||||
for (auto *II : LoadedModules) {
|
||||
CI.KnownModules[II] = CI.getPreprocessor()
|
||||
.getHeaderSearchInfo()
|
||||
.getModuleMap()
|
||||
.findModule(II->getName());
|
||||
}
|
||||
LoadedModules.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// If we don't already have an ASTReader, create one now.
|
||||
if (!ModuleManager)
|
||||
createModuleManager();
|
||||
|
||||
// Tell the module manager about this module file.
|
||||
if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {
|
||||
getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)
|
||||
<< FileName;
|
||||
return false;
|
||||
}
|
||||
auto Listener = llvm::make_unique<ReadModuleNames>(*this);
|
||||
auto &ListenerRef = *Listener;
|
||||
ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager,
|
||||
std::move(Listener));
|
||||
|
||||
// Build our mapping of module names to module files from this file
|
||||
// and its imports.
|
||||
RMN.visitImport(FileName);
|
||||
|
||||
if (RMN.Failed)
|
||||
// Try to load the module file.
|
||||
if (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule,
|
||||
SourceLocation(), ASTReader::ARR_None)
|
||||
!= ASTReader::Success)
|
||||
return false;
|
||||
|
||||
// If we never found a module name for the top file, then it's not a module,
|
||||
// it's a PCH or preamble or something.
|
||||
if (!RMN.TopFileIsModule) {
|
||||
getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_module)
|
||||
<< FileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We successfully loaded the module file; remember the set of provided
|
||||
// modules so that we don't try to load implicit modules for them.
|
||||
ListenerRef.registerAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1412,6 +1372,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
return ModuleLoadResult();
|
||||
}
|
||||
|
||||
// FIXME: Rmove ModuleFileOverrides
|
||||
auto Override = ModuleFileOverrides.find(ModuleName);
|
||||
bool Explicit = Override != ModuleFileOverrides.end();
|
||||
|
||||
|
@ -1507,7 +1468,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
case ASTReader::ConfigurationMismatch:
|
||||
case ASTReader::HadErrors:
|
||||
ModuleLoader::HadFatalFailure = true;
|
||||
// FIXME: The ASTReader will already have complained, but can we showhorn
|
||||
// FIXME: The ASTReader will already have complained, but can we shoehorn
|
||||
// that diagnostic information into a more useful form?
|
||||
KnownModules[Path[0].first] = nullptr;
|
||||
return ModuleLoadResult();
|
||||
|
|
|
@ -2029,6 +2029,21 @@ void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) {
|
|||
Filename.assign(Buffer.begin(), Buffer.end());
|
||||
}
|
||||
|
||||
static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) {
|
||||
switch (ARR) {
|
||||
case ASTReader::Failure: return true;
|
||||
case ASTReader::Missing: return !(Caps & ASTReader::ARR_Missing);
|
||||
case ASTReader::OutOfDate: return !(Caps & ASTReader::ARR_OutOfDate);
|
||||
case ASTReader::VersionMismatch: return !(Caps & ASTReader::ARR_VersionMismatch);
|
||||
case ASTReader::ConfigurationMismatch:
|
||||
return !(Caps & ASTReader::ARR_ConfigurationMismatch);
|
||||
case ASTReader::HadErrors: return true;
|
||||
case ASTReader::Success: return false;
|
||||
}
|
||||
|
||||
llvm_unreachable("unknown ASTReadResult");
|
||||
}
|
||||
|
||||
ASTReader::ASTReadResult
|
||||
ASTReader::ReadControlBlock(ModuleFile &F,
|
||||
SmallVectorImpl<ImportedModule> &Loaded,
|
||||
|
@ -2064,8 +2079,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
PP.getHeaderSearchInfo().getHeaderSearchOpts();
|
||||
|
||||
// All user input files reside at the index range [0, NumUserInputs), and
|
||||
// system input files reside at [NumUserInputs, NumInputs).
|
||||
if (!DisableValidation) {
|
||||
// system input files reside at [NumUserInputs, NumInputs). For explicitly
|
||||
// loaded module files, ignore missing inputs.
|
||||
if (!DisableValidation && F.Kind != MK_ExplicitModule) {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
|
||||
|
||||
// If we are reading a module, we will create a verification timestamp,
|
||||
|
@ -2181,10 +2197,23 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
ASTFileSignature StoredSignature = Record[Idx++];
|
||||
auto ImportedFile = ReadPath(F, Record, Idx);
|
||||
|
||||
// If our client can't cope with us being out of date, we can't cope with
|
||||
// our dependency being missing.
|
||||
unsigned Capabilities = ClientLoadCapabilities;
|
||||
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
|
||||
Capabilities &= ~ARR_Missing;
|
||||
|
||||
// Load the AST file.
|
||||
switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
|
||||
StoredSize, StoredModTime, StoredSignature,
|
||||
ClientLoadCapabilities)) {
|
||||
auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
|
||||
Loaded, StoredSize, StoredModTime,
|
||||
StoredSignature, Capabilities);
|
||||
|
||||
// If we diagnosed a problem, produce a backtrace.
|
||||
if (isDiagnosedResult(Result, Capabilities))
|
||||
Diag(diag::note_module_file_imported_by)
|
||||
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
|
||||
|
||||
switch (Result) {
|
||||
case Failure: return Failure;
|
||||
// If we have to ignore the dependency, we'll have to ignore this too.
|
||||
case Missing:
|
||||
|
@ -3152,11 +3181,18 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
|
|||
const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
|
||||
if (!ModMap) {
|
||||
assert(ImportedBy && "top-level import should be verified");
|
||||
if ((ClientLoadCapabilities & ARR_Missing) == 0)
|
||||
Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName
|
||||
<< ImportedBy->FileName
|
||||
<< F.ModuleMapPath;
|
||||
return Missing;
|
||||
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
|
||||
if (auto *ASTFE = M ? M->getASTFile() : nullptr)
|
||||
// This module was defined by an imported (explicit) module.
|
||||
Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
|
||||
<< ASTFE->getName();
|
||||
else
|
||||
// This module was built with a different module map.
|
||||
Diag(diag::err_imported_module_not_found)
|
||||
<< F.ModuleName << F.FileName << ImportedBy->FileName
|
||||
<< F.ModuleMapPath;
|
||||
}
|
||||
return OutOfDate;
|
||||
}
|
||||
|
||||
assert(M->Name == F.ModuleName && "found module with different name");
|
||||
|
@ -3557,6 +3593,20 @@ static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
|
|||
Stream.Read(8) == 'H';
|
||||
}
|
||||
|
||||
static unsigned moduleKindForDiagnostic(ModuleKind Kind) {
|
||||
switch (Kind) {
|
||||
case MK_PCH:
|
||||
return 0; // PCH
|
||||
case MK_ImplicitModule:
|
||||
case MK_ExplicitModule:
|
||||
return 1; // module
|
||||
case MK_MainFile:
|
||||
case MK_Preamble:
|
||||
return 2; // main source file
|
||||
}
|
||||
llvm_unreachable("unknown module kind");
|
||||
}
|
||||
|
||||
ASTReader::ASTReadResult
|
||||
ASTReader::ReadASTCore(StringRef FileName,
|
||||
ModuleKind Type,
|
||||
|
@ -3589,11 +3639,9 @@ ASTReader::ReadASTCore(StringRef FileName,
|
|||
return Missing;
|
||||
|
||||
// Otherwise, return an error.
|
||||
{
|
||||
std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
|
||||
+ ErrorStr;
|
||||
Error(Msg);
|
||||
}
|
||||
Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type)
|
||||
<< FileName << ErrorStr.empty()
|
||||
<< ErrorStr;
|
||||
return Failure;
|
||||
|
||||
case ModuleManager::OutOfDate:
|
||||
|
@ -3603,11 +3651,9 @@ ASTReader::ReadASTCore(StringRef FileName,
|
|||
return OutOfDate;
|
||||
|
||||
// Otherwise, return an error.
|
||||
{
|
||||
std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
|
||||
+ ErrorStr;
|
||||
Error(Msg);
|
||||
}
|
||||
Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type)
|
||||
<< FileName << ErrorStr.empty()
|
||||
<< ErrorStr;
|
||||
return Failure;
|
||||
}
|
||||
|
||||
|
@ -3628,7 +3674,8 @@ ASTReader::ReadASTCore(StringRef FileName,
|
|||
|
||||
// Sniff for the signature.
|
||||
if (!startsWithASTFileMagic(Stream)) {
|
||||
Diag(diag::err_not_a_pch_file) << FileName;
|
||||
Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type)
|
||||
<< FileName;
|
||||
return Failure;
|
||||
}
|
||||
|
||||
|
@ -3661,6 +3708,18 @@ ASTReader::ReadASTCore(StringRef FileName,
|
|||
HaveReadControlBlock = true;
|
||||
switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) {
|
||||
case Success:
|
||||
// Check that we didn't try to load a non-module AST file as a module.
|
||||
//
|
||||
// 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) &&
|
||||
F.ModuleName.empty()) {
|
||||
auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure;
|
||||
if (Result != OutOfDate ||
|
||||
(ClientLoadCapabilities & ARR_OutOfDate) == 0)
|
||||
Diag(diag::err_module_file_not_module) << FileName;
|
||||
return Result;
|
||||
}
|
||||
break;
|
||||
|
||||
case Failure: return Failure;
|
||||
|
@ -3690,8 +3749,6 @@ ASTReader::ReadASTCore(StringRef FileName,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
void ASTReader::InitializeContext() {
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -verify-pch %t/use_LibA.pch 2>&1 | FileCheck -check-prefix=VERIFY %s
|
||||
// RUN: not c-index-test -test-load-source all -x c -fmodules -fimplicit-module-maps -Xclang -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -include-pch %t/use_LibA.pch %s 2>&1 | FileCheck -check-prefix=INDEX %s
|
||||
|
||||
// VERIFY: fatal error: malformed or corrupted AST file: 'Unable to load module
|
||||
// VERIFY: fatal error: module file '{{.*}}LibA.pcm' not found
|
||||
// INDEX: {{^}}Failure: AST deserialization error occurred{{$}}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// RUN: cd %S
|
||||
// RUN: rm -rf %t
|
||||
//
|
||||
// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse %s -dependency-file - -MT implicit.pcm -o %t/implicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s
|
||||
// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse %s -dependency-file - -MT implicit.pcm -o %t/implicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s --check-prefix=IMPLICIT
|
||||
//
|
||||
// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test-base -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse Inputs/dependency-gen-base.modulemap -o %t/base.pcm -fmodule-map-file-home-is-cwd
|
||||
// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse -fmodule-file=%t/base.pcm %s -dependency-file - -MT explicit.pcm -o %t/explicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s
|
||||
// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse -fmodule-file=%t/base.pcm %s -dependency-file - -MT explicit.pcm -o %t/explicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s --check-prefix=EXPLICIT
|
||||
module "test" {
|
||||
export *
|
||||
header "Inputs/dependency-gen.h"
|
||||
|
@ -14,10 +14,30 @@ module "test" {
|
|||
extern module "test-base2" "Inputs/dependency-gen-base2.modulemap"
|
||||
extern module "test-base" "Inputs/dependency-gen-base.modulemap"
|
||||
|
||||
// CHECK-DAG: {{[/\\]}}dependency-gen.modulemap
|
||||
// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base.modulemap
|
||||
// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base2.modulemap
|
||||
// For implicit use of a module via the module cache, the input files
|
||||
// referenced by the .pcm are also dependencies of this build.
|
||||
//
|
||||
// IMPLICIT-DAG: {{[/\\]}}dependency-gen.modulemap
|
||||
// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base.modulemap
|
||||
// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base2.modulemap
|
||||
// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h
|
||||
// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included.h
|
||||
// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included2.h
|
||||
|
||||
// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h
|
||||
// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included.h
|
||||
// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included2.h
|
||||
// For an explicit use of a module via -fmodule-file=, the other module maps
|
||||
// and included headers are not dependencies of this target (they are instead
|
||||
// dependencies of the explicitly-specified .pcm input).
|
||||
//
|
||||
// FIXME: We should avoid loading the other referenced module maps (we already
|
||||
// have a parsed copy of their contents from the .pcm file) and thus not list
|
||||
// them here.
|
||||
//
|
||||
// FIXME: We should list a dependency on the explicitly specified .pcm files
|
||||
// (whether or not -module-file-deps is specified on the command line).
|
||||
//
|
||||
// EXPLICIT-FIXME-NOT: dependency-gen-
|
||||
// EXPLICIT-FIXME: {{.*}}/base.pcm
|
||||
//
|
||||
// EXPLICIT: {{^}}explicit.pcm:
|
||||
// EXPLICIT: {{.*}}/dependency-gen.modulemap
|
||||
// EXPLICIT: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: echo 'extern int a;' > %t/a.h
|
||||
// RUN: echo 'extern int b;' > %t/b.h
|
||||
// RUN: echo 'module a { header "a.h" header "b.h" }' > %t/modulemap
|
||||
|
||||
// We lazily check that the files referenced by an explicitly-specified .pcm
|
||||
// file exist. Test this by removing files and ensuring that the compilation
|
||||
// still succeeds.
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -I %t -emit-module -fmodule-name=a -x c++ %t/modulemap -o %t/a.pcm
|
||||
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
|
||||
// RUN: rm %t/modulemap
|
||||
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
|
||||
// RUN: rm %t/b.h
|
||||
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
|
||||
// RUN: rm %t/a.h
|
||||
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s -verify
|
||||
|
||||
#include "a.h" // expected-error {{file not found}}
|
||||
int x = b;
|
|
@ -179,6 +179,7 @@
|
|||
// CHECK-NO-FILE-INDIRECT: error: module file '{{.*}}a.pcm' not found
|
||||
// CHECK-NO-FILE-INDIRECT-NEXT: note: imported by module 'b' in '{{.*}}b.pcm'
|
||||
// CHECK-NO-FILE-INDIRECT-NEXT: note: imported by module 'c' in '{{.*}}c.pcm'
|
||||
// CHECK-NO-FILE-INDIRECT-NOT: note:
|
||||
|
||||
// -------------------------------
|
||||
// Check that we don't get upset if B's timestamp is newer than C's.
|
||||
|
@ -198,4 +199,6 @@
|
|||
// RUN: -fmodule-file=%t/c.pcm \
|
||||
// RUN: %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-MISMATCHED-B %s
|
||||
//
|
||||
// CHECK-MISMATCHED-B: fatal error: malformed or corrupted AST file: {{.*}}b.pcm": module file out of date
|
||||
// CHECK-MISMATCHED-B: fatal error: module file '{{.*}}b.pcm' is out of date and needs to be rebuilt
|
||||
// CHECK-MISMATCHED-B-NEXT: note: imported by module 'c'
|
||||
// CHECK-MISMATCHED-B-NOT: note:
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
#ifdef IMPLICIT
|
||||
|
||||
// expected-error@+1{{does not appear to be}}
|
||||
// expected-error@+1{{Module.pcm' is not a valid precompiled module file}}
|
||||
#import <Module/Module.h>
|
||||
#pragma clang __debug crash;
|
||||
|
||||
#else
|
||||
|
||||
// expected-error@+1{{does not appear to be}}
|
||||
// expected-error@+1{{Module.pcm' is not a valid precompiled module file}}
|
||||
@import Module;
|
||||
#pragma clang __debug crash;
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
// CHECK-BUILD: Inputs/relative-dep-gen-1.h
|
||||
// CHECK-BUILD: Inputs/relative-dep-gen-2.h
|
||||
// CHECK-USE: use.o:
|
||||
// CHECK-USE: Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
|
||||
// CHECK-USE: relative-dep-gen.cpp
|
||||
// CHECK-USE: Inputs/relative-dep-gen-1.h
|
||||
// CHECK-USE-DAG: Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
|
||||
// CHECK-USE-DAG: relative-dep-gen.cpp
|
||||
// CHECK-USE-DAG: Inputs/relative-dep-gen-1.h
|
||||
|
|
Loading…
Reference in New Issue