Skip to content

Commit 457055d

Browse files
authored
Merge pull request #4693 from jrose-apple/swift-3-swift_error-zero_result
[SILGen] Restore old logic for checking (non-)zero error results.
2 parents 915a59f + ac51b35 commit 457055d

File tree

4 files changed

+78
-19
lines changed

4 files changed

+78
-19
lines changed

lib/SILGen/SILGenForeignError.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -290,20 +290,16 @@ void SILGenFunction::emitForeignErrorBlock(SILLocation loc,
290290
static SILValue emitUnwrapIntegerResult(SILGenFunction &gen,
291291
SILLocation loc,
292292
SILValue value) {
293-
CanType boolType = gen.SGM.Types.getBoolType();
294-
295-
value = gen.emitBridgedToNativeValue(
296-
loc, ManagedValue::forUnmanaged(value),
297-
SILFunctionTypeRepresentation::CFunctionPointer,
298-
boolType).forward(gen);
299-
300-
auto structDecl = value->getType().getStructOrBoundGenericStruct();
301-
assert(structDecl && "value for error result wasn't of struct type!");
302-
assert(std::next(structDecl->getStoredProperties().begin())
303-
== structDecl->getStoredProperties().end());
304-
auto property = *structDecl->getStoredProperties().begin();
305-
value = gen.B.createStructExtract(loc, value, property);
306-
assert(value->getType().is<BuiltinIntegerType>());
293+
// This is a loop because we want to handle types that wrap integer types,
294+
// like ObjCBool (which may be Bool or Int8).
295+
while (!value->getType().is<BuiltinIntegerType>()) {
296+
auto structDecl = value->getType().getStructOrBoundGenericStruct();
297+
assert(structDecl && "value for error result wasn't of struct type!");
298+
assert(std::next(structDecl->getStoredProperties().begin())
299+
== structDecl->getStoredProperties().end());
300+
auto property = *structDecl->getStoredProperties().begin();
301+
value = gen.B.createStructExtract(loc, value, property);
302+
}
307303

308304
return value;
309305
}

test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ extension Int : _ObjectiveCBridgeable {
103103
}
104104
}
105105

