Skip to content

Commit ba88078

Browse files
authored
Merge pull request #83261 from egorzhdan/egorzhdan/allow-qual-swift-name-reland
Reland "[cxx-interop] Allow import-as-member for types in namespaces"
2 parents d8099bf + e4af21f commit ba88078

File tree

9 files changed

+154
-15
lines changed

9 files changed

+154
-15
lines changed

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ bool SwiftLookupTable::contextRequiresName(ContextKind kind) {
220220

221221
/// Try to translate the given Clang declaration into a context.
222222
static std::optional<SwiftLookupTable::StoredContext>
223-
translateDeclToContext(clang::NamedDecl *decl) {
223+
translateDeclToContext(const clang::NamedDecl *decl) {
224224
// Tag declaration.
225225
if (auto tag = dyn_cast<clang::TagDecl>(decl)) {
226226
if (tag->getIdentifier())
@@ -325,22 +325,49 @@ SwiftLookupTable::translateContext(EffectiveClangContext context) {
325325

326326
/// Lookup an unresolved context name and resolve it to a Clang
327327
/// declaration context or typedef name.
328-
clang::NamedDecl *SwiftLookupTable::resolveContext(StringRef unresolvedName) {
328+
const clang::NamedDecl *
329+
SwiftLookupTable::resolveContext(StringRef unresolvedName) {
330+
SmallVector<StringRef, 1> nameComponents;
331+
unresolvedName.split(nameComponents, '.');
332+
333+
EffectiveClangContext parentContext;
334+
329335
// Look for a context with the given Swift name.
330-
for (auto entry :
331-
lookup(SerializedSwiftName(unresolvedName),
332-
std::make_pair(ContextKind::TranslationUnit, StringRef()))) {
333-
if (auto decl = entry.dyn_cast<clang::NamedDecl *>()) {
334-
if (isa<clang::TagDecl>(decl) ||
335-
isa<clang::ObjCInterfaceDecl>(decl) ||
336-
isa<clang::TypedefNameDecl>(decl))
337-
return decl;
336+
for (auto nameComponent : nameComponents) {
337+
auto entries =
338+
parentContext
339+
? lookup(SerializedSwiftName(nameComponent), parentContext)
340+
: lookup(SerializedSwiftName(nameComponent),
341+
std::make_pair(ContextKind::TranslationUnit, StringRef()));
342+
bool entryFound = false;
343+
for (auto entry : entries) {
344+
if (auto decl = entry.dyn_cast<clang::NamedDecl *>()) {
345+
if (isa<clang::TagDecl>(decl) ||
346+
isa<clang::ObjCInterfaceDecl>(decl) ||
347+
isa<clang::NamespaceDecl>(decl)) {
348+
entryFound = true;
349+
parentContext = EffectiveClangContext(cast<clang::DeclContext>(decl));
350+
break;
351+
}
352+
if (auto typedefDecl = dyn_cast<clang::TypedefNameDecl>(decl)) {
353+
entryFound = true;
354+
parentContext = EffectiveClangContext(typedefDecl);
355+
break;
356+
}
357+
}
338358
}
339-
}
340359

341-
// FIXME: Search imported modules to resolve the context.
360+
// If we could not resolve this component of the qualified name, bail.
361+
if (!entryFound)
362+
break;
363+
}
364+
365+
if (!parentContext)
366+
return nullptr;
342367

343-
return nullptr;
368+
return parentContext.getAsDeclContext()
369+
? cast<clang::NamedDecl>(parentContext.getAsDeclContext())
370+
: parentContext.getTypedefName();
344371
}
345372

346373
void SwiftLookupTable::addCategory(clang::ObjCCategoryDecl *category) {

lib/ClangImporter/SwiftLookupTable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ class SwiftLookupTable {
593593
public:
594594
/// Lookup an unresolved context name and resolve it to a Clang
595595
/// named declaration.
596-
clang::NamedDecl *resolveContext(StringRef unresolvedName);
596+
const clang::NamedDecl *resolveContext(StringRef unresolvedName);
597597

598598
/// Lookup the set of entities with the given base name.
599599
///

test/APINotes/Inputs/broken-modules/BrokenAPINotes.apinotes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ Functions:
1313
- Name: ZXSpectrumSetMisnamedRegister
1414
SwiftName: 'setter:ZXSpectrum.misnamedRegister(self:newValue:)'
1515
- Name: ZXSpectrumHelperReset
16-
SwiftName: 'ZXSpectrum.Helper.reset()'
16+
SwiftName: 'ZXSpectrum::Helper.reset()'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#define SWIFT_NAME(name) __attribute__((swift_name(name)))
2+
3+
namespace MyNS {
4+
struct NestedStruct {
5+
int value = 123;
6+
};
7+
}
8+
9+
int nestedStruct_method(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.method(self:)") { return p.value; }
10+
int nestedStruct_methodConstRef(const MyNS::NestedStruct &p) SWIFT_NAME("MyNS.NestedStruct.methodConstRef(self:)") { return p.value + 1; }
11+
inline int nestedStruct_methodInline(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.methodInline(self:)") { return p.value + 2; }
12+
13+
namespace MyNS {
14+
namespace MyDeepNS {
15+
struct DeepNestedStruct {
16+
int value = 456;
17+
};
18+
}
19+
}
20+
21+
int deepNestedStruct_method(MyNS::MyDeepNS::DeepNestedStruct p) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.method(self:)") { return p.value; }
22+
int deepNestedStruct_methodConstRef(const MyNS::MyDeepNS::DeepNestedStruct &p) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.methodConstRef(self:)") { return p.value + 2; }
23+
24+
typedef MyNS::MyDeepNS::DeepNestedStruct DeepNestedStructTypedef;
25+
26+
int deepNestedStructTypedef_method(DeepNestedStructTypedef p) SWIFT_NAME("DeepNestedStructTypedef.methodTypedef(self:)") { return p.value + 3; }
27+
int deepNestedStructTypedef_methodQualName(MyNS::MyDeepNS::DeepNestedStruct p) SWIFT_NAME("DeepNestedStructTypedef.methodTypedefQualName(self:)") { return p.value + 4; }
28+
29+
namespace MyNS {
30+
int nestedStruct_nestedMethod(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.nestedMethod(self:)") { return p.value + 3; }
31+
inline int nestedStruct_nestedMethodInline(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.nestedMethodInline(self:)") { return p.value + 4; }
32+
}

test/Interop/Cxx/namespace/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ module Enums {
6060
requires cplusplus
6161
}
6262

63+
module ImportAsMember {
64+
header "import-as-member.h"
65+
export *
66+
requires cplusplus
67+
}
68+
6369
module MembersDirect {
6470
header "members-direct.h"
6571
requires cplusplus
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=ImportAsMember -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s
2+
3+
// CHECK: extension MyNS.NestedStruct {
4+
// CHECK-NEXT: func method() -> Int32
5+
// CHECK-NEXT: func methodConstRef() -> Int32
6+
// CHECK-NEXT: func methodInline() -> Int32
7+
// CHECK-NEXT: func nestedMethod() -> Int32
8+
// CHECK-NEXT: func nestedMethodInline() -> Int32
9+
// CHECK-NEXT: }
10+
11+
// CHECK: extension MyNS.MyDeepNS.DeepNestedStruct {
12+
// CHECK-NEXT: func method() -> Int32
13+
// CHECK-NEXT: func methodConstRef() -> Int32
14+
// CHECK-NEXT: func methodTypedef() -> Int32
15+
// CHECK-NEXT: func methodTypedefQualName() -> Int32
16+
// CHECK-NEXT: }
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=upcoming-swift
2+
3+
import ImportAsMember
4+
5+
func takesNestedStruct(_ s: MyNS.NestedStruct) {
6+
_ = s.method()
7+
_ = s.methodConstRef()
8+
_ = s.nestedMethod()
9+
_ = s.nestedMethodInline()
10+
11+
_ = nestedStruct_method(s) // expected-error {{'nestedStruct_method' has been replaced by instance method 'MyNS.NestedStruct.method()'}}
12+
}
13+
14+
func takesDeepNestedStruct(_ s: MyNS.MyDeepNS.DeepNestedStruct) {
15+
_ = s.method()
16+
_ = s.methodConstRef()
17+
_ = s.methodTypedef()
18+
_ = s.methodTypedefQualName()
19+
20+
_ = deepNestedStruct_method(s) // expected-error {{'deepNestedStruct_method' has been replaced by instance method 'MyNS.MyDeepNS.DeepNestedStruct.method()'}}
21+
}
22+
23+
MyNS.method() // expected-error {{type 'MyNS' has no member 'method'}}
24+
MyNS.nestedMethod() // expected-error {{type of expression is ambiguous without a type annotation}}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift)
2+
3+
// REQUIRES: executable_test
4+
5+
import StdlibUnittest
6+
import ImportAsMember
7+
8+
var NamespacesTestSuite = TestSuite("Import as member of namespace")
9+
10+
NamespacesTestSuite.test("Struct in a namespace") {
11+
let s = MyNS.NestedStruct()
12+
expectEqual(123, s.method())
13+
expectEqual(124, s.methodConstRef())
14+
expectEqual(125, s.methodInline())
15+
}
16+
17+
NamespacesTestSuite.test("Struct in a deep namespace") {
18+
let s = MyNS.MyDeepNS.DeepNestedStruct()
19+
expectEqual(456, s.method())
20+
expectEqual(458, s.methodConstRef())
21+
expectEqual(459, s.methodTypedef())
22+
expectEqual(460, s.methodTypedefQualName())
23+
}
24+
25+
NamespacesTestSuite.test("Struct and function in a namespace") {
26+
let s = MyNS.NestedStruct()
27+
expectEqual(126, s.nestedMethod())
28+
expectEqual(127, s.nestedMethodInline())
29+
}
30+
31+
runAllTests()

test/Interop/Cxx/objc-correctness/appkit-uikit.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs -cxx-interoperability-mode=default %s
2+
// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs -cxx-interoperability-mode=default %s -swift-version 6
23

34
// REQUIRES: objc_interop
45
// REQUIRES: VENDOR=apple
@@ -9,6 +10,8 @@ import AppKit
910

1011
var _: AttributeScopes.AppKitAttributes.UnderlineStyleAttribute! = nil
1112

13+
var _ = NSEvent.SpecialKey.upArrow.rawValue
14+
1215
#elseif canImport(UIKit)
1316
import UIKit
1417

0 commit comments

Comments
 (0)