[cxx-interop] Allow compiling with libc++ on Linux

This makes sure that Swift respects `-Xcc -stdlib=libc++` flags.

Clang already has existing logic to discover the system-wide libc++ installation on Linux. We rely on that logic here.

Importing a Swift module that was built with a different C++ stdlib is not supported and emits an error.

The Cxx module can be imported when compiling with any C++ stdlib. The synthesized conformances, e.g. to CxxRandomAccessCollection also work. However, CxxStdlib currently cannot be imported when compiling with libc++, since on Linux it refers to symbols from libstdc++ which have different mangled names in libc++.

rdar://118357548 / https://github.com/swiftlang/swift/issues/69825
This commit is contained in:
Egor Zhdan
2024-07-30 20:01:58 +01:00
parent 536a88971f
commit 059f0f97d1
31 changed files with 348 additions and 28 deletions

View File

@@ -954,8 +954,10 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
M.setABIName(Ctx.getIdentifier(loadedModuleFile->getModuleABIName()));
if (loadedModuleFile->isConcurrencyChecked())
M.setIsConcurrencyChecked();
if (loadedModuleFile->hasCxxInteroperability())
if (loadedModuleFile->hasCxxInteroperability()) {
M.setHasCxxInteroperability();
M.setCXXStdlibKind(loadedModuleFile->getCXXStdlibKind());
}
if (!loadedModuleFile->getModulePackageName().empty()) {
M.setPackageName(Ctx.getIdentifier(loadedModuleFile->getModulePackageName()));
}
@@ -1055,6 +1057,18 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
M.getName());
Ctx.Diags.diagnose(loc, diag::enable_cxx_interop_docs);
}
// Modules built with libc++ cannot be imported into modules that are built
// with libstdc++, and vice versa. Make an exception for Cxx.swiftmodule since
// it doesn't refer to any C++ stdlib symbols, and for CxxStdlib.swiftmodule
// since we skipped loading the overlay for the module.
if (M.hasCxxInteroperability() && Ctx.LangOpts.EnableCXXInterop &&
M.getCXXStdlibKind() != Ctx.LangOpts.CXXStdlib &&
M.getName() != Ctx.Id_Cxx && M.getName() != Ctx.Id_CxxStdlib) {
auto loc = diagLoc.value_or(SourceLoc());
Ctx.Diags.diagnose(loc, diag::cxx_stdlib_kind_mismatch, M.getName(),
to_string(M.getCXXStdlibKind()),
to_string(Ctx.LangOpts.CXXStdlib));
}
return fileUnit;
}