106+
extension Bool: _ObjectiveCBridgeable {
107+
public func _bridgeToObjectiveC() -> NSNumber {
108+
return NSNumber()
109+
}
110+
public static func _forceBridgeFromObjectiveC(
111+
_ x: NSNumber,
112+
result: inout Bool?
113+
) {
114+
}
115+
public static func _conditionallyBridgeFromObjectiveC(
116+
_ x: NSNumber,
117+
result: inout Bool?
118+
) -> Bool {
119+
return true
120+
}
121+
public static func _unconditionallyBridgeFromObjectiveC(
122+
_ x: NSNumber?
123+
) -> Bool {
124+
return false
125+
}
126+
}
127+
106128
extension Array : _ObjectiveCBridgeable {
107129
public func _bridgeToObjectiveC() -> NSArray {
108130
return NSArray()

test/Inputs/clang-importer-sdk/usr/include/errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
+ (float) bounce: (NSError**) err __attribute__((swift_error(nonnull_error)));
4646
+ (void) flounce: (NSError**) err __attribute__((swift_error(nonnull_error)));
4747
+ (int) ounce: (NSError**) err __attribute__((swift_error(zero_result)));
48+
+ (NSInteger) ounceWord: (NSError**) err __attribute__((swift_error(zero_result)));
4849
+ (int) once: (NSError**) err __attribute__((swift_error(nonzero_result)));
4950
+ (BOOL) sconce: (NSError**) err __attribute__((swift_error(zero_result)));
5051
+ (BOOL) scotch: (NSError**) err __attribute__((swift_error(nonzero_result)));

test/SILGen/foreign_errors.swift

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -parse-as-library %s | %FileCheck %s
1+
// RUN: rm -rf %t && mkdir -p %t
2+
// RUN: %build-clang-importer-objc-overlays
3+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-silgen -parse-as-library %s | %FileCheck %s
24

35
// REQUIRES: objc_interop
46

@@ -31,10 +33,12 @@ func test0() throws {
3133
// CHECK: assign [[T1]] to [[ERR_TEMP0]]
3234

3335
// Pull out the boolean value and compare it to zero.
34-
// CHECK: [[FN:%.*]] = function_ref @_TF10ObjectiveC22_convertObjCBoolToBoolFVS_8ObjCBoolSb
35-
// CHECK: [[BOOL:%.*]] = apply [[FN]]([[RESULT]])
36-
// CHECK: [[BIT:%.*]] = struct_extract [[BOOL]]
37-
// CHECK: cond_br [[BIT]], [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
36+
// CHECK: [[BOOL_OR_INT:%.*]] = struct_extract [[RESULT]]
37+
// CHECK: [[RAW_VALUE:%.*]] = struct_extract [[BOOL_OR_INT]]
38+
// On some platforms RAW_VALUE will be compared against 0; on others it's
39+
// already an i1 (bool) and those instructions will be skipped. Just do a
40+
// looser check.
41+
// CHECK: cond_br {{%.+}}, [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
3842
try ErrorProne.fail()
3943

4044
// Normal path: fall out and return.
@@ -229,3 +233,39 @@ func testPreservedResult() throws -> CInt {
229233
// CHECK-NOT: release
230234
// CHECK: return [[RESULT]]
231235
// CHECK: [[ERROR_BB]]
236+
237+
func testPreservedResultBridged() throws -> Int {
238+
return try ErrorProne.ounceWord()
239+
}
240+
241+
// CHECK-LABEL: sil hidden @_TF14foreign_errors26testPreservedResultBridgedFzT_Si
242+
// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
243+
// CHECK: [[T1:%.*]] = class_method [volatile] [[T0]] : $@thick ErrorProne.Type, #ErrorProne.ounceWord!1.foreign : (ErrorProne.Type) -> () throws -> Int , $@convention(objc_method) (ImplicitlyUnwrappedOptional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int
244+
// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
245+
// CHECK: [[RESULT:%.*]] = apply [[T1]](
246+
// CHECK: [[T0:%.*]] = struct_extract [[RESULT]]
247+
// CHECK: [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
248+
// CHECK: [[T2:%.*]] = builtin "cmp_ne_Int{{.*}}"([[T0]] : $[[PRIM]], [[T1]] : $[[PRIM]])
249+
// CHECK: cond_br [[T2]], [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
250+
// CHECK: [[NORMAL_BB]]:
251+
// CHECK-NOT: release
252+
// CHECK: return [[RESULT]]
253+
// CHECK: [[ERROR_BB]]
254+
255+
func testPreservedResultInverted() throws {
256+
try ErrorProne.once()
257+
}
258+
259+
// CHECK-LABEL: sil hidden @_TF14foreign_errors27testPreservedResultInvertedFzT_T_
260+
// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
261+
// CHECK: [[T1:%.*]] = class_method [volatile] [[T0]] : $@thick ErrorProne.Type, #ErrorProne.once!1.foreign : (ErrorProne.Type) -> () throws -> () , $@convention(objc_method) (ImplicitlyUnwrappedOptional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
262+
// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
263+
// CHECK: [[RESULT:%.*]] = apply [[T1]](
264+
// CHECK: [[T0:%.*]] = struct_extract [[RESULT]]
265+
// CHECK: [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
266+
// CHECK: [[T2:%.*]] = builtin "cmp_ne_Int32"([[T0]] : $[[PRIM]], [[T1]] : $[[PRIM]])
267+
// CHECK: cond_br [[T2]], [[ERROR_BB:bb[0-9]+]], [[NORMAL_BB:bb[0-9]+]]
268+
// CHECK: [[NORMAL_BB]]:
269+
// CHECK-NOT: release
270+
// CHECK: return {{%.+}} : $()
271+
// CHECK: [[ERROR_BB]]

0 commit comments

Comments
 (0)