Skip to content

Commit 5bd7a27

Browse files
authored
[cxx-interop] Do not over-release objects returned by synthesized C++ methods (#76139)
Call Sema::BuildReturnStmt instead of ReturnStmt::Create so that an implicit cast of kind ARCProduceObject is inserted in the AST. rdar://133731973
1 parent 03c429c commit 5bd7a27

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,8 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
21122112
}
21132113
newMethod->setParams(params);
21142114

2115+
clang::Sema::SynthesizedFunctionScope scope(clangSema, newMethod);
2116+
21152117
// Create a new Clang diagnostic pool to capture any diagnostics
21162118
// emitted during the construction of the method.
21172119
clang::sema::DelayedDiagnosticPool diagPool{
@@ -2159,8 +2161,9 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
21592161
clang::SourceLocation());
21602162
if (!memberCall.isUsable())
21612163
return nullptr;
2162-
auto returnStmt = clang::ReturnStmt::Create(clangCtx, clang::SourceLocation(),
2163-
memberCall.get(), nullptr);
2164+
auto returnStmt =
2165+
clangSema.BuildReturnStmt(clang::SourceLocation(), memberCall.get())
2166+
.get();
21642167

21652168
// Check if there were any Clang errors during the construction
21662169
// of the method body.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface C : NSObject
4+
@end
5+
6+
struct Base {
7+
C *_Nonnull non_virtual_method() const;
8+
virtual C *_Nonnull virtual_method() const;
9+
int a;
10+
};
11+
12+
struct Derived : Base {};

test/Interop/Cxx/class/inheritance/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,9 @@ module VirtualMethods {
3737
header "virtual-methods.h"
3838
requires cplusplus
3939
}
40+
41+
module FunctionsObjC {
42+
header "functions-objc.h"
43+
requires cplusplus
44+
requires objc
45+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-emit-irgen %s -I %S/Inputs -cxx-interoperability-mode=default -Xcc -fno-exceptions -Xcc -fno-objc-exceptions | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
import FunctionsObjC
5+
6+
// CHECK: define linkonce_odr noundef ptr @_ZNK7Derived36__synthesizedBaseCall_virtual_methodEv(ptr noundef nonnull align {{4|8}} dereferenceable(12) %[[THIS:.*]])
7+
// CHECK: %[[THIS_ADDR:.*]] = alloca ptr,
8+
// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]],
9+
// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]],
10+
// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]],
11+
// CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0
12+
// CHECK: %[[V0:.*]] = load ptr, ptr %[[VFN]],
13+
// CHECK: %[[CALL:.*]] = call noundef ptr %[[V0]](ptr noundef nonnull align {{4|8}} dereferenceable(12) %[[THIS1]])
14+
// CHECK: ret ptr %[[CALL]]
15+
16+
// CHECK: define linkonce_odr noundef ptr @_ZNK7Derived40__synthesizedBaseCall_non_virtual_methodEv(ptr noundef nonnull align {{4|8}} dereferenceable(12) %[[THIS:.*]])
17+
// CHECK: %[[THIS_ADDR:.*]] = alloca ptr,
18+
// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]],
19+
// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]],
20+
// CHECK: %[[CALL:.*]] = call noundef ptr @_ZNK4Base18non_virtual_methodEv(ptr noundef nonnull align {{4|8}} dereferenceable(12) %[[THIS1]])
21+
// CHECK: ret ptr %[[CALL]]
22+
23+
func testBaseMethodCall() -> C {
24+
let derived = Derived()
25+
return derived.non_virtual_method()
26+
}
27+
28+
func testBaseVirtualMethodCall() -> C {
29+
let derived = Derived()
30+
return derived.virtual_method()
31+
}

0 commit comments

Comments
 (0)