Skip to content

Commit 65eaafe

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
1 parent 5e0bcab commit 65eaafe

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
@@ -637,6 +637,11 @@ namespace importer {
637637
/// Returns true if the given module has a 'cplusplus' requirement.
638638
bool requiresCPlusPlus(const clang::Module *module);
639639

640+
/// Returns true if the given module is one of the C++ standard library modules.
641+
/// This could be the top-level std module, or any of the libc++ split modules
642+
/// (std_vector, std_iosfwd, etc).
643+
bool isCxxStdModule(const clang::Module *module);
644+
640645
/// Returns the pointee type if the given type is a C++ `const`
641646
/// reference type, `None` otherwise.
642647
llvm::Optional<clang::QualType>

lib/ClangImporter/ClangImporter.cpp

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

21652165
// `CxxStdlib` is the only accepted spelling of the C++ stdlib module name.
2166-
if (path.front().Item.is("std"))
2166+
if (path.front().Item.is("std") ||
2167+
path.front().Item.str().starts_with("std_"))
21672168
return nullptr;
21682169
if (path.front().Item == ctx.Id_CxxStdlib) {
21692170
ImportPath::Builder adjustedPath(ctx.getIdentifier("std"), importLoc);
@@ -3985,6 +3986,13 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
39853986
ImportPath::Module::Builder builder(M->getName());
39863987
(void) owner.loadModule(SourceLoc(), std::move(builder).get());
39873988
}
3989+
// If this Clang module is a part of the C++ stdlib, and we haven't loaded
3990+
// the overlay for it so far, it is a split libc++ module (e.g. std_vector).
3991+
// Load the CxxStdlib overlay explicitly.
3992+
if (!overlay && importer::isCxxStdModule(clangModule)) {
3993+
ImportPath::Module::Builder builder(Ctx.Id_CxxStdlib);
3994+
overlay = owner.loadModule(SourceLoc(), std::move(builder).get());
3995+
}
39883996
auto mutableThis = const_cast<ClangModuleUnit *>(this);
39893997
mutableThis->overlayModule.setPointerAndInt(overlay, true);
39903998
}
@@ -7624,12 +7632,7 @@ const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition(
76247632

76257633
bool importer::requiresCPlusPlus(const clang::Module *module) {
76267634
// The libc++ modulemap doesn't currently declare the requirement.
7627-
if (module->getTopLevelModuleName() == "std")
7628-
return true;
7629-
// In recent libc++ versions the module is split into multiple top-level
7630-
// modules (std_vector, std_utility, etc).
7631-
if (module->getTopLevelModule()->IsSystem &&
7632-
module->getTopLevelModuleName().starts_with("std_"))
7635+
if (isCxxStdModule(module))
76337636
return true;
76347637

76357638
// Modulemaps often declare the requirement for the top-level module only.
@@ -7643,6 +7646,18 @@ bool importer::requiresCPlusPlus(const clang::Module *module) {
76437646
});
76447647
}
76457648

7649+
bool importer::isCxxStdModule(const clang::Module *module) {
7650+
if (module->getTopLevelModuleName() == "std")
7651+
return true;
7652+
// In recent libc++ versions the module is split into multiple top-level
7653+
// modules (std_vector, std_utility, etc).
7654+
if (module->getTopLevelModule()->IsSystem &&
7655+
module->getTopLevelModuleName().starts_with("std_"))
7656+
return true;
7657+
7658+
return false;
7659+
}
7660+
76467661
llvm::Optional<clang::QualType>
76477662
importer::getCxxReferencePointeeTypeOrNone(const clang::Type *type) {
76487663
if (type->isReferenceType())

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3389,10 +3389,8 @@ namespace {
33893389
->getTopLevelModule()
33903390
->getFullModuleName() == n;
33913391
};
3392-
if (topLevelModuleEq(decl, "std") ||
3393-
(decl->getOwningModule() && decl->getOwningModule()->IsSystem &&
3394-
StringRef(decl->getOwningModule()->getTopLevelModule()->Name)
3395-
.starts_with("std_"))) {
3392+
if ((decl->getOwningModule() &&
3393+
importer::isCxxStdModule(decl->getOwningModule()))) {
33963394
if (isAlternativeCStdlibFunctionFromTextualHeader(decl)) {
33973395
return nullptr;
33983396
}

0 commit comments

Comments
 (0)