Skip to content

Commit fee9c2a

Browse files
committed
Allow importing pointer-returning methods as throwing. (#2420)
Leftover bits of SE-0055. Now that pointer nullability is reflected in the type system, we can properly import throwing methods with non-object pointer return types. Note that Swift still won't let you declare them. That's coming next.
1 parent 967fa1d commit fee9c2a

File tree

7 files changed

+95
-50
lines changed

7 files changed

+95
-50
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,27 +1544,8 @@ static bool canImportAsOptional(clang::ASTContext &ctx, clang::QualType type) {
15441544
// Objective-C object pointers.
15451545
if (type->getAs<clang::ObjCObjectPointerType>()) return true;
15461546

1547-
// Block and function pointers.
1548-
if (type->isBlockPointerType() || type->isFunctionPointerType()) return true;
1549-
1550-
// CF types.
1551-
do {
1552-
// Check whether we have a typedef that refers to a CoreFoundation type.
1553-
if (auto typedefType = dyn_cast<clang::TypedefType>(type.getTypePtr())) {
1554-
if (ClangImporter::Implementation::isCFTypeDecl(typedefType->getDecl()))
1555-
return true;
1556-
1557-
type = typedefType->getDecl()->getUnderlyingType();
1558-
continue;
1559-
}
1560-
1561-
// Try to desugar one level...
1562-
clang::QualType desugared = type.getSingleStepDesugaredType(ctx);
1563-
if (desugared.getTypePtr() == type.getTypePtr())
1564-
break;
1565-
1566-
type = desugared;
1567-
} while (!type.isNull());
1547+
// Block and C pointers, including CF types.
1548+
if (type->isBlockPointerType() || type->isPointerType()) return true;
15681549

15691550
return false;
15701551
}

test/IDE/Inputs/swift_name_objc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ SWIFT_NAME(SomeProtocol)
6767
@interface NSErrorImports : NSObject
6868
- (nullable NSObject *)methodAndReturnError:(NSError **)error;
6969
- (BOOL)methodWithFloat:(float)value error:(NSError **)error;
70+
- (nullable void *)pointerMethodAndReturnError:(NSError **)error;
71+
- (nullable SEL)selectorMethodAndReturnError:(NSError **)error;
72+
- (nullable void (*)(void))functionPointerMethodAndReturnError:(NSError **)error;
73+
- (nullable void (^)(void))blockMethodAndReturnError:(NSError **)error;
74+
7075
- (nullable instancetype)initAndReturnError:(NSError **)error;
7176
- (nullable instancetype)initWithFloat:(float)value error:(NSError **)error;
77+
78+
- (nonnull void *)badPointerMethodAndReturnError:(NSError **)error;
7279
@end
7380

7481
typedef const void *CFTypeRef __attribute__((objc_bridge(id)));

test/IDE/dump_swift_lookup_tables_objc.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
// CHECK-NEXT: TU: __swift
5151
// CHECK-NEXT: accessibilityFloat:
5252
// CHECK-NEXT: NSAccessibility: -[NSAccessibility accessibilityFloat]
53+
// CHECK-NEXT: badPointerMethodAndReturnError:
54+
// CHECK-NEXT: NSErrorImports: -[NSErrorImports badPointerMethodAndReturnError:]
55+
// CHECK-NEXT: blockMethod:
56+
// CHECK-NEXT: NSErrorImports: -[NSErrorImports blockMethodAndReturnError:]
5357
// CHECK-NEXT: categoryMethodWith:
5458
// CHECK-NEXT: SNSomeClass: -[SNSomeClass categoryMethodWithX:y:], -[SNSomeClass categoryMethodWithX:y:z:]
5559
// CHECK: doubleProperty:
@@ -58,6 +62,8 @@
5862
// CHECK-NEXT: SNSomeClass: -[SNSomeClass extensionMethodWithX:y:]
5963
// CHECK: floatProperty:
6064
// CHECK-NEXT: SNSomeClass: SNSomeClass.floatProperty
65+
// CHECK-NEXT: functionPointerMethod:
66+
// CHECK-NEXT: NSErrorImports: -[NSErrorImports functionPointerMethodAndReturnError:]
6167
// CHECK-NEXT: init:
6268
// CHECK-NEXT: SNSomeClass: -[SNSomeClass initWithFloat:], -[SNSomeClass initWithDefault], +[SNSomeClass someClassWithDouble:], +[SNSomeClass someClassWithTry:], +[SNSomeClass buildWithUnsignedChar:]
6369
// CHECK-NEXT: UIActionSheet: -[UIActionSheet initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:]
@@ -70,10 +76,14 @@
7076
// CHECK-NEXT: SNSomeClass: -[SNSomeClass objectAtIndexedSubscript:]
7177
// CHECK-NEXT: optSetter:
7278
// CHECK-NEXT: SNCollision: SNCollision.optSetter
79+
// CHECK-NEXT: pointerMethod:
80+
// CHECK-NEXT: NSErrorImports: -[NSErrorImports pointerMethodAndReturnError:]
7381
// CHECK-NEXT: protoInstanceMethodWith:
7482
// CHECK-NEXT: SNSomeProtocol: -[SNSomeProtocol protoInstanceMethodWithX:y:]
7583
// CHECK: reqSetter:
7684
// CHECK-NEXT: SNCollision: SNCollision.reqSetter
85+
// CHECK-NEXT: selectorMethod:
86+
// CHECK-NEXT: NSErrorImports: -[NSErrorImports selectorMethodAndReturnError:]
7787
// CHECK-NEXT: setAccessibilityFloat:
7888
// CHECK-NEXT: NSAccessibility: -[NSAccessibility setAccessibilityFloat:]
7989
// CHECK-NEXT: subscript:

test/Interpreter/Inputs/ObjCClasses/ObjCClasses.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ NS_ASSUME_NONNULL_BEGIN
1414
@property NSInteger t;
1515
@end
1616

17-
/* This class has a method that doesn't fill in the error properly. */
18-
@interface NilError : NSObject
19-
+ (BOOL) throwIt: (NSError**) error;
17+
@interface TestingNSError : NSObject
18+
+ (BOOL)throwNilError:(NSError**)error;
19+
+ (nullable void *)maybeThrow:(BOOL)shouldThrow error:(NSError **)error;
20+
+ (nullable void (^)(void))blockThrowError:(NSError **)error;
2021
@end
2122

2223
@interface Container<C> : NSObject

test/Interpreter/Inputs/ObjCClasses/ObjCClasses.m

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#include "ObjCClasses.h"
1+
#import "ObjCClasses.h"
2+
#import <Foundation/NSError.h>
23
#include <stdio.h>
34

45
@implementation HasHiddenIvars
@@ -8,10 +9,24 @@ @implementation HasHiddenIvars
89
@synthesize t;
910
@end
1011

11-
@implementation NilError
12-
+ (BOOL) throwIt: (NSError**) error {
12+
@implementation TestingNSError
13+
+ (BOOL)throwNilError:(NSError **)error {
1314
return 0;
1415
}
16+
17+
+ (nullable void *)maybeThrow:(BOOL)shouldThrow error:(NSError **)error {
18+
if (shouldThrow) {
19+
*error = [NSError errorWithDomain:@"pointer error" code:0 userInfo:nil];
20+
return 0;
21+
}
22+
return (void *)42;
23+
}
24+
25+
+ (nullable void (^)(void))blockThrowError:(NSError **)error {
26+
*error = [NSError errorWithDomain:@"block error" code:0 userInfo:nil];
27+
return 0;
28+
}
29+
1530
@end
1631

1732
@implementation Container
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
//
3+
// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
4+
// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ %t/ObjCClasses.o %s -o %t/a.out
5+
// RUN: %target-run %t/a.out
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: objc_interop
9+
10+
import ObjCClasses
11+
import Foundation
12+
import StdlibUnittest
13+
14+
var ErrorHandlingTests = TestSuite("ErrorHandling")
15+
16+
ErrorHandlingTests.test("nil") {
17+
do {
18+
try TestingNSError.throwNilError()
19+
expectUnreachable()
20+
} catch {
21+
expectEqual("Foundation._GenericObjCError.nilError", String(reflecting: error))
22+
}
23+
}
24+
25+
ErrorHandlingTests.test("pointerFailure") {
26+
do {
27+
_ = try TestingNSError.maybeThrow(true)
28+
expectUnreachable()
29+
} catch let error as NSError {
30+
expectEqual("pointer error", error.domain)
31+
}
32+
}
33+
34+
ErrorHandlingTests.test("pointerSuccess") {
35+
do {
36+
var pointer = try TestingNSError.maybeThrow(false)
37+
expectType(UnsafeMutablePointer<Void>.self, &pointer)
38+
expectEqual(UnsafeMutablePointer(bitPattern: 42)!, pointer)
39+
} catch {
40+
expectUnreachableCatch(error)
41+
}
42+
}
43+
44+
ErrorHandlingTests.test("blockFailure") {
45+
do {
46+
_ = try TestingNSError.blockThrowError()
47+
expectUnreachable()
48+
} catch let error as NSError {
49+
expectEqual("block error", error.domain)
50+
}
51+
}
52+
53+
runAllTests()
54+

test/Interpreter/nil_error_value.swift

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)