Skip to content

Commit eac1524

Browse files
authored
Merge pull request #20060 from gottesmm/pr-d72b9d7f8355cbe3c62d4424af52b4dae10ab1dd
[typelowering] Look through 1 level of optionality when determining i…
2 parents 4710c43 + dd8edef commit eac1524

File tree

7 files changed

+92
-4
lines changed

7 files changed

+92
-4
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1869,7 +1869,9 @@ class SelectorFamilyConventions : public Conventions {
18691869
break;
18701870
}
18711871

1872-
auto type = tl.getLoweredType().getASTType();
1872+
// Get the underlying AST type, potentially stripping off one level of
1873+
// optionality while we do it.
1874+
CanType type = tl.getLoweredType().unwrapOptionalType().getASTType();
18731875
if (type->hasRetainablePointerRepresentation()
18741876
|| (type->getSwiftNewtypeUnderlyingType() && !tl.isTrivial()))
18751877
return ResultConvention::Autoreleased;

test/IRGen/newtype.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,16 @@ class ObjCTest {
135135
// CHECK-LABEL: define hidden %0* @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo"
136136
// CHECK: [[CASTED:%.+]] = ptrtoint %0* %2 to i{{32|64}}
137137
// CHECK: [[RESULT:%.+]] = call swiftcc i{{32|64}} @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGF"(i{{32|64}} [[CASTED]], %T7newtype8ObjCTestC* swiftself {{%.+}})
138-
// CHECK: [[OPAQUE_RESULT:%.+]] = inttoptr i{{32|64}} [[RESULT]] to %0*
138+
// CHECK: [[AUTORELEASE_RESULT:%.+]] = {{(tail )?}}call {{.*}} @objc_autoreleaseReturnValue {{.*}}(i{{32|64}} [[RESULT]])
139+
// CHECK: [[OPAQUE_RESULT:%.+]] = inttoptr i{{32|64}} [[AUTORELEASE_RESULT]] to %0*
139140
// CHECK: ret %0* [[OPAQUE_RESULT]]
140141
// CHECK: {{^}$}}
141142

142143
// OPT-LABEL: define hidden %0* @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo"
143-
// OPT: ret %0* %2
144+
// OPT: [[CAST_VALUE:%.*]] = bitcast %0* %2 to %objc_object*
145+
// OPT: [[RESULT:%.*]] = {{(tail )?}}call %objc_object* @objc_autoreleaseReturnValue(%objc_object* [[CAST_VALUE]])
146+
// OPT: [[RESULT_CAST:%.*]] = bitcast %objc_object* [[RESULT]] to %0*
147+
// OPT: ret %0* [[RESULT_CAST]]
144148
// OPT: {{^}$}}
145149
@objc func optionalPassThrough(_ ed: ErrorDomain?) -> ErrorDomain? {
146150
return ed

test/Interpreter/Inputs/newtype.m

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
#include <stdio.h>
3+
#include "newtype.h"
4+
5+
@implementation NSMyObject
6+
7+
@synthesize lifetimeTracked;
8+
9+
-(instancetype)init {
10+
self = [super init];
11+
if (!self) {
12+
return nil;
13+
}
14+
self.lifetimeTracked = nil;
15+
return self;
16+
}
17+
18+
- (void)print {
19+
printf("I am alive?!\n");
20+
fflush(stdout);
21+
}
22+
23+
@end
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Newtype {
2+
header "newtype.h"
3+
export *
4+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
@import ObjectiveC;
3+
4+
@interface NSMyObject : NSObject
5+
6+
-(NSMyObject *)init;
7+
-(void)print;
8+
9+
@property(retain) id lifetimeTracked;
10+
11+
@end
12+
13+
typedef NSMyObject *MyObject __attribute((swift_newtype(struct))) __attribute((swift_name("MyObject")));

test/Interpreter/NewtypeLeak.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang -c %S/Inputs/newtype.m -o %t/newtype.objc.o -I %S/Inputs/usr/include -fmodules
3+
// RUN: %target-build-swift -c -I %S/Inputs/usr/include -o %t/newtype.swift.o %s
4+
// RUN: %swiftc_driver %t/newtype.objc.o %t/newtype.swift.o -o %t/newtype
5+
// RUN: %target-codesign %t/newtype
6+
// RUN: %target-run %t/newtype
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: objc_interop
10+
11+
import Foundation
12+
import StdlibUnittest
13+
import Newtype
14+
15+
class ObjCLifetimeTracked : NSMyObject {
16+
var a = LifetimeTracked(0)
17+
}
18+
19+
// Make sure that we do properly autorelease newtypes and do not leak them.
20+
class ObjCTest : NSObject {
21+
@objc dynamic func optionalPassThrough(_ ed: MyObject?) -> MyObject? {
22+
return ed
23+
}
24+
}
25+
26+
func main() {
27+
let e = MyObject(ObjCLifetimeTracked())
28+
let c = ObjCTest()
29+
let x = c.optionalPassThrough(e)!
30+
x.rawValue.print()
31+
}
32+
33+
var Tests = TestSuite("newtypeleak")
34+
35+
Tests.test("dontLeak") {
36+
autoreleasepool {
37+
main()
38+
}
39+
expectEqual(0, LifetimeTracked.instances)
40+
}
41+
42+
runAllTests()

test/SILGen/newtype.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func getRawValue(ed: ErrorDomain) -> String {
4848

4949
class ObjCTest {
5050
// CHECK-RAW-LABEL: sil hidden @$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGF : $@convention(method) (@guaranteed Optional<ErrorDomain>, @guaranteed ObjCTest) -> @owned Optional<ErrorDomain> {
51-
// CHECK-RAW: sil hidden [thunk] @$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo : $@convention(objc_method) (Optional<ErrorDomain>, ObjCTest) -> Optional<ErrorDomain> {
51+
// CHECK-RAW: sil hidden [thunk] @$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo : $@convention(objc_method) (Optional<ErrorDomain>, ObjCTest) -> @autoreleased Optional<ErrorDomain> {
5252
@objc func optionalPassThrough(_ ed: ErrorDomain?) -> ErrorDomain? {
5353
return ed
5454
}

0 commit comments

Comments
 (0)