From d15e13901492198a163dd7d8531411116ba7ad95 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Sep 2025 19:15:57 +0100 Subject: [PATCH 1/2] Revert "[cxx-interop] Do not look into `extern` blocks in libc++'s std_private_random_binomial_distribution" This reverts commit 8e71509108398b3984a8c8ac1364213b6730d14f. --- lib/ClangImporter/SwiftLookupTable.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/ClangImporter/SwiftLookupTable.cpp b/lib/ClangImporter/SwiftLookupTable.cpp index 65dfde62ed19d..07929fc8067fc 100644 --- a/lib/ClangImporter/SwiftLookupTable.cpp +++ b/lib/ClangImporter/SwiftLookupTable.cpp @@ -2046,17 +2046,7 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table, addDeclsFromContext(nestedLinkageSpecDecl); } }; - - // HACK: libc++ redeclares lgamma_r in one of its headers, and that - // declaration hijacks lgamma_r from math.h where it is originally - // defined. This causes deserialization issues when loading the Darwin - // overlay on Apple platforms, because Swift cannot find lgamma_r in - // module _math. - bool shouldSkip = canonicalMember->getOwningModule() && - canonicalMember->getOwningModule()->Name == - "std_private_random_binomial_distribution"; - if (!shouldSkip) - addDeclsFromContext(linkageSpecDecl); + addDeclsFromContext(linkageSpecDecl); } } } From c3a56fdc9160b099153dca5a9a9dfa9daf3c336d Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Sep 2025 19:17:14 +0100 Subject: [PATCH 2/2] Revert "[cxx-interop] Import decls in extern blocks within namespaces" This reverts commit 844787fd Reverting because of a modularization issue in host libc++. rdar://160536819 rdar://160536878 --- lib/AST/ASTPrinter.cpp | 137 ++++++++---------- lib/ClangImporter/ClangImporter.cpp | 5 - lib/ClangImporter/ImportDecl.cpp | 7 +- lib/ClangImporter/SwiftLookupTable.cpp | 14 -- .../Inputs/extern-within-namespace.h | 28 ---- ...rn-within-namespace-module-interface.swift | 17 --- .../namespace/extern-within-namespace.swift | 25 ---- 7 files changed, 63 insertions(+), 170 deletions(-) delete mode 100644 test/Interop/Cxx/namespace/Inputs/extern-within-namespace.h delete mode 100644 test/Interop/Cxx/namespace/extern-within-namespace-module-interface.swift delete mode 100644 test/Interop/Cxx/namespace/extern-within-namespace.swift diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 8863947e78b8e..4c939e53adf76 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2789,87 +2789,72 @@ static void addNamespaceMembers(Decl *decl, if (declOwner && declOwner != redeclOwner->getTopLevelModule()) continue; } + for (auto member : redecl->decls()) { + if (auto classTemplate = dyn_cast(member)) { + // Add all specializations to a worklist so we don't accidentally mutate + // the list of decls we're iterating over. + llvm::SmallPtrSet specWorklist; + for (auto spec : classTemplate->specializations()) + specWorklist.insert(spec); + for (auto spec : specWorklist) { + if (auto import = + ctx.getClangModuleLoader()->importDeclDirectly(spec)) + if (addedMembers.insert(import).second) + members.push_back(import); + } + } - std::function addDeclsFromContext = - [&](clang::DeclContext *declContext) { - for (auto member : declContext->decls()) { - if (auto classTemplate = - dyn_cast(member)) { - // Add all specializations to a worklist so we don't accidentally - // mutate the list of decls we're iterating over. - llvm::SmallPtrSet - specWorklist; - for (auto spec : classTemplate->specializations()) - specWorklist.insert(spec); - for (auto spec : specWorklist) { - if (auto import = - ctx.getClangModuleLoader()->importDeclDirectly(spec)) - if (addedMembers.insert(import).second) - members.push_back(import); - } + auto lookupAndAddMembers = [&](DeclName name) { + auto allResults = evaluateOrDefault( + ctx.evaluator, ClangDirectLookupRequest({decl, redecl, name}), {}); + + for (auto found : allResults) { + auto clangMember = cast(found); + if (auto importedDecl = + ctx.getClangModuleLoader()->importDeclDirectly(clangMember)) { + if (addedMembers.insert(importedDecl).second) { + members.push_back(importedDecl); + + // Handle macro-expanded declarations. + importedDecl->visitAuxiliaryDecls([&](Decl *decl) { + auto valueDecl = dyn_cast(decl); + if (!valueDecl) + return; + + // Bail out if the auxiliary decl was not produced by a macro. + auto module = decl->getDeclContext()->getParentModule(); + auto *sf = module->getSourceFileContainingLocation(decl->getLoc()); + if (!sf || sf->Kind != SourceFileKind::MacroExpansion) + return; + + members.push_back(valueDecl); + }); } + } + } + }; - auto lookupAndAddMembers = [&](clang::NamedDecl *namedDecl) { - auto name = ctx.getClangModuleLoader()->importName(namedDecl); - if (!name) - return; - - auto allResults = evaluateOrDefault( - ctx.evaluator, ClangDirectLookupRequest({decl, redecl, name}), - {}); - - for (auto found : allResults) { - auto clangMember = cast(found); - if (auto importedDecl = - ctx.getClangModuleLoader()->importDeclDirectly( - clangMember)) { - if (addedMembers.insert(importedDecl).second) { - members.push_back(importedDecl); - - // Handle macro-expanded declarations. - importedDecl->visitAuxiliaryDecls([&](Decl *decl) { - auto valueDecl = dyn_cast(decl); - if (!valueDecl) - return; - - // Bail out if the auxiliary decl was not produced by a - // macro. - auto module = decl->getDeclContext()->getParentModule(); - auto *sf = module->getSourceFileContainingLocation( - decl->getLoc()); - if (!sf || sf->Kind != SourceFileKind::MacroExpansion) - return; - - members.push_back(valueDecl); - }); - } - } - } - }; - - // Look through `extern` blocks. - if (auto linkageSpecDecl = dyn_cast(member)) - addDeclsFromContext(linkageSpecDecl); - - auto namedDecl = dyn_cast(member); - if (!namedDecl) + auto namedDecl = dyn_cast(member); + if (!namedDecl) + continue; + auto name = ctx.getClangModuleLoader()->importName(namedDecl); + if (!name) + continue; + lookupAndAddMembers(name); + + // Unscoped enums could have their enumerators present + // in the parent namespace. + if (auto *ed = dyn_cast(member)) { + if (!ed->isScoped()) { + for (const auto *ecd : ed->enumerators()) { + auto name = ctx.getClangModuleLoader()->importName(ecd); + if (!name) continue; - lookupAndAddMembers(namedDecl); - - // Unscoped enums could have their enumerators present - // in the parent namespace. - if (auto *ed = dyn_cast(member)) { - if (!ed->isScoped()) { - for (auto *ecd : ed->enumerators()) { - lookupAndAddMembers(ecd); - } - } - } + lookupAndAddMembers(name); } - }; - - addDeclsFromContext(redecl); + } + } + } } } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index c816ebef3059e..a970ef774ea8e 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -5076,11 +5076,6 @@ static bool isDirectLookupMemberContext(const clang::Decl *foundClangDecl, return firstDecl->getCanonicalDecl() == parent->getCanonicalDecl(); } } - // Look through `extern` blocks. - if (auto linkageSpecDecl = dyn_cast(memberContext)) { - if (auto parentDecl = dyn_cast(linkageSpecDecl->getParent())) - return isDirectLookupMemberContext(foundClangDecl, parentDecl, parent); - } return false; } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index f000dbdda83cb..df852fe96e7d2 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -1171,14 +1171,11 @@ namespace { return nullptr; // If this is a top-level namespace, don't put it in the module we're // importing, put it in the "__ObjC" module that is implicitly imported. - auto clangDC = decl->getDeclContext(); - while (isa(clangDC)) - clangDC = clangDC->getParent(); - if (!clangDC->isNamespace()) + if (!decl->getParent()->isNamespace()) dc = Impl.ImportedHeaderUnit; else { // This is a nested namespace, so just lookup it's parent normally. - auto parentNS = cast(clangDC); + auto parentNS = cast(decl->getParent()); auto parent = Impl.importDecl(parentNS, getVersion(), /*UseCanonicalDecl*/ false); // The parent namespace might not be imported if it's `swift_private`. diff --git a/lib/ClangImporter/SwiftLookupTable.cpp b/lib/ClangImporter/SwiftLookupTable.cpp index 07929fc8067fc..a203c00dfe618 100644 --- a/lib/ClangImporter/SwiftLookupTable.cpp +++ b/lib/ClangImporter/SwiftLookupTable.cpp @@ -2034,20 +2034,6 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table, namedMember = def; addEntryToLookupTable(table, namedMember, nameImporter); } - if (auto linkageSpecDecl = - dyn_cast(canonicalMember)) { - std::function addDeclsFromContext = - [&](clang::DeclContext *declContext) { - for (auto nestedDecl : declContext->decls()) { - if (auto namedMember = dyn_cast(nestedDecl)) - addEntryToLookupTable(table, namedMember, nameImporter); - else if (auto nestedLinkageSpecDecl = - dyn_cast(nestedDecl)) - addDeclsFromContext(nestedLinkageSpecDecl); - } - }; - addDeclsFromContext(linkageSpecDecl); - } } } if (auto usingDecl = dyn_cast(named)) { diff --git a/test/Interop/Cxx/namespace/Inputs/extern-within-namespace.h b/test/Interop/Cxx/namespace/Inputs/extern-within-namespace.h deleted file mode 100644 index a193084e62e1f..0000000000000 --- a/test/Interop/Cxx/namespace/Inputs/extern-within-namespace.h +++ /dev/null @@ -1,28 +0,0 @@ -namespace Outer { -namespace Inner { -extern "C" { -int foobar() { return 123; } -struct NestedType { - char c; -}; -} -} // namespace Inner - -inline namespace InnerInline { -extern "C" { -int baz() { return 321; } -} -} // namespace InnerInline -} // namespace Outer - -namespace ExternWithinExtern { -extern "C" { -extern "C++" { -namespace Inner { -extern "C" { -int deep() { return 42; } -} -} // namespace Inner -} -} -} // namespace ExternWithinExtern diff --git a/test/Interop/Cxx/namespace/extern-within-namespace-module-interface.swift b/test/Interop/Cxx/namespace/extern-within-namespace-module-interface.swift deleted file mode 100644 index 4752166d67ef8..0000000000000 --- a/test/Interop/Cxx/namespace/extern-within-namespace-module-interface.swift +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %target-swift-ide-test -print-module -module-to-print=ExternWithinNamespace -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s - -// CHECK: enum Outer { -// CHECK-NEXT: enum Inner { -// CHECK-NEXT: static func foobar() -// CHECK-NEXT: struct NestedType { -// CHECK: } -// CHECK-NEXT: } -// CHECK-NEXT: enum InnerInline { -// CHECK-NEXT: static func baz() -> Int32 -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: enum ExternWithinExtern { -// CHECK-NEXT: enum Inner { -// CHECK-NEXT: static func deep() -> Int32 -// CHECK-NEXT: } -// CHECK-NEXT: } diff --git a/test/Interop/Cxx/namespace/extern-within-namespace.swift b/test/Interop/Cxx/namespace/extern-within-namespace.swift deleted file mode 100644 index 7c6d40664a1de..0000000000000 --- a/test/Interop/Cxx/namespace/extern-within-namespace.swift +++ /dev/null @@ -1,25 +0,0 @@ -// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift) - -// REQUIRES: executable_test - -import StdlibUnittest -import ExternWithinNamespace - -var ExternTestSuite = TestSuite("Extern block within namespaces") - -ExternTestSuite.test("Function within extern block within namespace") { - let r = Outer.Inner.foobar() - expectEqual(r, 123) -} - -ExternTestSuite.test("Function within extern block within inline namespace") { - let r = Outer.InnerInline.baz() - expectEqual(r, 321) -} - -ExternTestSuite.test("Function within extern block within extern block") { - let r = ExternWithinExtern.Inner.deep() - expectEqual(r, 42) -} - -runAllTests()