[ParseableInterface] Fixes and tests for Graydon's fallback work

This commit is contained in:
Jordan Rose
2018-11-29 11:02:16 -08:00
parent f7200e87bd
commit 7d30f9cb1f
8 changed files with 350 additions and 44 deletions

View File

@@ -51,12 +51,6 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
(!ModuleBuffer && !ModuleDocBuffer)) &&
"Module and Module Doc buffer must both be initialized or NULL");
// The SerializedModuleLoaderBase implementation here only knows how to do a
// serialized (not parseable) module-load; this is valid behaviour in all
// ModuleLoadingModes except OnlyParseable mode, where it is disabled.
if (LoadMode == ModuleLoadingMode::OnlyParseable)
return std::make_error_code(std::errc::not_supported);
clang::vfs::FileSystem &FS = *Ctx.SourceMgr.getFileSystem();
// Try to open the module file first. If we fail, don't even look for the
@@ -99,12 +93,24 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
return std::error_code();
}
static void addDiagnosticInfoForArchitectureMismatch(ASTContext &ctx,
SourceLoc sourceLocation,
StringRef moduleName,
StringRef archName,
StringRef directoryPath) {
clang::vfs::FileSystem &fs = *ctx.SourceMgr.getFileSystem();
std::error_code SerializedModuleLoader::openModuleFiles(
StringRef DirName, StringRef ModuleFilename, StringRef ModuleDocFilename,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
llvm::SmallVectorImpl<char> &Scratch) {
if (LoadMode == ModuleLoadingMode::OnlyParseable)
return std::make_error_code(std::errc::not_supported);
return SerializedModuleLoaderBase::openModuleFiles(DirName, ModuleFilename,
ModuleDocFilename,
ModuleBuffer,
ModuleDocBuffer, Scratch);
}
bool SerializedModuleLoader::maybeDiagnoseArchitectureMismatch(
SourceLoc sourceLocation, StringRef moduleName, StringRef archName,
StringRef directoryPath) {
clang::vfs::FileSystem &fs = *Ctx.SourceMgr.getFileSystem();
std::error_code errorCode;
std::string foundArchs;
@@ -113,7 +119,7 @@ static void addDiagnosticInfoForArchitectureMismatch(ASTContext &ctx,
directoryIterator != endIterator;
directoryIterator.increment(errorCode)) {
if (errorCode)
return;
return false;
StringRef filePath = directoryIterator->getName();
StringRef extension = llvm::sys::path::extension(filePath);
if (file_types::lookupTypeForExtension(extension) ==
@@ -128,11 +134,12 @@ static void addDiagnosticInfoForArchitectureMismatch(ASTContext &ctx,
// Maybe this swiftmodule directory only contains swiftinterfaces, or
// maybe something else is going on. Regardless, we shouldn't emit a
// possibly incorrect diagnostic.
return;
return false;
}
ctx.Diags.diagnose(sourceLocation, diag::sema_no_import_arch, moduleName,
Ctx.Diags.diagnose(sourceLocation, diag::sema_no_import_arch, moduleName,
archName, foundArchs);
return true;
}
bool
@@ -164,29 +171,43 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
archDocFile += file_types::getExtension(file_types::TY_SwiftModuleDocFile);
}
auto &fs = *Ctx.SourceMgr.getFileSystem();
isFramework = false;
// Declare some reusable buffers up front; if we end up spilling onto the
// heap once, we're likely to do so again.
llvm::SmallString<128> scratch;
llvm::SmallString<128> currPath;
isFramework = false;
for (auto path : Ctx.SearchPathOpts.ImportSearchPaths) {
auto err = openModuleFiles(path,
std::error_code result;
currPath = path;
llvm::sys::path::append(currPath, moduleFilename.str());
llvm::ErrorOr<clang::vfs::Status> statResult = fs.status(currPath);
if (statResult && statResult->isDirectory()) {
// A .swiftmodule directory contains architecture-specific files.
result = openModuleFiles(currPath,
archFile.str(), archDocFile.str(),
moduleBuffer, moduleDocBuffer,
scratch);
if (result == std::errc::no_such_file_or_directory) {
if (maybeDiagnoseArchitectureMismatch(moduleID.second, moduleName,
archName, currPath)) {
return false;
}
}
} else {
// We can't just return the error; the path we're looking for might not
// be "Foo.swiftmodule".
result = openModuleFiles(path,
moduleFilename.str(), moduleDocFilename.str(),
moduleBuffer, moduleDocBuffer,
scratch);
if (err == std::errc::is_a_directory) {
currPath = path;
llvm::sys::path::append(currPath, moduleFilename.str());
err = openModuleFiles(currPath,
archFile.str(), archDocFile.str(),
moduleBuffer, moduleDocBuffer,
scratch);
if (err == std::errc::no_such_file_or_directory) {
addDiagnosticInfoForArchitectureMismatch(
Ctx, moduleID.second, moduleName, archName, currPath);
return false;
}
}
if (!err)
if (!result)
return true;
}
@@ -200,19 +221,21 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
llvm::sys::path::append(currPath, moduleFramework.str());
// Check if the framework directory exists
auto &fs = *Ctx.SourceMgr.getFileSystem();
if (!fs.exists(currPath)) {
return false;
}
// Frameworks always use architecture-specific files within a .swiftmodule
// directory.
llvm::sys::path::append(currPath, "Modules", moduleFilename.str());
auto err = openModuleFiles(currPath, archFile.str(), archDocFile.str(),
moduleBuffer, moduleDocBuffer, scratch);
if (err == std::errc::no_such_file_or_directory) {
addDiagnosticInfoForArchitectureMismatch(
Ctx, moduleID.second, moduleName, archName, currPath);
return false;
if (maybeDiagnoseArchitectureMismatch(moduleID.second, moduleName,
archName, currPath)) {
return false;
}
}
return !err;