Skip to content

Commit 4603c84

Browse files
authored
Merge pull request #61181 from zoecarver/lookup-operator
[cxx-interop] Fix friend operators that come from class template specializations.
2 parents 1ffe3eb + 0010337 commit 4603c84

File tree

6 files changed

+65
-4
lines changed

6 files changed

+65
-4
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,6 +2712,11 @@ static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter,
27122712
if (OwningClangModule == ModuleFilter->getClangModule())
27132713
return true;
27142714

2715+
// Friends from class templates don't have an owning module. Just return true.
2716+
if (isa<clang::FunctionDecl>(D) &&
2717+
cast<clang::FunctionDecl>(D)->isThisDeclarationInstantiatedFromAFriendDefinition())
2718+
return true;
2719+
27152720
// Handle redeclarable Clang decls by checking each redeclaration.
27162721
bool IsTagDecl = isa<clang::TagDecl>(D);
27172722
if (!(IsTagDecl || isa<clang::FunctionDecl>(D) || isa<clang::VarDecl>(D) ||
@@ -4124,7 +4129,13 @@ bool ClangImporter::Implementation::lookupValue(SwiftLookupTable &table,
41244129

41254130
// If the name matched, report this result.
41264131
bool anyMatching = false;
4127-
if (decl->getName().matchesRef(name) &&
4132+
4133+
// Use the base name for operators; they likely won't have parameters.
4134+
auto foundDeclName = decl->getName();
4135+
if (foundDeclName.isOperator())
4136+
foundDeclName = foundDeclName.getBaseName();
4137+
4138+
if (foundDeclName.matchesRef(name) &&
41284139
decl->getDeclContext()->isModuleScopeContext()) {
41294140
consumer.foundDecl(decl, DeclVisibilityKind::VisibleAtTopLevel);
41304141
anyMatching = true;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2133,7 +2133,16 @@ namespace {
21332133
if (auto friendDecl = dyn_cast<clang::FriendDecl>(m)) {
21342134
if (friendDecl->getFriendDecl()) {
21352135
m = friendDecl->getFriendDecl();
2136-
auto lookupTable = Impl.findLookupTable(m->getOwningModule());
2136+
2137+
// Find the owning module of the class template. Members of class
2138+
// template specializations don't have an owning module.
2139+
clang::Module *owningModule = nullptr;
2140+
if (auto spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(decl))
2141+
owningModule = spec->getSpecializedTemplate()->getOwningModule();
2142+
else
2143+
owningModule = decl->getOwningModule();
2144+
2145+
auto lookupTable = Impl.findLookupTable(owningModule);
21372146
addEntryToLookupTable(*lookupTable, friendDecl->getFriendDecl(),
21382147
Impl.getNameImporter());
21392148
}
@@ -8233,6 +8242,15 @@ ClangImporter::Implementation::importDeclContextOf(
82338242
if (dc->getDeclKind() == clang::Decl::LinkageSpec)
82348243
dc = dc->getParent();
82358244

8245+
// Treat friend decls like top-level decls.
8246+
if (auto functionDecl = dyn_cast<clang::FunctionDecl>(decl)) {
8247+
if (functionDecl->getFriendObjectKind()) {
8248+
// Find the top-level decl context.
8249+
while (isa<clang::NamedDecl>(dc))
8250+
dc = dc->getParent();
8251+
}
8252+
}
8253+
82368254
if (dc->isTranslationUnit()) {
82378255
if (auto *module = getClangModuleForDecl(decl))
82388256
return module;

test/Interop/Cxx/class/nested-records-module-interface.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
// CHECK: struct ForwardDeclaredFriend {
8383
// CHECK: init()
8484
// CHECK: }
85-
// CHECK: static func takesFriend(_ f: NestedDeclIsAFirstForwardDeclaration.ForwardDeclaredFriend)
85+
// CHECK: func takesFriend(_ f: NestedDeclIsAFirstForwardDeclaration.ForwardDeclaredFriend)
8686
// CHECK: struct HasNestedForwardDeclaration {
8787
// CHECK: init()
8888
// CHECK: struct IsNestedForwardDeclaration {

test/Interop/Cxx/operators/Inputs/member-inline.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ struct LoadableBoolWrapper {
5050
}
5151
};
5252

53+
template<class T>
54+
struct TemplatedWithFriendOperator {
55+
friend bool operator==(const TemplatedWithFriendOperator &lhs,
56+
const TemplatedWithFriendOperator &rhs) {
57+
return true;
58+
}
59+
};
60+
61+
using TemplatedWithFriendOperatorSpec = TemplatedWithFriendOperator<int>;
62+
5363
struct __attribute__((swift_attr("import_owned"))) AddressOnlyIntWrapper {
5464
int value;
5565

test/Interop/Cxx/operators/member-inline.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ OperatorsTestSuite.test("LoadableIntWrapper.successor() (inline)") {
8585
expectEqual(42, wrapper.value)
8686
}
8787

88+
OperatorsTestSuite.test("TemplatedWithFriendOperator.equal (inline)") {
89+
let lhs = TemplatedWithFriendOperatorSpec()
90+
let rhs = TemplatedWithFriendOperatorSpec()
91+
92+
let result = lhs == rhs
93+
94+
expectTrue(result)
95+
}
96+
8897
#if !os(Windows) // https://github.com/apple/swift/issues/55575
8998
OperatorsTestSuite.test("LoadableBoolWrapper.exclaim (inline)") {
9099
var wrapper = LoadableBoolWrapper(value: true)

test/Interop/Cxx/stdlib/use-std-map.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop)
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xfrontend -validate-tbd-against-ir=none)
22
//
33
// REQUIRES: executable_test
44
//
@@ -7,6 +7,8 @@
77

88
import StdlibUnittest
99
import StdMap
10+
import std
11+
import Cxx
1012

1113
var StdMapTestSuite = TestSuite("StdMap")
1214

@@ -26,4 +28,15 @@ StdMapTestSuite.test("subscript") {
2628
expectEqual(m[3], 3)
2729
}
2830

31+
extension Map.const_iterator : UnsafeCxxInputIterator { }
32+
extension Map : CxxSequence { }
33+
34+
StdMapTestSuite.test("first(where:)") {
35+
let m = initMap()
36+
let found = m.first(where: { $0.first > 1 })
37+
38+
expectEqual(found!.first, 2)
39+
expectEqual(found!.second, 2)
40+
}
41+
2942
runAllTests()

0 commit comments

Comments
 (0)