[cxx-interop] Fix two issues with extending nested types across modules.

One fix allows extending nested records in other modules, the other fixes the same issue for namespaces.
This commit is contained in:
zoecarver
2021-11-09 09:20:14 -08:00
parent bc153435db
commit 6ba7a1ec1e
12 changed files with 123 additions and 7 deletions

View File

@@ -2527,6 +2527,10 @@ static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter,
auto *Importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
auto ClangNode = Importer->getEffectiveClangNode(VD);
// Decls in the __ObjC bridging header is always visible.
if (VD->getModuleContext() == Importer->getImportedHeaderModule())
return true;
// Macros can be "redeclared" by putting an equivalent definition in two
// different modules. (We don't actually check the equivalence.)
// FIXME: We're also not checking if the redeclaration is in /this/ module.

View File

@@ -2467,6 +2467,11 @@ namespace {
for (auto redecl : decl->redecls())
Impl.ImportedDecls[{redecl, getVersion()}] = enumDecl;
// Because a namespaces's decl context is the bridging header, make sure
// we add them to the bridging header lookup table.
addEntryToLookupTable(*Impl.BridgingHeaderLookupTable,
const_cast<clang::NamespaceDecl *>(decl),
Impl.getNameImporter());
return enumDecl;
}

View File

@@ -350,9 +350,6 @@ public:
"<bridging-header-import>";
private:
/// The Swift lookup table for the bridging header.
std::unique_ptr<SwiftLookupTable> BridgingHeaderLookupTable;
/// The Swift lookup tables, per module.
///
/// Annoyingly, we list this table early so that it gets torn down after
@@ -416,6 +413,9 @@ private:
llvm::SmallDenseMap<ModuleDecl *, SourceFile *> ClangSwiftAttrSourceFiles;
public:
/// The Swift lookup table for the bridging header.
std::unique_ptr<SwiftLookupTable> BridgingHeaderLookupTable;
/// Mapping of already-imported declarations.
llvm::DenseMap<std::pair<const clang::Decl *, Version>, Decl *> ImportedDecls;

View File

