Skip to content

Commit 52f16f0

Browse files
authored
Merge pull request #4173 from slavapestov/bool-is-a-giant-mess-on-darwin-platforms
IRGen: Differentiate between Swift.Bool and ObjCBool
2 parents 0b77871 + a21c748 commit 52f16f0

File tree

15 files changed

+173
-71
lines changed

15 files changed

+173
-71
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,9 +2166,6 @@ ERROR(builtin_string_literal_broken_proto,none,
21662166
ERROR(string_literal_broken_proto,none,
21672167
"protocol 'ExpressibleByStringLiteral' is broken", ())
21682168

2169-
ERROR(bool_type_broken,none,
2170-
"could not find a Bool type defined for 'is'", ())
2171-
21722169
// Array literals
21732170
ERROR(array_protocol_broken,none,
21742171
"ExpressibleByArrayLiteral protocol definition is broken", ())

lib/ClangImporter/ImportType.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ namespace {
331331
pointeeType = Impl.importType(pointeeQualType,
332332
ImportTypeKind::Pointee,
333333
AllowNSUIntegerAsInt,
334-
/*can fully bridge*/false);
334+
/*isFullyBridgeable*/false);
335335

336336
// If the pointed-to type is unrepresentable in Swift, import as
337337
// OpaquePointer.
@@ -418,7 +418,7 @@ namespace {
418418
Type elementType = Impl.importType(type->getElementType(),
419419
ImportTypeKind::Pointee,
420420
AllowNSUIntegerAsInt,
421-
/*can fully bridge*/false);
421+
/*isFullyBridgeable*/false);
422422
if (!elementType)
423423
return Type();
424424

@@ -2272,7 +2272,14 @@ Type ClangImporter::Implementation::importMethodType(
22722272
OptionalityOfReturn);
22732273
// Adjust the result type for a throwing function.
22742274
if (swiftResultTy && errorInfo) {
2275-
origSwiftResultTy = swiftResultTy->getCanonicalType();
2275+
2276+
// Get the original unbridged result type.
2277+
origSwiftResultTy = importType(resultType, resultKind,
2278+
allowNSUIntegerAsIntInResult,
2279+
/*isFullyBridgeable*/false,
2280+
OptionalityOfReturn)
2281+
->getCanonicalType();
2282+
22762283
swiftResultTy = adjustResultTypeForThrowingFunction(*errorInfo,
22772284
swiftResultTy);
22782285
}

lib/IRGen/GenClangType.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -743,15 +743,6 @@ clang::CanQualType ClangTypeConverter::convert(IRGenModule &IGM, CanType type) {
743743
auto ptrTy = ctx.getObjCObjectPointerType(clangType);
744744
return ctx.getCanonicalType(ptrTy);
745745
}
746-
} else if (decl == IGM.Context.getBoolDecl()) {
747-
// FIXME: Handle _Bool and DarwinBoolean.
748-
auto &ctx = IGM.getClangASTContext();
749-
auto &TI = ctx.getTargetInfo();
750-
// FIXME: Figure out why useSignedCharForObjCBool() returns
751-
// 'true' on Linux
752-
if (IGM.ObjCInterop && TI.useSignedCharForObjCBool()) {
753-
return ctx.SignedCharTy;
754-
}
755746
}
756747
}
757748

