mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Remove symbolic import mode
Importing C++ class templates in symbolic mode has proven to be problematic in interaction with other compiler features, and it isn't used widely. This change removes the feature. rdar://150528798
This commit is contained in:
@@ -426,199 +426,6 @@ emitDataForSwiftSerializedModule(ModuleDecl *module,
|
||||
const PathRemapper &pathRemapper,
|
||||
SourceFile *initialFile);
|
||||
|
||||
static void
|
||||
appendSymbolicInterfaceToIndexStorePath(SmallVectorImpl<char> &resultingPath) {
|
||||
llvm::sys::path::append(resultingPath, "interfaces");
|
||||
}
|
||||
|
||||
static llvm::Error initSymbolicInterfaceStorePath(StringRef storePath) {
|
||||
SmallString<128> subPath = storePath;
|
||||
appendSymbolicInterfaceToIndexStorePath(subPath);
|
||||
std::error_code ec = llvm::sys::fs::create_directories(subPath);
|
||||
if (ec)
|
||||
return llvm::errorCodeToError(ec);
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
static void appendSymbolicInterfaceClangModuleFilename(
|
||||
StringRef filePath, SmallVectorImpl<char> &resultingPath) {
|
||||
llvm::sys::path::append(resultingPath, llvm::sys::path::filename(filePath));
|
||||
StringRef extension = ".symbolicswiftinterface";
|
||||
resultingPath.append(extension.begin(), extension.end());
|
||||
}
|
||||
|
||||
// FIXME (Alex): Share code with IndexUnitWriter in LLVM after refactoring it.
|
||||
static llvm::Expected<bool>
|
||||
isFileUpToDateForOutputFile(StringRef filePath, StringRef timeCompareFilePath) {
|
||||
auto makeError = [](StringRef path, std::error_code ec) -> llvm::Error {
|
||||
std::string error;
|
||||
llvm::raw_string_ostream(error)
|
||||
<< "could not access path '" << path << "': " << ec.message();
|
||||
return llvm::createStringError(ec, error.c_str());
|
||||
};
|
||||
llvm::sys::fs::file_status unitStat;
|
||||
if (std::error_code ec = llvm::sys::fs::status(filePath, unitStat)) {
|
||||
if (ec != std::errc::no_such_file_or_directory && ec != llvm::errc::delete_pending)
|
||||
return makeError(filePath, ec);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timeCompareFilePath.empty())
|
||||
return true;
|
||||
|
||||
llvm::sys::fs::file_status compareStat;
|
||||
if (std::error_code ec =
|
||||
llvm::sys::fs::status(timeCompareFilePath, compareStat)) {
|
||||
if (ec != std::errc::no_such_file_or_directory && ec != llvm::errc::delete_pending)
|
||||
return makeError(timeCompareFilePath, ec);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true (unit is up-to-date) if the file to compare is older than the
|
||||
// unit file.
|
||||
return compareStat.getLastModificationTime() <=
|
||||
unitStat.getLastModificationTime();
|
||||
}
|
||||
|
||||
/// Emit the symbolic swift interface file for an imported Clang module into the
|
||||
/// index store directory.
|
||||
///
|
||||
/// The swift interface file is emitted only when it doesn't exist yet, or when
|
||||
/// the PCM for the Clang module has been updated.
|
||||
///
|
||||
/// System modules without the 'cplusplus' requirement are not emitted.
|
||||
static void emitSymbolicInterfaceForClangModule(
|
||||
ClangModuleUnit *clangModUnit, ModuleDecl *M,
|
||||
const clang::Module *clangModule, StringRef indexStorePath,
|
||||
const clang::CompilerInstance &clangCI, DiagnosticEngine &diags) {
|
||||
if (!M->getASTContext().LangOpts.EnableCXXInterop)
|
||||
return;
|
||||
// Skip system modules without an explicit 'cplusplus' requirement.
|
||||
bool isSystem = clangModUnit->isSystemModule();
|
||||
if (isSystem && !importer::requiresCPlusPlus(clangModule))
|
||||
return;
|
||||
|
||||
// Make sure the `interfaces` directory is created.
|
||||
if (auto err = initSymbolicInterfaceStorePath(indexStorePath)) {
|
||||
llvm::handleAllErrors(std::move(err), [&](const llvm::ECError &ec) {
|
||||
diags.diagnose(SourceLoc(), diag::error_create_symbolic_interfaces_dir,
|
||||
ec.convertToErrorCode().message());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
auto moduleRef = clangModule->getASTFile();
|
||||
if (!moduleRef)
|
||||
return;
|
||||
|
||||
// Determine the output name for the symbolic interface file.
|
||||
clang::serialization::ModuleFile *ModFile =
|
||||
clangCI.getASTReader()->getModuleManager().lookup(*moduleRef);
|
||||
assert(ModFile && "no module file loaded for module ?");
|
||||
SmallString<128> interfaceOutputPath = indexStorePath;
|
||||
appendSymbolicInterfaceToIndexStorePath(interfaceOutputPath);
|
||||
appendSymbolicInterfaceClangModuleFilename(ModFile->FileName,
|
||||
interfaceOutputPath);
|
||||
|
||||
// Check if the symbolic interface file is already up to date.
|
||||
std::string error;
|
||||
auto upToDate =
|
||||
isFileUpToDateForOutputFile(interfaceOutputPath, ModFile->FileName);
|
||||
if (!upToDate) {
|
||||
llvm::handleAllErrors(
|
||||
upToDate.takeError(), [&](const llvm::StringError &ec) {
|
||||
diags.diagnose(SourceLoc(),
|
||||
diag::error_symbolic_interfaces_failed_status_check,
|
||||
ec.getMessage());
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (M->getASTContext().LangOpts.EnableIndexingSystemModuleRemarks) {
|
||||
diags.diagnose(SourceLoc(), diag::remark_emitting_symbolic_interface_module,
|
||||
interfaceOutputPath, *upToDate);
|
||||
}
|
||||
if (*upToDate)
|
||||
return;
|
||||
|
||||
// Output the interface to a temporary file first.
|
||||
SmallString<128> tempOutputPath = interfaceOutputPath;
|
||||
tempOutputPath += "-%%%%%%%%";
|
||||
int tempFD;
|
||||
if (llvm::sys::fs::createUniqueFile(tempOutputPath.str(), tempFD,
|
||||
tempOutputPath)) {
|
||||
llvm::raw_string_ostream errOS(error);
|
||||
errOS << "failed to create temporary file: " << tempOutputPath;
|
||||
diags.diagnose(SourceLoc(), diag::error_write_symbolic_interface,
|
||||
errOS.str());
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::raw_fd_ostream os(tempFD, /*shouldClose=*/true);
|
||||
StreamPrinter printer(os);
|
||||
ide::printSymbolicSwiftClangModuleInterface(M, printer, clangModule);
|
||||
os.close();
|
||||
|
||||
if (os.has_error()) {
|
||||
llvm::raw_string_ostream errOS(error);
|
||||
errOS << "failed to write '" << tempOutputPath
|
||||
<< "': " << os.error().message();
|
||||
diags.diagnose(SourceLoc(), diag::error_write_symbolic_interface,
|
||||
errOS.str());
|
||||
os.clear_error();
|
||||
llvm::sys::fs::remove(tempOutputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the resulting output to the destination symbolic interface file.
|
||||
std::error_code ec = llvm::sys::fs::rename(
|
||||
/*from=*/tempOutputPath, /*to=*/interfaceOutputPath);
|
||||
if (ec) {
|
||||
llvm::raw_string_ostream errOS(error);
|
||||
errOS << "failed to rename '" << tempOutputPath << "' to '"
|
||||
<< interfaceOutputPath << "': " << ec.message();
|
||||
diags.diagnose(SourceLoc(), diag::error_write_symbolic_interface,
|
||||
errOS.str());
|
||||
llvm::sys::fs::remove(tempOutputPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void emitTransitiveClangSymbolicInterfacesForSwiftModuleImports(
|
||||
ArrayRef<ImportedModule> imports, StringRef indexStorePath,
|
||||
const clang::CompilerInstance &clangCI, DiagnosticEngine &diags) {
|
||||
auto &fileMgr = clangCI.getFileManager();
|
||||
for (auto &import : imports) {
|
||||
ModuleDecl *mod = import.importedModule;
|
||||
if (mod->isOnoneSupportModule())
|
||||
continue; // ignore the Onone support library.
|
||||
if (mod->isSwiftShimsModule())
|
||||
continue;
|
||||
|
||||
for (auto *FU : mod->getFiles()) {
|
||||
switch (FU->getKind()) {
|
||||
default:
|
||||
break;
|
||||
case FileUnitKind::SerializedAST:
|
||||
case FileUnitKind::DWARFModule:
|
||||
case FileUnitKind::ClangModule: {
|
||||
auto *LFU = cast<LoadedFile>(FU);
|
||||
if (auto F = fileMgr.getFile(LFU->getFilename())) {
|
||||
if (FU->getKind() == FileUnitKind::ClangModule) {
|
||||
auto clangModUnit = cast<ClangModuleUnit>(LFU);
|
||||
if (auto clangMod = clangModUnit->getUnderlyingClangModule()) {
|
||||
// Emit the symbolic interface file in addition to index data.
|
||||
emitSymbolicInterfaceForClangModule(
|
||||
clangModUnit, mod, clangMod, indexStorePath, clangCI, diags);
|
||||
}
|
||||
}
|
||||
// FIXME: We should keep recursing here into other Swift modules.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void addModuleDependencies(ArrayRef<ImportedModule> imports,
|
||||
StringRef indexStorePath,
|
||||
bool indexClangModules,
|
||||
@@ -688,11 +495,6 @@ static void addModuleDependencies(ArrayRef<ImportedModule> imports,
|
||||
if (shouldIndexModule)
|
||||
clang::index::emitIndexDataForModuleFile(clangMod,
|
||||
clangCI, unitWriter);
|
||||
// Emit the symbolic interface file in addition to index data.
|
||||
if (indexClangModules)
|
||||
emitSymbolicInterfaceForClangModule(clangModUnit, mod, clangMod,
|
||||
indexStorePath, clangCI,
|
||||
diags);
|
||||
}
|
||||
} else {
|
||||
// Serialized AST file.
|
||||
@@ -727,9 +529,6 @@ static void addModuleDependencies(ArrayRef<ImportedModule> imports,
|
||||
SmallVector<ImportedModule, 4> imports;
|
||||
mod->getImportedModules(imports,
|
||||
ModuleDecl::ImportFilterKind::Exported);
|
||||
if (indexClangModules)
|
||||
emitTransitiveClangSymbolicInterfacesForSwiftModuleImports(
|
||||
imports, indexStorePath, clangCI, diags);
|
||||
}
|
||||
}
|
||||
clang::index::writer::OpaqueModule opaqMod =
|
||||
|
||||
Reference in New Issue
Block a user