@@ -122,6 +122,9 @@ func testSwiftCompletions(foo: SwiftStruct) {
// CLANG_BAR-DAG: Decl[GlobalVar]/OtherModule[Bar]: BAR_MACRO_1[#Int32#]{{; name=.+$}}
// CLANG_BAR-DAG: Decl[Struct]/OtherModule[Bar]: SomeItemSet[#SomeItemSet#]
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[Bar]: SomeEnvironment[#SomeItemSet#]
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
// CLANG_BAR: End completions
// CLANG_BOTH_FOO_BAR: Begin completions
@@ -148,12 +151,15 @@ func testCompleteModuleQualifiedFoo2() {
Foo#^CLANG_QUAL_FOO_2^#
// If the number of results below changes, then you need to add a result to the
// list below.
// CLANG_QUAL_FOO_2: Begin completions, 76 items
// CLANG_QUAL_FOO_2: Begin completions, 82 items
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassBase[#FooClassBase#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassDerived[#FooClassDerived#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .ClassWithInternalProt[#ClassWithInternalProt#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Struct]/OtherModule[Foo]: ._InternalStruct[#_InternalStruct#]
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassPropertyOwnership[#FooClassPropertyOwnership#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
// CLANG_QUAL_FOO_2-DAG: Decl[FreeFunction]/OtherModule[Foo]: ._internalTopLevelFunc()[#Void#]
// CLANG_QUAL_FOO_2-DAG: Decl[Enum]/OtherModule[Foo]: .FooComparisonResult[#FooComparisonResult#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[FreeFunction]/OtherModule[Foo]: .fooFunc1({#(a): Int32#})[#Int32#]{{; name=.+$}}
@@ -217,6 +223,9 @@ func testCompleteModuleQualifiedFoo2() {
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooRepeatedMembers[#FooRepeatedMembers#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassWithClassProperties[#FooClassWithClassProperties#];
// CLANG_QUAL_FOO_2-DAG: Decl[Enum]/OtherModule[Foo]: .SCNFilterMode[#SCNFilterMode#];
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
// CLANG_QUAL_FOO_2: End completions
}
@@ -224,7 +233,7 @@ func testCompleteModuleQualifiedBar1() {
Bar.#^CLANG_QUAL_BAR_1^#
// If the number of results below changes, this is an indication that you need
// to add a result to the appropriate list. Do not just bump the number!
// CLANG_QUAL_BAR_1: Begin completions, 8 items
// CLANG_QUAL_BAR_1: Begin completions, 11 items
}
func testCompleteFunctionCall1() {

View File

@@ -0,0 +1,12 @@
#ifndef TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H
#define TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H
struct Parent {
struct Child {};
};
namespace Namespace {
struct InNamespace {};
}
#endif // TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H

View File

@@ -0,0 +1,4 @@
module Namespace {
header "namespace.h"
requires cplusplus
}

View File

@@ -0,0 +1,13 @@
import Namespace
extension Namespace.Parent {
public static func test() -> Int { 42 }
}
extension Namespace.Parent.Child {
public static func test() -> Int { 52 }
}
extension Namespace.NestedNamespace.NestedStruct {
public func test() -> Int { 62 }
}

View File

@@ -0,0 +1,18 @@
#ifndef TEST_INTEROP_CXX_MODULES_INPUTS_NAMESPACE_H
#define TEST_INTEROP_CXX_MODULES_INPUTS_NAMESPACE_H
namespace Namespace {
struct Parent {
struct Child {};
};
namespace NestedNamespace {
struct NestedStruct {};
} // namespace NestedNamespace
} // namespace Namespace
#endif // TEST_INTEROP_CXX_MODULES_INPUTS_NAMESPACE_H

View File

@@ -0,0 +1,7 @@
extension Parent.Child {
public static func test() -> Int { 42 }
}
extension Namespace.InNamespace {
public func test() -> Int { 52 }
}

View File

@@ -0,0 +1,23 @@
// RUN: %empty-directory(%t)
// RUN: cd %t
// RUN: %target-build-swift -I %S/Inputs -Xfrontend -enable-cxx-interop %S/Inputs/namespace-extension-lib.swift -emit-module -emit-library -module-name NamespaceExtensionLib
// RUN: %target-build-swift %s -I %S/Inputs -Xfrontend -enable-cxx-interop -o %t/run -I %t/ -L %t/ -lNamespaceExtensionLib
// RUN: %target-codesign %t/run
// RUN: %target-run %t/run
//
// REQUIRES: executable_test
import StdlibUnittest
import Namespace
import NamespaceExtensionLib
var NamespacesTestSuite = TestSuite("Extension in library on namespace")
NamespacesTestSuite.test("Call functions from extension") {
expectEqual(Namespace.Parent.test(), 42)
expectEqual(Namespace.Parent.Child.test(), 52)
expectEqual(Namespace.NestedNamespace.NestedStruct().test(), 62)
}
runAllTests()

View File

@@ -0,0 +1,21 @@
// RUN: %empty-directory(%t)
// RUN: cd %t
// RUN: %target-build-swift -import-objc-header %S/Inputs/bridge-header.h -Xfrontend -enable-cxx-interop %S/Inputs/struct-from-bridge-extension-lib.swift -emit-module -emit-library -module-name BridgeExtensionLib
// RUN: %target-build-swift %s -import-objc-header %S/Inputs/bridge-header.h -Xfrontend -enable-cxx-interop -o %t/run -I %t/ -L %t/ -lBridgeExtensionLib
// RUN: %target-codesign %t/run
// RUN: %target-run %t/run
//
// REQUIRES: executable_test
import StdlibUnittest
import BridgeExtensionLib
var BridgeTestSuite = TestSuite("Extension in library on nested types in bridge header")
BridgeTestSuite.test("Call functions from extension") {
expectEqual(Parent.Child.test(), 42)
expectEqual(Namespace.InNamespace().test(), 52)
}
runAllTests()

View File

@@ -47,10 +47,10 @@
// CHECK-NEXT: }
// CHECK-NEXT: typealias ForwardDeclaredClassTemplateOutOfLineChar = TemplatesNS1.TemplatesNS2.__CxxTemplateInstN12TemplatesNS112TemplatesNS237ForwardDeclaredClassTemplateOutOfLineIcEE
// CHECK-NEXT: enum TemplatesNS4 {
// CHECK-NEXT: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIcEE {
// CHECK-NEXT: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIiEE {
// CHECK-NEXT: init()
// CHECK-NEXT: }
// CHECK-NEXT: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIiEE {
// CHECK-NEXT: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIcEE {
// CHECK-NEXT: init()
// CHECK-NEXT: }
// CHECK-NEXT: struct HasSpecialization<> {