Skip to content

Commit 479d84f

Browse files
authored
Merge pull request #70468 from apple/egorzhdan/5.10-split-libcxx-fixes
🍒[cxx-interop] Fix fallout of splitting libc++ module into many top-level modules
2 parents 482c0d2 + 6db39f1 commit 479d84f

File tree

7 files changed

+42
-15
lines changed

7 files changed

+42
-15
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/ClangDerivedConformances.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ getIteratorCategoryDecl(const clang::CXXRecordDecl *clangDecl) {
126126
clang::IdentifierInfo *iteratorCategoryDeclName =
127127
&clangDecl->getASTContext().Idents.get("iterator_category");
128128
auto iteratorCategories = clangDecl->lookup(iteratorCategoryDeclName);
129-
if (!iteratorCategories.isSingleResult())
129+
// If this is a templated typedef, Clang might have instantiated several
130+
// equivalent typedef decls. If they aren't equivalent, Clang has already
131+
// complained about this. Let's assume that they are equivalent. (see
132+
// filterNonConflictingPreviousTypedefDecls in clang/Sema/SemaDecl.cpp)
133+
if (iteratorCategories.empty())
130134
return nullptr;
131135
auto iteratorCategory = iteratorCategories.front();
132136

lib/ClangImporter/ClangImporter.cpp

Lines changed: 22 additions & 2 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,7 +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")
7475+
if (isCxxStdModule(module))
74687476
return true;
74697477

74707478
// Modulemaps often declare the requirement for the top-level module only.
@@ -7478,6 +7486,18 @@ bool importer::requiresCPlusPlus(const clang::Module *module) {
74787486
});
74797487
}
74807488

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+
74817501
llvm::Optional<clang::QualType>
74827502
importer::getCxxReferencePointeeTypeOrNone(const clang::Type *type) {
74837503
if (type->isReferenceType())

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3267,7 +3267,8 @@ namespace {
32673267
->getTopLevelModule()
32683268
->getFullModuleName() == n;
32693269
};
3270-
if (topLevelModuleEq(decl, "std")) {
3270+
if ((decl->getOwningModule() &&
3271+
importer::isCxxStdModule(decl->getOwningModule()))) {
32713272
if (isAlternativeCStdlibFunctionFromTextualHeader(decl)) {
32723273
return nullptr;
32733274
}

test/Interop/Cxx/stdlib/libcxx-module-interface.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxStdlib -source-filename=x -enable-experimental-cxx-interop -tools-directory=%llvm_obj_root/bin -module-cache-path %t | %FileCheck %s -check-prefix=CHECK-STD
2+
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxStdlib -source-filename=x -enable-experimental-cxx-interop -tools-directory=%llvm_obj_root/bin -module-cache-path %t -module-print-submodules | %FileCheck %s -check-prefix=CHECK-STD-WITH-SUBMODULES
23
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxStdlib.iosfwd -source-filename=x -enable-experimental-cxx-interop -tools-directory=%llvm_obj_root/bin -module-cache-path %t | %FileCheck %s -check-prefix=CHECK-IOSFWD
34
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxStdlib.string -source-filename=x -enable-experimental-cxx-interop -tools-directory=%llvm_obj_root/bin -module-cache-path %t | %FileCheck %s -check-prefix=CHECK-STRING
45

@@ -8,6 +9,10 @@
89
// CHECK-STD: import CxxStdlib.iosfwd
910
// CHECK-STD: import CxxStdlib.string
1011

12+
// CHECK-STD-WITH-SUBMODULES: enum std {
13+
// CHECK-STD-WITH-SUBMODULES: enum __1 {
14+
// CHECK-STD-WITH-SUBMODULES-NOT: enum std
15+
1116
// CHECK-IOSFWD: enum std {
1217
// CHECK-IOSFWD: enum __1 {
1318
// CHECK-IOSFWD: struct basic_string<CChar, char_traits<CChar>, allocator<CChar>> : CxxRandomAccessCollection {
@@ -20,10 +25,12 @@
2025
// CHECK-IOSFWD: typealias wstring = std.__1.basic_string<CWideChar, char_traits<CWideChar>, allocator<CWideChar>>
2126
// CHECK-IOSFWD: }
2227
// CHECK-IOSFWD: }
28+
// CHECK-IOSFWD-NOT: enum std
2329

2430
// CHECK-STRING: enum std {
2531
// CHECK-STRING: enum __1 {
2632
// CHECK-STRING: static func to_string(_ __val: Int32) -> std.__1.string
2733
// CHECK-STRING: static func to_wstring(_ __val: Int32) -> std.__1.wstring
2834
// CHECK-STRING: }
2935
// CHECK-STRING: }
36+
// CHECK-STRING-NOT: enum std

test/Interop/Cxx/stdlib/print-libcxx-module-interface.swift

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/Interop/Cxx/symbolic-imports/print-libcxx-symbolic-module-interface.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// REQUIRES: OS=macosx
99

1010
// CHECK: enum std {
11-
// CHECK-NEXT: enum __1 {
11+
// CHECK: enum __1 {
1212

1313
// STRING: struct basic_string {
1414

0 commit comments

Comments
 (0)