lib/SILGen/SILGenForeignError.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,20 @@ void SILGenFunction::emitForeignErrorBlock(SILLocation loc,
290290
static SILValue emitUnwrapIntegerResult(SILGenFunction &gen,
291291
SILLocation loc,
292292
SILValue value) {
293-
while (!value->getType().is<BuiltinIntegerType>()) {
294-
auto structDecl = value->getType().getStructOrBoundGenericStruct();
295-
assert(structDecl && "value for error result wasn't of struct type!");
296-
assert(std::next(structDecl->getStoredProperties().begin())
297-
== structDecl->getStoredProperties().end());
298-
auto property = *structDecl->getStoredProperties().begin();
299-
value = gen.B.createStructExtract(loc, value, property);
300-
}
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>());
301307

302308
return value;
303309
}
@@ -315,20 +321,28 @@ emitResultIsZeroErrorCheck(SILGenFunction &gen, SILLocation loc,
315321

316322
SILValue resultValue =
317323
emitUnwrapIntegerResult(gen, loc, result.getUnmanagedValue());
318-
SILValue zero =
319-
gen.B.createIntegerLiteral(loc, resultValue->getType(), 0);
320-
321-
ASTContext &ctx = gen.getASTContext();
322-
SILValue resultIsError =
323-
gen.B.createBuiltinBinaryFunction(loc,
324-
zeroIsError ? "cmp_eq" : "cmp_ne",
325-
resultValue->getType(),
326-
SILType::getBuiltinIntegerType(1, ctx),
327-
{resultValue, zero});
324+
CanType resultType = resultValue->getType().getSwiftRValueType();
325+
326+
if (!resultType->isBuiltinIntegerType(1)) {
327+
SILValue zero =
328+
gen.B.createIntegerLiteral(loc, resultValue->getType(), 0);
329+
330+
ASTContext &ctx = gen.getASTContext();
331+
resultValue =
332+
gen.B.createBuiltinBinaryFunction(loc,
333+
"cmp_ne",
334+
resultValue->getType(),
335+
SILType::getBuiltinIntegerType(1, ctx),
336+
{resultValue, zero});
337+
}
328338

329339
SILBasicBlock *errorBB = gen.createBasicBlock(FunctionSection::Postmatter);
330340
SILBasicBlock *contBB = gen.createBasicBlock();
331-
gen.B.createCondBranch(loc, resultIsError, errorBB, contBB);
341+
342+
if (zeroIsError)
343+
gen.B.createCondBranch(loc, resultValue, contBB, errorBB);
344+
else
345+
gen.B.createCondBranch(loc, resultValue, errorBB, contBB);
332346

333347
gen.emitForeignErrorBlock(loc, errorBB, errorSlot);
334348

lib/Sema/TypeCheckType.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,8 +3025,19 @@ bool TypeChecker::isRepresentableInObjC(
30253025
// Functions that return nothing (void) can be throwing; they indicate
30263026
// failure with a 'false' result.
30273027
kind = ForeignErrorConvention::ZeroResult;
3028-
errorResultType = Context.getBoolDecl()
3029-
->getDeclaredInterfaceType()->getCanonicalType();
3028+
NominalTypeDecl *boolDecl = Context.getObjCBoolDecl();
3029+
// On Linux, we might still run @objc tests even though there's
3030+
// no ObjectiveC Foundation, so use Swift.Bool instead of crapping
3031+
// out.
3032+
if (boolDecl == nullptr)
3033+
boolDecl = Context.getBoolDecl();
3034+
3035+
if (boolDecl == nullptr) {
3036+
diagnose(AFD->getLoc(), diag::broken_bool);
3037+
return false;
3038+
}
3039+
3040+
errorResultType = boolDecl->getDeclaredType()->getCanonicalType();
30303041
} else if (!resultType->getAnyOptionalObjectType() &&
30313042
isBridgedToObjectiveCClass(dc, resultType)) {
30323043
// Functions that return a (non-optional) type bridged to Objective-C

lib/Sema/TypeChecker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,13 @@ Type TypeChecker::lookupBoolType(const DeclContext *dc) {
243243
getStdlibModule(dc)->lookupValue({}, Context.getIdentifier("Bool"),
244244
NLKind::QualifiedLookup, results);
245245
if (results.size() != 1) {
246-
diagnose(SourceLoc(), diag::bool_type_broken);
246+
diagnose(SourceLoc(), diag::broken_bool);
247247
return Type();
248248
}
249249

250250
auto tyDecl = dyn_cast<TypeDecl>(results.front());
251251
if (!tyDecl) {
252-
diagnose(SourceLoc(), diag::bool_type_broken);
252+
diagnose(SourceLoc(), diag::broken_bool);
253253
return Type();
254254
}
255255

test/IRGen/Inputs/abi/Gadget.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ struct BigStruct {
4141

4242
@interface Gadget : NSObject
4343
- (BOOL) negate:(BOOL) b;
44+
- (_Bool) invert:(_Bool) b;
45+
46+
- (BOOL) negateThrowing:(BOOL) b error:(NSError **) error;
47+
48+
// This one is not imported as a 'throws' function in Swift
49+
- (_Bool) invertThrowing:(_Bool) b error:(NSError **) error;
4450
@end
4551

4652
@protocol Pasta

test/IRGen/abitypes.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,48 @@ class Foo {
414414
return g.negate(b)
415415
}
416416

417+
// x86_64-macosx: define hidden i1 @_TFC8abitypes3Foo7negate3fSbSb(i1, %C8abitypes3Foo*) {{.*}} {
418+
// x86_64-macosx: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(invert:)", align 8
419+
// x86_64-macosx: [[NEG:%[0-9]+]] = call zeroext i1 bitcast (void ()* @objc_msgSend to i1 (%1*, i8*, i1)*)(%1* [[RECEIVER:%[0-9]+]], i8* [[SEL]], i1 zeroext %0)
420+
// x86_64-macosx: ret i1 [[NEG]]
421+
// x86_64-macosx: }
422+
423+
// x86_64-ios: define hidden i1 @_TFC8abitypes3Foo7negate3fSbSb(i1, %C8abitypes3Foo*) {{.*}} {
424+
// x86_64-ios: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(invert:)", align 8
425+
// x86_64-ios: [[NEG:%[0-9]+]] = call zeroext i1 bitcast (void ()* @objc_msgSend to i1 (%1*, i8*, i1)*)(%1* [[RECEIVER:%[0-9]+]], i8* [[SEL]], i1 zeroext %0)
426+
// x86_64-ios: ret i1 [[NEG]]
427+
// x86_64-ios: }
428+
429+
// i386-ios: define hidden i1 @_TFC8abitypes3Foo7negate3fSbSb(i1, %C8abitypes3Foo*) {{.*}} {
430+
// i386-ios: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(invert:)", align 4
431+
// i386-ios: [[NEG:%[0-9]+]] = call zeroext i1 bitcast (void ()* @objc_msgSend to i1 (%1*, i8*, i1)*)(%1* [[RECEIVER:%[0-9]+]], i8* [[SEL]], i1 zeroext %0)
432+
// i386-ios: ret i1 [[NEG]]
433+
// i386-ios: }
434+
435+
dynamic func negate3(_ b: Bool) -> Bool {
436+
var g = Gadget()
437+
return g.invert(b)
438+
}
439+
440+
// x86_64-macosx: define hidden void @_TFC8abitypes3Foo10throwsTestfzSbT_(i1, %C8abitypes3Foo*, %swift.error**) {{.*}} {
441+
// x86_64-macosx: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(negateThrowing:error:)", align 8
442+
// x86_64-macosx: call signext i8 bitcast (void ()* @objc_msgSend to i8 (%1*, i8*, i8, %2**)*)(%1* {{%[0-9]+}}, i8* [[SEL]], i8 signext {{%[0-9]+}}, %2** {{%[0-9]+}})
443+
// x86_64-macosx: }
444+
445+
// x86_64-ios: define hidden void @_TFC8abitypes3Foo10throwsTestfzSbT_(i1, %C8abitypes3Foo*, %swift.error**) {{.*}} {
446+
// x86_64-ios: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(negateThrowing:error:)", align 8
447+
// x86_64-ios: call zeroext i1 bitcast (void ()* @objc_msgSend to i1 (%1*, i8*, i1, %2**)*)(%1* {{%[0-9]+}}, i8* [[SEL]], i1 zeroext {{%[0-9]+}}, %2** {{%[0-9]+}})
448+
// x86_64-ios: }
449+
450+
// i386-ios: define hidden void @_TFC8abitypes3Foo10throwsTestfzSbT_(i1, %C8abitypes3Foo*, %swift.error**) {{.*}} {
451+
// i386-ios: [[SEL:%[0-9]+]] = load i8*, i8** @"\01L_selector(negateThrowing:error:)", align 4
452+
// i386-ios: call signext i8 bitcast (void ()* @objc_msgSend to i8 (%1*, i8*, i8, %2**)*)(%1* {{%[0-9]+}}, i8* [[SEL]], i8 signext {{%[0-9]+}}, %2** {{%[0-9]+}})
453+
// i386-ios: }
454+
dynamic func throwsTest(_ b: Bool) throws {
455+
var g = Gadget()
456+
try g.negateThrowing(b)
457+
}
458+
417459
// x86_64-macosx: define hidden i32* @_TToFC8abitypes3Foo24copyUnsafeMutablePointer{{.*}}(i8*, i8*, i32*) unnamed_addr {{.*}} {
418460
dynamic func copyUnsafeMutablePointer(_ p: UnsafeMutablePointer<Int32>) -> UnsafeMutablePointer<Int32> {
419461
return p

test/Interpreter/Inputs/ObjCClasses/ObjCClasses.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ NS_ASSUME_NONNULL_BEGIN
9898
+ (unsigned) count;
9999
@end
100100

101+
@interface TestingBool : NSObject
102+
- (void) shouldBeTrueObjCBool: (BOOL)value;
103+
- (void) shouldBeTrueCBool: (_Bool)value;
104+
@end
105+
101106
NS_ASSUME_NONNULL_END
102107

103108
#endif

test/Interpreter/Inputs/ObjCClasses/ObjCClasses.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#import "ObjCClasses.h"
22
#import <Foundation/NSError.h>
33
#include <stdio.h>
4+
#include <assert.h>
45

56
@implementation HasHiddenIvars
67
@synthesize x;
@@ -151,3 +152,15 @@ + (unsigned) count {
151152
}
152153

153154
@end
155+
156+
@implementation TestingBool
157+
158+
- (void) shouldBeTrueObjCBool: (BOOL)value {
159+
assert(value);
160+
}
161+
162+
- (void) shouldBeTrueCBool: (_Bool)value {
163+
assert(value);
164+
}
165+
166+
@end

test/Interpreter/objc_bool.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
//
4+
// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
5+
// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out
6+
// RUN: %target-run %t/a.out
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: objc_interop
10+
11+
import ObjCClasses
12+
import Foundation
13+
14+
TestingBool().shouldBeTrueObjCBool(true)
15+
TestingBool().shouldBeTrueCBool(true)

0 commit comments

Comments
 (0)