Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 40 additions & 13 deletions lib/ClangImporter/SwiftLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ bool SwiftLookupTable::contextRequiresName(ContextKind kind) {

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

/// Lookup an unresolved context name and resolve it to a Clang
/// declaration context or typedef name.
clang::NamedDecl *SwiftLookupTable::resolveContext(StringRef unresolvedName) {
const clang::NamedDecl *
SwiftLookupTable::resolveContext(StringRef unresolvedName) {
SmallVector<StringRef, 1> nameComponents;
unresolvedName.split(nameComponents, '.');

EffectiveClangContext parentContext;

// Look for a context with the given Swift name.
for (auto entry :
lookup(SerializedSwiftName(unresolvedName),
std::make_pair(ContextKind::TranslationUnit, StringRef()))) {
if (auto decl = entry.dyn_cast<clang::NamedDecl *>()) {
if (isa<clang::TagDecl>(decl) ||
isa<clang::ObjCInterfaceDecl>(decl) ||
isa<clang::TypedefNameDecl>(decl))
return decl;
for (auto nameComponent : nameComponents) {
auto entries =
parentContext
? lookup(SerializedSwiftName(nameComponent), parentContext)
: lookup(SerializedSwiftName(nameComponent),
std::make_pair(ContextKind::TranslationUnit, StringRef()));
bool entryFound = false;
for (auto entry : entries) {
if (auto decl = entry.dyn_cast<clang::NamedDecl *>()) {
if (isa<clang::TagDecl>(decl) ||
isa<clang::ObjCInterfaceDecl>(decl) ||
isa<clang::NamespaceDecl>(decl)) {
entryFound = true;
parentContext = EffectiveClangContext(cast<clang::DeclContext>(decl));
break;
}
if (auto typedefDecl = dyn_cast<clang::TypedefNameDecl>(decl)) {
entryFound = true;
parentContext = EffectiveClangContext(typedefDecl);
break;
}
}
}
}

// FIXME: Search imported modules to resolve the context.
// If we could not resolve this component of the qualified name, bail.
if (!entryFound)
break;
}

if (!parentContext)
return nullptr;

return nullptr;
return parentContext.getAsDeclContext()
? cast<clang::NamedDecl>(parentContext.getAsDeclContext())
: parentContext.getTypedefName();
}

void SwiftLookupTable::addCategory(clang::ObjCCategoryDecl *category) {
Expand Down
2 changes: 1 addition & 1 deletion lib/ClangImporter/SwiftLookupTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ class SwiftLookupTable {
public:
/// Lookup an unresolved context name and resolve it to a Clang
/// named declaration.
clang::NamedDecl *resolveContext(StringRef unresolvedName);
const clang::NamedDecl *resolveContext(StringRef unresolvedName);

/// Lookup the set of entities with the given base name.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Functions:
- Name: ZXSpectrumSetMisnamedRegister
SwiftName: 'setter:ZXSpectrum.misnamedRegister(self:newValue:)'
- Name: ZXSpectrumHelperReset
SwiftName: 'ZXSpectrum.Helper.reset()'
SwiftName: 'ZXSpectrum::Helper.reset()'
32 changes: 32 additions & 0 deletions test/Interop/Cxx/namespace/Inputs/import-as-member.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#define SWIFT_NAME(name) __attribute__((swift_name(name)))

namespace MyNS {
struct NestedStruct {
int value = 123;
};
}

int nestedStruct_method(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.method(self:)") { return p.value; }
int nestedStruct_methodConstRef(const MyNS::NestedStruct &p) SWIFT_NAME("MyNS.NestedStruct.methodConstRef(self:)") { return p.value + 1; }
inline int nestedStruct_methodInline(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.methodInline(self:)") { return p.value + 2; }

namespace MyNS {
namespace MyDeepNS {
struct DeepNestedStruct {
int value = 456;
};
}
}

int deepNestedStruct_method(MyNS::MyDeepNS::DeepNestedStruct p) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.method(self:)") { return p.value; }
int deepNestedStruct_methodConstRef(const MyNS::MyDeepNS::DeepNestedStruct &p) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.methodConstRef(self:)") { return p.value + 2; }

typedef MyNS::MyDeepNS::DeepNestedStruct DeepNestedStructTypedef;

int deepNestedStructTypedef_method(DeepNestedStructTypedef p) SWIFT_NAME("DeepNestedStructTypedef.methodTypedef(self:)") { return p.value + 3; }
int deepNestedStructTypedef_methodQualName(MyNS::MyDeepNS::DeepNestedStruct p) SWIFT_NAME("DeepNestedStructTypedef.methodTypedefQualName(self:)") { return p.value + 4; }

namespace MyNS {
int nestedStruct_nestedMethod(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.nestedMethod(self:)") { return p.value + 3; }
inline int nestedStruct_nestedMethodInline(MyNS::NestedStruct p) SWIFT_NAME("MyNS.NestedStruct.nestedMethodInline(self:)") { return p.value + 4; }
}
6 changes: 6 additions & 0 deletions test/Interop/Cxx/namespace/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ module Enums {
requires cplusplus
}

module ImportAsMember {
header "import-as-member.h"
export *
requires cplusplus
}

module MembersDirect {
header "members-direct.h"
requires cplusplus
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=ImportAsMember -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s

// CHECK: extension MyNS.NestedStruct {
// CHECK-NEXT: func method() -> Int32
// CHECK-NEXT: func methodConstRef() -> Int32
// CHECK-NEXT: func methodInline() -> Int32
// CHECK-NEXT: func nestedMethod() -> Int32
// CHECK-NEXT: func nestedMethodInline() -> Int32
// CHECK-NEXT: }

// CHECK: extension MyNS.MyDeepNS.DeepNestedStruct {
// CHECK-NEXT: func method() -> Int32
// CHECK-NEXT: func methodConstRef() -> Int32
// CHECK-NEXT: func methodTypedef() -> Int32
// CHECK-NEXT: func methodTypedefQualName() -> Int32
// CHECK-NEXT: }
24 changes: 24 additions & 0 deletions test/Interop/Cxx/namespace/import-as-member-typechecker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=upcoming-swift

import ImportAsMember

func takesNestedStruct(_ s: MyNS.NestedStruct) {
_ = s.method()
_ = s.methodConstRef()
_ = s.nestedMethod()
_ = s.nestedMethodInline()

_ = nestedStruct_method(s) // expected-error {{'nestedStruct_method' has been replaced by instance method 'MyNS.NestedStruct.method()'}}
}

func takesDeepNestedStruct(_ s: MyNS.MyDeepNS.DeepNestedStruct) {
_ = s.method()
_ = s.methodConstRef()
_ = s.methodTypedef()
_ = s.methodTypedefQualName()

_ = deepNestedStruct_method(s) // expected-error {{'deepNestedStruct_method' has been replaced by instance method 'MyNS.MyDeepNS.DeepNestedStruct.method()'}}
}

MyNS.method() // expected-error {{type 'MyNS' has no member 'method'}}
MyNS.nestedMethod() // expected-error {{type of expression is ambiguous without a type annotation}}
31 changes: 31 additions & 0 deletions test/Interop/Cxx/namespace/import-as-member.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift)

// REQUIRES: executable_test

import StdlibUnittest
import ImportAsMember

var NamespacesTestSuite = TestSuite("Import as member of namespace")

NamespacesTestSuite.test("Struct in a namespace") {
let s = MyNS.NestedStruct()
expectEqual(123, s.method())
expectEqual(124, s.methodConstRef())
expectEqual(125, s.methodInline())
}

NamespacesTestSuite.test("Struct in a deep namespace") {
let s = MyNS.MyDeepNS.DeepNestedStruct()
expectEqual(456, s.method())
expectEqual(458, s.methodConstRef())
expectEqual(459, s.methodTypedef())
expectEqual(460, s.methodTypedefQualName())
}

NamespacesTestSuite.test("Struct and function in a namespace") {
let s = MyNS.NestedStruct()
expectEqual(126, s.nestedMethod())
expectEqual(127, s.nestedMethodInline())
}

runAllTests()
3 changes: 3 additions & 0 deletions test/Interop/Cxx/objc-correctness/appkit-uikit.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs -cxx-interoperability-mode=default %s
// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs -cxx-interoperability-mode=default %s -swift-version 6

// REQUIRES: objc_interop
// REQUIRES: VENDOR=apple
Expand All @@ -9,6 +10,8 @@ import AppKit

var _: AttributeScopes.AppKitAttributes.UnderlineStyleAttribute! = nil

var _ = NSEvent.SpecialKey.upArrow.rawValue

#elseif canImport(UIKit)
import UIKit

Expand Down