mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #24424 from harlanhaskins/an-absolutely-remarkable-thing
[ModuleInterface] Emit remarks when rebuilding from an interface
This commit is contained in:
@@ -18,8 +18,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if !(defined(DIAG) || (defined(ERROR) && defined(WARNING) && defined(NOTE)))
|
||||
# error Must define either DIAG or the set {ERROR,WARNING,NOTE}
|
||||
#if !(defined(DIAG) || (defined(ERROR) && defined(WARNING) && defined(NOTE) && \
|
||||
defined(REMARK)))
|
||||
# error Must define either DIAG or the set {ERROR,WARNING,NOTE,REMARK}
|
||||
#endif
|
||||
|
||||
#ifndef ERROR
|
||||
@@ -37,6 +38,11 @@
|
||||
DIAG(NOTE,ID,Options,Text,Signature)
|
||||
#endif
|
||||
|
||||
#ifndef REMARK
|
||||
# define REMARK(ID,Options,Text,Signature) \
|
||||
DIAG(REMARK,ID,Options,Text,Signature)
|
||||
#endif
|
||||
|
||||
WARNING(warning_no_such_sdk,none,
|
||||
"no such SDK: '%0'", (StringRef))
|
||||
|
||||
@@ -278,6 +284,20 @@ ERROR(error_extracting_flags_from_module_interface,none,
|
||||
ERROR(missing_dependency_of_module_interface,none,
|
||||
"missing dependency '%0' of module interface '%1': %2",
|
||||
(StringRef, StringRef, StringRef))
|
||||
REMARK(rebuilding_module_from_interface,none,
|
||||
"rebuilding module '%0' from interface '%1'", (StringRef, StringRef))
|
||||
NOTE(out_of_date_module_here,none,
|
||||
"%select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1'",
|
||||
(unsigned, StringRef))
|
||||
NOTE(module_interface_dependency_out_of_date,none,
|
||||
"dependency is out of date: '%0'",
|
||||
(StringRef))
|
||||
NOTE(compiled_module_invalid,none,
|
||||
"unable to load compiled module '%0'",
|
||||
(StringRef))
|
||||
NOTE(compiled_module_invalid_reason,none,
|
||||
"unable to load compiled module '%0': %1",
|
||||
(StringRef, StringRef))
|
||||
ERROR(error_extracting_dependencies_from_cached_module,none,
|
||||
"error extracting dependencies from cached module '%0'",
|
||||
(StringRef))
|
||||
@@ -289,6 +309,7 @@ ERROR(unknown_forced_module_loading_mode,none,
|
||||
# if defined(DIAG)
|
||||
# undef DIAG
|
||||
# endif
|
||||
# undef REMARK
|
||||
# undef NOTE
|
||||
# undef WARNING
|
||||
# undef ERROR
|
||||
|
||||
@@ -272,6 +272,10 @@ public:
|
||||
/// times) when compiling a module interface?
|
||||
bool SerializeModuleInterfaceDependencyHashes = false;
|
||||
|
||||
/// Should we warn if an imported module needed to be rebuilt from a
|
||||
/// module interface file?
|
||||
bool RemarkOnRebuildFromModuleInterface = false;
|
||||
|
||||
/// The different modes for validating TBD against the LLVM IR.
|
||||
enum class TBDValidationMode {
|
||||
Default, ///< Do the default validation for the current platform.
|
||||
|
||||
@@ -122,16 +122,18 @@ namespace swift {
|
||||
/// directory, and loading the serialized .swiftmodules from there.
|
||||
class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase {
|
||||
friend class unittest::ParseableInterfaceModuleLoaderTest;
|
||||
explicit ParseableInterfaceModuleLoader(ASTContext &ctx, StringRef cacheDir,
|
||||
StringRef prebuiltCacheDir,
|
||||
DependencyTracker *tracker,
|
||||
ModuleLoadingMode loadMode)
|
||||
explicit ParseableInterfaceModuleLoader(
|
||||
ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
|
||||
DependencyTracker *tracker, ModuleLoadingMode loadMode,
|
||||
bool RemarkOnRebuildFromInterface)
|
||||
: SerializedModuleLoaderBase(ctx, tracker, loadMode),
|
||||
CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir)
|
||||
CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
|
||||
RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface)
|
||||
{}
|
||||
|
||||
std::string CacheDir;
|
||||
std::string PrebuiltCacheDir;
|
||||
bool RemarkOnRebuildFromInterface;
|
||||
|
||||
std::error_code findModuleFilesInDirectory(
|
||||
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
|
||||
@@ -144,10 +146,12 @@ class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase {
|
||||
public:
|
||||
static std::unique_ptr<ParseableInterfaceModuleLoader>
|
||||
create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
|
||||
DependencyTracker *tracker, ModuleLoadingMode loadMode) {
|
||||
DependencyTracker *tracker, ModuleLoadingMode loadMode,
|
||||
bool RemarkOnRebuildFromInterface = false) {
|
||||
return std::unique_ptr<ParseableInterfaceModuleLoader>(
|
||||
new ParseableInterfaceModuleLoader(ctx, cacheDir, prebuiltCacheDir,
|
||||
tracker, loadMode));
|
||||
tracker, loadMode,
|
||||
RemarkOnRebuildFromInterface));
|
||||
}
|
||||
|
||||
/// Unconditionally build \p InPath (a swiftinterface file) to \p OutPath (as
|
||||
|
||||
@@ -388,6 +388,9 @@ def warn_long_expression_type_checking : Separate<["-"], "warn-long-expression-t
|
||||
def warn_long_expression_type_checking_EQ : Joined<["-"], "warn-long-expression-type-checking=">,
|
||||
Alias<warn_long_expression_type_checking>;
|
||||
|
||||
def Rmodule_interface_rebuild : Flag<["-"], "Rmodule-interface-rebuild">,
|
||||
HelpText<"Emits a remark if an imported module needs to be re-compiled from its module interface">;
|
||||
|
||||
def solver_expression_time_threshold_EQ : Joined<["-"], "solver-expression-time-threshold=">;
|
||||
|
||||
def solver_disable_shrink :
|
||||
|
||||
@@ -83,6 +83,9 @@ bool ArgsToFrontendOptionsConverter::convert(
|
||||
Opts.SerializeModuleInterfaceDependencyHashes |=
|
||||
Args.hasArg(OPT_serialize_module_interface_dependency_hashes);
|
||||
|
||||
Opts.RemarkOnRebuildFromModuleInterface |=
|
||||
Args.hasArg(OPT_Rmodule_interface_rebuild);
|
||||
|
||||
computePrintStatsOptions();
|
||||
computeDebugTimeOptions();
|
||||
computeTBDOptions();
|
||||
|
||||
@@ -246,6 +246,9 @@ bool DiagnosticVerifier::verifyFile(unsigned BufferID,
|
||||
} else if (MatchStart.startswith("expected-error")) {
|
||||
ExpectedClassification = llvm::SourceMgr::DK_Error;
|
||||
MatchStart = MatchStart.substr(strlen("expected-error"));
|
||||
} else if (MatchStart.startswith("expected-remark")) {
|
||||
ExpectedClassification = llvm::SourceMgr::DK_Remark;
|
||||
MatchStart = MatchStart.substr(strlen("expected-remark"));
|
||||
} else
|
||||
continue;
|
||||
|
||||
|
||||
@@ -339,13 +339,11 @@ bool CompilerInstance::setUpModuleLoaders() {
|
||||
if (MLM != ModuleLoadingMode::OnlySerialized) {
|
||||
auto const &Clang = clangImporter->getClangInstance();
|
||||
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);
|
||||
StringRef PrebuiltModuleCachePath =
|
||||
Invocation.getFrontendOptions().PrebuiltModuleCachePath;
|
||||
auto PIML = ParseableInterfaceModuleLoader::create(*Context,
|
||||
ModuleCachePath,
|
||||
PrebuiltModuleCachePath,
|
||||
getDependencyTracker(),
|
||||
MLM);
|
||||
auto &FEOpts = Invocation.getFrontendOptions();
|
||||
StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath;
|
||||
auto PIML = ParseableInterfaceModuleLoader::create(
|
||||
*Context, ModuleCachePath, PrebuiltModuleCachePath,
|
||||
getDependencyTracker(), MLM, FEOpts.RemarkOnRebuildFromModuleInterface);
|
||||
Context->addModuleLoader(std::move(PIML));
|
||||
}
|
||||
Context->addModuleLoader(std::move(SML));
|
||||
|
||||
@@ -621,6 +621,100 @@ public:
|
||||
|
||||
namespace {
|
||||
|
||||
/// Keeps track of the various reasons the module interface loader needed to
|
||||
/// fall back and rebuild a module from its interface.
|
||||
struct ModuleRebuildInfo {
|
||||
enum class ModuleKind {
|
||||
Normal,
|
||||
Cached,
|
||||
Forwarding,
|
||||
Prebuilt
|
||||
};
|
||||
struct OutOfDateModule {
|
||||
std::string path;
|
||||
Optional<serialization::Status> serializationStatus;
|
||||
ModuleKind kind;
|
||||
SmallVector<std::string, 10> outOfDateDependencies;
|
||||
};
|
||||
SmallVector<OutOfDateModule, 3> outOfDateModules;
|
||||
|
||||
OutOfDateModule &getOrInsertOutOfDateModule(StringRef path) {
|
||||
for (auto &mod : outOfDateModules) {
|
||||
if (mod.path == path) return mod;
|
||||
}
|
||||
outOfDateModules.push_back({path, None, ModuleKind::Normal, {}});
|
||||
return outOfDateModules.back();
|
||||
}
|
||||
|
||||
/// Sets the kind of a module that failed to load.
|
||||
void setModuleKind(StringRef path, ModuleKind kind) {
|
||||
getOrInsertOutOfDateModule(path).kind = kind;
|
||||
}
|
||||
|
||||
/// Sets the serialization status of the module at \c path. If this is
|
||||
/// anything other than \c Valid, a note will be added stating why the module
|
||||
/// was invalid.
|
||||
void setSerializationStatus(StringRef path, serialization::Status status) {
|
||||
getOrInsertOutOfDateModule(path).serializationStatus = status;
|
||||
}
|
||||
|
||||
/// Registers an out-of-date dependency at \c depPath for the module
|
||||
/// at \c modulePath.
|
||||
void addOutOfDateDependency(StringRef modulePath, StringRef depPath) {
|
||||
getOrInsertOutOfDateModule(modulePath)
|
||||
.outOfDateDependencies.push_back(depPath);
|
||||
}
|
||||
|
||||
const char *invalidModuleReason(serialization::Status status) {
|
||||
using namespace serialization;
|
||||
switch (status) {
|
||||
case Status::FormatTooOld:
|
||||
return "compiled with an older version of the compiler";
|
||||
case Status::FormatTooNew:
|
||||
return "compiled with a newer version of the compiler";
|
||||
case Status::Malformed:
|
||||
return "malformed";
|
||||
case Status::TargetIncompatible:
|
||||
return "compiled for a different target platform";
|
||||
case Status::TargetTooNew:
|
||||
return "target platform newer than current platform";
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a diagnostic for all out-of-date compiled or forwarding modules
|
||||
/// encountered while trying to load a module.
|
||||
void diagnose(ASTContext &ctx, SourceLoc loc, StringRef moduleName,
|
||||
StringRef interfacePath) {
|
||||
ctx.Diags.diagnose(loc, diag::rebuilding_module_from_interface,
|
||||
moduleName, interfacePath);
|
||||
|
||||
// We may have found multiple failing modules, that failed for different
|
||||
// reasons. Emit a note for each of them.
|
||||
for (auto &mod : outOfDateModules) {
|
||||
ctx.Diags.diagnose(loc, diag::out_of_date_module_here,
|
||||
(unsigned)mod.kind, mod.path);
|
||||
|
||||
// Diagnose any out-of-date dependencies in this module.
|
||||
for (auto &dep : mod.outOfDateDependencies) {
|
||||
ctx.Diags.diagnose(loc, diag::module_interface_dependency_out_of_date,
|
||||
dep);
|
||||
}
|
||||
|
||||
// If there was a compiled module that wasn't able to be read, diagnose
|
||||
// the reason we couldn't read it.
|
||||
if (auto status = mod.serializationStatus) {
|
||||
if (auto reason = invalidModuleReason(*status)) {
|
||||
ctx.Diags.diagnose(loc, diag::compiled_module_invalid_reason,
|
||||
mod.path, reason);
|
||||
} else {
|
||||
ctx.Diags.diagnose(loc, diag::compiled_module_invalid, mod.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Handles the details of loading parseable interfaces as modules, and will
|
||||
/// do the necessary lookup to determine if we should be loading from the
|
||||
/// normal cache, the prebuilt cache, a module adjacent to the interface, or
|
||||
@@ -631,6 +725,7 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
ASTContext &ctx;
|
||||
llvm::vfs::FileSystem &fs;
|
||||
DiagnosticEngine &diags;
|
||||
ModuleRebuildInfo rebuildInfo;
|
||||
const StringRef modulePath;
|
||||
const std::string interfacePath;
|
||||
const StringRef moduleName;
|
||||
@@ -639,17 +734,20 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
const SourceLoc diagnosticLoc;
|
||||
DependencyTracker *const dependencyTracker;
|
||||
const ModuleLoadingMode loadMode;
|
||||
const bool remarkOnRebuildFromInterface;
|
||||
|
||||
ParseableInterfaceModuleLoaderImpl(
|
||||
ASTContext &ctx, StringRef modulePath, StringRef interfacePath,
|
||||
StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir,
|
||||
SourceLoc diagLoc, DependencyTracker *dependencyTracker = nullptr,
|
||||
SourceLoc diagLoc, bool remarkOnRebuildFromInterface,
|
||||
DependencyTracker *dependencyTracker = nullptr,
|
||||
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized)
|
||||
: ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags),
|
||||
modulePath(modulePath), interfacePath(interfacePath),
|
||||
moduleName(moduleName), prebuiltCacheDir(prebuiltCacheDir),
|
||||
cacheDir(cacheDir), diagnosticLoc(diagLoc),
|
||||
dependencyTracker(dependencyTracker), loadMode(loadMode) {}
|
||||
dependencyTracker(dependencyTracker), loadMode(loadMode),
|
||||
remarkOnRebuildFromInterface(remarkOnRebuildFromInterface) {}
|
||||
|
||||
/// Construct a cache key for the .swiftmodule being generated. There is a
|
||||
/// balance to be struck here between things that go in the cache key and
|
||||
@@ -745,13 +843,15 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
|
||||
// Check if all the provided file dependencies are up-to-date compared to
|
||||
// what's currently on disk.
|
||||
bool dependenciesAreUpToDate(ArrayRef<FileDependency> deps) {
|
||||
bool dependenciesAreUpToDate(StringRef modulePath,
|
||||
ArrayRef<FileDependency> deps) {
|
||||
SmallString<128> SDKRelativeBuffer;
|
||||
for (auto &in : deps) {
|
||||
StringRef fullPath = getFullDependencyPath(in, SDKRelativeBuffer);
|
||||
if (!dependencyIsUpToDate(in, fullPath)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath
|
||||
<< " is directly out of date\n");
|
||||
rebuildInfo.addOutOfDateDependency(modulePath, fullPath);
|
||||
return false;
|
||||
}
|
||||
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n");
|
||||
@@ -762,15 +862,18 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
// Check that the output .swiftmodule file is at least as new as all the
|
||||
// dependencies it read when it was built last time.
|
||||
bool serializedASTBufferIsUpToDate(
|
||||
const llvm::MemoryBuffer &buf, SmallVectorImpl<FileDependency> &allDeps) {
|
||||
StringRef path, const llvm::MemoryBuffer &buf,
|
||||
SmallVectorImpl<FileDependency> &allDeps) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << modulePath << "\n");
|
||||
auto validationInfo = serialization::validateSerializedAST(
|
||||
buf.getBuffer(), /*ExtendedValidationInfo=*/nullptr, &allDeps);
|
||||
|
||||
if (validationInfo.status != serialization::Status::Valid)
|
||||
if (validationInfo.status != serialization::Status::Valid) {
|
||||
rebuildInfo.setSerializationStatus(path, validationInfo.status);
|
||||
return false;
|
||||
}
|
||||
|
||||
return dependenciesAreUpToDate(allDeps);
|
||||
return dependenciesAreUpToDate(path, allDeps);
|
||||
}
|
||||
|
||||
// Check that the output .swiftmodule file is at least as new as all the
|
||||
@@ -782,14 +885,15 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
if (!OutBuf)
|
||||
return false;
|
||||
moduleBuffer = std::move(*OutBuf);
|
||||
return serializedASTBufferIsUpToDate(*moduleBuffer, AllDeps);
|
||||
return serializedASTBufferIsUpToDate(modulePath, *moduleBuffer, AllDeps);
|
||||
}
|
||||
|
||||
// Check that a "forwarding" .swiftmodule file is at least as new as all the
|
||||
// dependencies it read when it was built last time. Requires that the
|
||||
// forwarding module has been loaded from disk.
|
||||
bool forwardingModuleIsUpToDate(
|
||||
const ForwardingModule &fwd, SmallVectorImpl<FileDependency> &deps,
|
||||
StringRef path, const ForwardingModule &fwd,
|
||||
SmallVectorImpl<FileDependency> &deps,
|
||||
std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
|
||||
// First, make sure the underlying module path exists and is valid.
|
||||
auto modBuf = fs.getBufferForFile(fwd.underlyingModulePath);
|
||||
@@ -805,7 +909,7 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
dep.path, /*isSDKRelative=*/false, dep.size,
|
||||
dep.lastModificationTime));
|
||||
}
|
||||
if (!dependenciesAreUpToDate(deps))
|
||||
if (!dependenciesAreUpToDate(path, deps))
|
||||
return false;
|
||||
|
||||
moduleBuffer = std::move(*modBuf);
|
||||
@@ -924,6 +1028,7 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
llvm_unreachable("module interface loader should not have been created");
|
||||
}
|
||||
|
||||
|
||||
// First, check the cached module path. Whatever's in this cache represents
|
||||
// the most up-to-date knowledge we have about the module.
|
||||
if (auto cachedBufOrError = fs.getBufferForFile(cachedOutputPath)) {
|
||||
@@ -939,7 +1044,8 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
if (isForwardingModule) {
|
||||
if (auto forwardingModule = ForwardingModule::load(*buf)) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
|
||||
if (forwardingModuleIsUpToDate(*forwardingModule, deps,
|
||||
if (forwardingModuleIsUpToDate(cachedOutputPath,
|
||||
*forwardingModule, deps,
|
||||
moduleBuffer)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date forwarding module at "
|
||||
<< cachedOutputPath << "\n");
|
||||
@@ -949,15 +1055,19 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date forwarding module at "
|
||||
<< cachedOutputPath << "\n");
|
||||
rebuildInfo.setModuleKind(cachedOutputPath,
|
||||
ModuleRebuildInfo::ModuleKind::Forwarding);
|
||||
}
|
||||
// Otherwise, check if the AST buffer itself is up to date.
|
||||
} else if (serializedASTBufferIsUpToDate(*buf, deps)) {
|
||||
} else if (serializedASTBufferIsUpToDate(cachedOutputPath, *buf, deps)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date cached module at "
|
||||
<< cachedOutputPath << "\n");
|
||||
return DiscoveredModule::normal(cachedOutputPath, std::move(buf));
|
||||
} else {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date cached module at "
|
||||
<< cachedOutputPath << "\n");
|
||||
rebuildInfo.setModuleKind(cachedOutputPath,
|
||||
ModuleRebuildInfo::ModuleKind::Cached);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,6 +1093,8 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
} else {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date prebuilt module at "
|
||||
<< path->str() << "\n");
|
||||
rebuildInfo.setModuleKind(*path,
|
||||
ModuleRebuildInfo::ModuleKind::Prebuilt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,7 +1111,8 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
|
||||
auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
|
||||
if (adjacentModuleBuffer) {
|
||||
if (serializedASTBufferIsUpToDate(*adjacentModuleBuffer.get(), deps)) {
|
||||
if (serializedASTBufferIsUpToDate(modulePath, *adjacentModuleBuffer.get(),
|
||||
deps)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
|
||||
<< modulePath
|
||||
<< "; deferring to serialized module loader\n");
|
||||
@@ -1022,6 +1135,8 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
} else {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
|
||||
<< modulePath << "\n");
|
||||
rebuildInfo.setModuleKind(modulePath,
|
||||
ModuleRebuildInfo::ModuleKind::Normal);
|
||||
}
|
||||
} else if (adjacentModuleBuffer.getError() != notFoundError) {
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
@@ -1159,7 +1274,15 @@ class ParseableInterfaceModuleLoaderImpl {
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
|
||||
// We didn't discover a module corresponding to this interface. Build one.
|
||||
|
||||
// We didn't discover a module corresponding to this interface.
|
||||
|
||||
// Diagnose that we didn't find a loadable module, if we were asked to.
|
||||
if (remarkOnRebuildFromInterface) {
|
||||
rebuildInfo.diagnose(ctx, diagnosticLoc, moduleName,
|
||||
interfacePath);
|
||||
}
|
||||
|
||||
if (builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true,
|
||||
&moduleBuffer))
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
@@ -1214,7 +1337,8 @@ std::error_code ParseableInterfaceModuleLoader::findModuleFilesInDirectory(
|
||||
// Create an instance of the Impl to do the heavy lifting.
|
||||
ParseableInterfaceModuleLoaderImpl Impl(
|
||||
Ctx, ModPath, InPath, ModuleID.first.str(),
|
||||
CacheDir, PrebuiltCacheDir, ModuleID.second, dependencyTracker,
|
||||
CacheDir, PrebuiltCacheDir, ModuleID.second,
|
||||
RemarkOnRebuildFromInterface, dependencyTracker,
|
||||
LoadMode);
|
||||
|
||||
// Ask the impl to find us a module that we can load or give us an error
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// RUN: %empty-directory(%t/ModuleCache)
|
||||
// RUN: %empty-directory(%t/Build)
|
||||
// RUN: %empty-directory(%t/PrebuiltCache)
|
||||
|
||||
// 1. Create a dummy module
|
||||
// RUN: echo 'public func publicFunction() {}' > %t/TestModule.swift
|
||||
|
||||
// 2. Create an interface for it
|
||||
// RUN: %target-swift-frontend -typecheck %t/TestModule.swift -emit-module-interface-path %t/Build/TestModule.swiftinterface -swift-version 5
|
||||
|
||||
// 3. Create an empty .swiftmodule, which will force recompiling from the interface
|
||||
// RUN: touch %t/Build/TestModule.swiftmodule
|
||||
|
||||
// 4. Try to import the malformed compiled module
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -I %t/Build -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
|
||||
|
||||
import TestModule // expected-remark {{rebuilding module 'TestModule' from interface}}
|
||||
// expected-note @-1 {{is out of date}}
|
||||
// expected-note @-2 {{malformed}}
|
||||
@@ -0,0 +1,21 @@
|
||||
// RUN: %empty-directory(%t/ModuleCache)
|
||||
// RUN: %empty-directory(%t/Build)
|
||||
|
||||
// 1. Create a dummy module
|
||||
// RUN: echo 'public func publicFunction() {}' > %t/TestModule.swift
|
||||
|
||||
// 2. Create an interface for it
|
||||
// RUN: %target-swift-frontend -typecheck %t/TestModule.swift -emit-module-interface-path %t/Build/TestModule.swiftinterface -swift-version 5
|
||||
|
||||
// 3. Try to import the interface, which will pass and create a cached module
|
||||
// RUN: %target-swift-frontend -typecheck %s -I %t/Build -module-cache-path %t/ModuleCache
|
||||
|
||||
// 4. Touch the interface so the cached module is no longer up-to-date
|
||||
// RUN: touch %t/Build/TestModule.swiftinterface
|
||||
|
||||
// 5. Try to import the now out-of-date cached module
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -I %t/Build -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache -Xllvm -debug-only=textual-module-interface
|
||||
|
||||
import TestModule // expected-remark {{rebuilding module 'TestModule' from interface}}
|
||||
// expected-note @-1 {{cached module is out of date}}
|
||||
// expected-note @-2 {{dependency is out of date}}
|
||||
@@ -0,0 +1,21 @@
|
||||
// RUN: %empty-directory(%t/ModuleCache)
|
||||
// RUN: %empty-directory(%t/Build)
|
||||
|
||||
// 1. Create a dummy module
|
||||
// RUN: echo 'public func publicFunction() {}' > %t/TestModule.swift
|
||||
|
||||
// 2. Create an interface for it
|
||||
// RUN: %target-swift-frontend -typecheck %t/TestModule.swift -emit-module-interface-path %t/Build/TestModule.swiftinterface -swift-version 5
|
||||
|
||||
// 3. Build the .swiftinterface to a .swiftmodule, which will have a dependency on the interface
|
||||
// RUN: %target-swift-frontend -compile-module-from-interface -o %t/Build/TestModule.swiftmodule %t/Build/TestModule.swiftinterface
|
||||
|
||||
// 4. Touch the interface so the module is no longer up-to-date
|
||||
// RUN: touch %t/Build/TestModule.swiftinterface
|
||||
|
||||
// 5. Try to import the out-of-date compiled module
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -I %t/Build -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
|
||||
|
||||
import TestModule // expected-remark {{rebuilding module 'TestModule' from interface}}
|
||||
// expected-note @-1 {{compiled module is out of date}}
|
||||
// expected-note @-2 {{dependency is out of date}}
|
||||
@@ -0,0 +1,32 @@
|
||||
// RUN: %empty-directory(%t/ModuleCache)
|
||||
// RUN: %empty-directory(%t/Build)
|
||||
// RUN: %empty-directory(%t/PrebuiltCache)
|
||||
|
||||
// 1. Create a dummy module
|
||||
// RUN: echo 'public func publicFunction() {}' > %t/TestModule.swift
|
||||
|
||||
// 2. Create an interface for it
|
||||
// RUN: %target-swift-frontend -typecheck %t/TestModule.swift -emit-module-interface-path %t/Build/TestModule.swiftinterface -swift-version 5
|
||||
|
||||
// 3. Build the .swiftinterface to a .swiftmodule in the prebuilt cache, which will have a dependency on the interface
|
||||
// RUN: %target-swift-frontend -compile-module-from-interface %t/Build/TestModule.swiftinterface -o %t/PrebuiltCache/TestModule.swiftmodule
|
||||
|
||||
// 5. Try to import the prebuilt module (this should pass)
|
||||
// RUN: %target-swift-frontend -typecheck %s -I %t/Build -sdk %t -prebuilt-module-cache-path %t/PrebuiltCache -module-cache-path %t/ModuleCache
|
||||
|
||||
// 6. Make sure we installed a forwarding module in the cache
|
||||
// RUN: %{python} %S/../Inputs/check-is-forwarding-module.py %t/ModuleCache/TestModule-*.swiftmodule
|
||||
|
||||
// 7. Modify the interface so the forwarding module and prebuilt modules are no longer up-to-date
|
||||
// RUN: echo ' ' >> %t/Build/TestModule.swiftinterface
|
||||
|
||||
// 8. Try to import the now out-of-date forwarding module, which will fail.
|
||||
// It will also fail to load the prebuilt module after the forwarding module
|
||||
// is rejected, meaning we'll get a second set of notes about the prebuilt module.
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -I %t/Build -Rmodule-interface-rebuild -sdk %t -prebuilt-module-cache-path %t/PrebuiltCache -module-cache-path %t/ModuleCache
|
||||
|
||||
import TestModule // expected-remark {{rebuilding module 'TestModule' from interface}}
|
||||
// expected-note @-1 {{forwarding module is out of date}}
|
||||
// expected-note @-2 {{dependency is out of date}}
|
||||
// expected-note @-3 {{prebuilt module is out of date}}
|
||||
// expected-note @-4 {{dependency is out of date}}
|
||||
Reference in New Issue
Block a user