Skip to content

Commit 23f5e01

Browse files
authored
[CXX Interoperability] Stop re-importing FuncDecl when FuncDecl is imported before parent record (#59607)
We saw a test case failing when 2 records contain the same operator. This occurs because when the first operator is called, we import the record associated with that operator but we also import the _function_ for the 2nd record. So if we have 2 records `Foo` and `Bar` and both implement `operator-`, after calling `Foo`'s `operator-` we would have imported 1. `Foo` 2. `Foo.operator-` 3. `Bar.operator-` Then when we call `Bar.operator-` we try importing `Bar` record & then import the operator again. So that ends up with 1. `Foo` 2. `Foo.operator-` 3. `Bar.operator-` 4. `Bar` 5. `Bar.operator-` which causes there to be 2 imports of the same operator (`FuncDecl`) This patch checks to see if the `FuncDecl` was previously imported and returns early if it has been Thanks @egorzhdan and @zoecarver for helping me debug this one :p
1 parent b8e2f2e commit 23f5e01

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,13 @@ namespace {
27722772
if (!dc)
27732773
return nullptr;
27742774

2775+
// We may have already imported this function decl before we imported the
2776+
// parent record. In such a case it's important we don't re-import.
2777+
auto known = Impl.ImportedDecls.find({decl, getVersion()});
2778+
if (known != Impl.ImportedDecls.end()) {
2779+
return known->second;
2780+
}
2781+
27752782
bool isOperator = decl->getDeclName().getNameKind() ==
27762783
clang::DeclarationName::CXXOperatorName;
27772784
bool isNonSubscriptOperator =

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ struct AddressOnlyIntWrapper {
4949
return value + x * y;
5050
}
5151

52+
AddressOnlyIntWrapper operator-(AddressOnlyIntWrapper rhs) const {
53+
return AddressOnlyIntWrapper(value - rhs.value);
54+
}
5255
AddressOnlyIntWrapper &operator++() {
5356
value++;
5457
return *this;

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,23 @@ import StdlibUnittest
88
var OperatorsTestSuite = TestSuite("Operators")
99

1010
#if !os(Windows) // SR-13129
11-
OperatorsTestSuite.test("LoadableIntWrapper.plus (inline)") {
11+
OperatorsTestSuite.test("LoadableIntWrapper.minus (inline)") {
1212
var lhs = LoadableIntWrapper(value: 42)
1313
let rhs = LoadableIntWrapper(value: 23)
1414

1515
let result = lhs - rhs
1616

1717
expectEqual(19, result.value)
1818
}
19+
20+
OperatorsTestSuite.test("AddressOnlyIntWrapper.minus") {
21+
let lhs = AddressOnlyIntWrapper(42)
22+
let rhs = AddressOnlyIntWrapper(23)
23+
24+
let result = lhs - rhs
25+
26+
expectEqual(19, result.value)
27+
}
1928
#endif
2029

2130
OperatorsTestSuite.test("LoadableIntWrapper.call (inline)") {

0 commit comments

Comments
 (0)