Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5816,6 +5816,8 @@ Expr *ExprRewriter::buildCollectionUpcastExpr(Expr *expr, Type toType,

Expr *ExprRewriter::buildObjCBridgeExpr(Expr *expr, Type toType,
ConstraintLocatorBuilder locator) {
auto &tc = cs.getTypeChecker();

Type fromType = cs.getType(expr);

// Bridged collection casts always succeed, so we treat them as
Expand All @@ -5838,6 +5840,20 @@ Expr *ExprRewriter::buildObjCBridgeExpr(Expr *expr, Type toType,
if (!objcExpr)
return nullptr;

// We might have a coercion of a Swift type to a CF type toll-free
// bridged to Objective-C.
//
// FIXME: Ideally we would instead have already recorded a restriction
// when solving the constraint, and we wouldn't need to duplicate this
// part of coerceToType() here.
if (auto foreignClass = toType->getClassOrBoundGenericClass()) {
if (foreignClass->getForeignClassKind() ==
ClassDecl::ForeignKind::CFType) {
return cs.cacheType(
new (tc.Context) ForeignObjectConversionExpr(objcExpr, toType));
}
}

return coerceToType(objcExpr, toType, locator);
}

Expand Down
4 changes: 4 additions & 0 deletions test/Inputs/clang-importer-sdk/usr/include/CoreFoundation.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ typedef struct __attribute__((objc_bridge(NSString))) __CFString const *CFString
typedef struct __CFTree *CFTreeRef;
typedef const struct __attribute__((objc_bridge(CFURL))) __CFURL * CFURLRef;

typedef struct __attribute__((objc_bridge(NSDictionary))) __CFDictionary const *CFDictionaryRef;
typedef struct __attribute__((objc_bridge(NSArray))) __CFArray const *CFArrayRef;
typedef struct __attribute__((objc_bridge(NSSet))) __CFSet const *CFSetRef;

typedef CFTypeRef CFAliasForTypeRef;


Expand Down
22 changes: 22 additions & 0 deletions test/expr/cast/cf.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,25 @@ func testCFConvWithIUO(_ x: CFString!, y: NSString!) {
acceptNSString(x)
acceptCFString(y)
}

func testBridgedCFDowncast(array: [Any], dictionary: [AnyHashable : Any], set: Set<AnyHashable>) {
let cfArray = array as CFArray
let cfDictionary = dictionary as CFDictionary
let cfSet = set as CFSet

_ = array as? CFArray // expected-warning {{conditional cast from '[Any]' to 'CFArray' always succeeds}}
_ = dictionary as? CFDictionary // expected-warning {{conditional cast from '[AnyHashable : Any]' to 'CFDictionary' always succeeds}}
_ = set as? CFSet // expected-warning {{conditional cast from 'Set<AnyHashable>' to 'CFSet' always succeeds}}

_ = array as! CFArray // expected-warning {{forced cast from '[Any]' to 'CFArray' always succeeds}}
_ = dictionary as! CFDictionary // expected-warning {{forced cast from '[AnyHashable : Any]' to 'CFDictionary' always succeeds}}
_ = set as! CFSet // expected-warning {{forced cast from 'Set<AnyHashable>' to 'CFSet' always succeeds}}

_ = cfArray as! [Any]
_ = cfDictionary as! [AnyHashable : Any]
_ = cfSet as! Set<AnyHashable>

_ = cfArray as? [Any]
_ = cfDictionary as? [AnyHashable : Any]
_ = cfSet as? Set<AnyHashable>
}