Skip to content

Commit 67e361a

Browse files
authored
Merge pull request #61205 from apple/egorzhdan/cxx-successor-no-immortal
[cxx-interop] Do not synthesize `successor()` for immortal types
2 parents d643b22 + e58e249 commit 67e361a

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2221,7 +2221,21 @@ namespace {
22212221
MD->overwriteAccess(AccessLevel::Private);
22222222
} else if (cxxOperatorKind ==
22232223
clang::OverloadedOperatorKind::OO_PlusPlus) {
2224-
if (cxxMethod->param_empty()) {
2224+
// Make sure the type is not an immortal foreign reference type.
2225+
// We cannot handle `operator++` for those types, since the
2226+
// current implementation creates a new instance of the type.
2227+
bool isImmortal = false;
2228+
if (auto classDecl = dyn_cast<ClassDecl>(result)) {
2229+
auto retainOperation = evaluateOrDefault(
2230+
Impl.SwiftContext.evaluator,
2231+
CustomRefCountingOperation(
2232+
{classDecl, CustomRefCountingOperationKind::retain}),
2233+
{});
2234+
isImmortal = retainOperation.kind ==
2235+
CustomRefCountingOperationResult::immortal;
2236+
}
2237+
2238+
if (cxxMethod->param_empty() && !isImmortal) {
22252239
// This is a pre-increment operator. We synthesize a
22262240
// non-mutating function called `successor() -> Self`.
22272241
FuncDecl *successorFunc = synthesizer.makeSuccessorFunc(MD);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ struct HasPreIncrementOperatorWithVoidReturnType {
8585
void operator++() { ++value; }
8686
};
8787

88+
struct __attribute__((swift_attr("import_reference"),
89+
swift_attr("retain:immortal"),
90+
swift_attr("release:immortal"))) ImmortalCounter {
91+
int value = 0;
92+
93+
ImmortalCounter &operator++() {
94+
value++;
95+
return *this;
96+
}
97+
};
98+
static ImmortalCounter myCounter;
99+
88100
struct HasDeletedOperator {
89101
void operator!=(HasDeletedOperator) const = delete;
90102
};

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,5 @@ let anotherReturnTypeResult: HasPreIncrementOperatorWithAnotherReturnType = anot
4949

5050
let voidReturnType = HasPreIncrementOperatorWithVoidReturnType()
5151
let voidReturnTypeResult: HasPreIncrementOperatorWithVoidReturnType = voidReturnType.successor()
52+
53+
let immortalIncrement = myCounter.successor() // expected-error {{value of type 'ImmortalCounter' has no member 'successor'}}

0 commit comments

Comments
 (0)