Skip to content

Commit 84b253e

Browse files
committed
[cxx-interop] Keep pulling in the entire libc++
libc++ recently split the `std` module into many top-level modules: llvm/llvm-project@571178a Previously if a C++ module had `#include <iosfwd>`, importing that module in Swift would make the entire C++ stdlib visible from Swift, since it was a single top-level Clang module. After libc++ got split it doesn't automatically do so, but we need to preserve the current behavior for Swift users. rdar://119270491 (cherry picked from commit 65eaafe)
1 parent 59036e4 commit 84b253e

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,11 @@ namespace importer {
632632
/// Returns true if the given module has a 'cplusplus' requirement.
633633
bool requiresCPlusPlus(const clang::Module *module);
634634

635+
/// Returns true if the given module is one of the C++ standard library modules.
636+
/// This could be the top-level std module, or any of the libc++ split modules
637+
/// (std_vector, std_iosfwd, etc).
638+
bool isCxxStdModule(const clang::Module *module);
639+
635640
/// Returns the pointee type if the given type is a C++ `const`
636641
/// reference type, `None` otherwise.
637642
llvm::Optional<clang::QualType>

lib/ClangImporter/ClangImporter.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,7 +2157,8 @@ ModuleDecl *ClangImporter::Implementation::loadModule(
21572157
ASTContext &ctx = getNameImporter().getContext();
21582158

21592159
// `CxxStdlib` is the only accepted spelling of the C++ stdlib module name.
2160-
if (path.front().Item.is("std"))
2160+
if (path.front().Item.is("std") ||
2161+
path.front().Item.str().starts_with("std_"))
21612162
return nullptr;
21622163
if (path.front().Item == ctx.Id_CxxStdlib) {
21632164
ImportPath::Builder adjustedPath(ctx.getIdentifier("std"), importLoc);
@@ -3979,6 +3980,13 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
39793980
ImportPath::Module::Builder builder(M->getName());
39803981
(void) owner.loadModule(SourceLoc(), std::move(builder).get());
39813982
}
3983+
// If this Clang module is a part of the C++ stdlib, and we haven't loaded
3984+
// the overlay for it so far, it is a split libc++ module (e.g. std_vector).
3985+
// Load the CxxStdlib overlay explicitly.
3986+
if (!overlay && importer::isCxxStdModule(clangModule)) {
3987+
ImportPath::Module::Builder builder(Ctx.Id_CxxStdlib);
3988+
overlay = owner.loadModule(SourceLoc(), std::move(builder).get());
3989+
}
39823990
auto mutableThis = const_cast<ClangModuleUnit *>(this);
39833991
mutableThis->overlayModule.setPointerAndInt(overlay, true);
39843992
}
@@ -7464,12 +7472,7 @@ const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition(
74647472

74657473
bool importer::requiresCPlusPlus(const clang::Module *module) {
74667474
// The libc++ modulemap doesn't currently declare the requirement.
7467-
if (module->getTopLevelModuleName() == "std")
7468-
return true;
7469-
// In recent libc++ versions the module is split into multiple top-level
7470-
// modules (std_vector, std_utility, etc).
7471-
if (module->getTopLevelModule()->IsSystem &&
7472-
module->getTopLevelModuleName().starts_with("std_"))
7475+
if (isCxxStdModule(module))
74737476
return true;
74747477

74757478
// Modulemaps often declare the requirement for the top-level module only.
@@ -7483,6 +7486,18 @@ bool importer::requiresCPlusPlus(const clang::Module *module) {
74837486
});
74847487
}
74857488

7489+
bool importer::isCxxStdModule(const clang::Module *module) {
7490+
if (module->getTopLevelModuleName() == "std")
7491+
return true;
7492+
// In recent libc++ versions the module is split into multiple top-level
7493+
// modules (std_vector, std_utility, etc).
7494+
if (module->getTopLevelModule()->IsSystem &&
7495+
module->getTopLevelModuleName().starts_with("std_"))
7496+
return true;
7497+
7498+
return false;
7499+
}
7500+
74867501
llvm::Optional<clang::QualType>
74877502
importer::getCxxReferencePointeeTypeOrNone(const clang::Type *type) {
74887503
if (type->isReferenceType())

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,10 +3267,8 @@ namespace {
32673267
->getTopLevelModule()
32683268
->getFullModuleName() == n;
32693269
};
3270-
if (topLevelModuleEq(decl, "std") ||
3271-
(decl->getOwningModule() && decl->getOwningModule()->IsSystem &&
3272-
StringRef(decl->getOwningModule()->getTopLevelModule()->Name)
3273-
.starts_with("std_"))) {
3270+
if ((decl->getOwningModule() &&
3271+
importer::isCxxStdModule(decl->getOwningModule()))) {
32743272
if (isAlternativeCStdlibFunctionFromTextualHeader(decl)) {
32753273
return nullptr;
32763274
}

0 commit comments

Comments
 (0)