mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Bridge types during import only if we are in a fully-bridgeable context.
Somehow the logic had slipped so that we were basing this decision purely on the ImportTypeKind and not on whether the broader context is bridgeable. This was allowing us to use bridged types when e.g. importing the results and parameters of C function pointer types, which is really bad. Also, when importing a reference to a typedef of block type, do not use the typedef in a non-bridgeable context. We import typedefs of block type as fully-bridged types, but this means that it is invalid to import a type using the typedef in a context where the original C type must be used. Similarly, make sure we use a properly-imported underlying type of the typedef when the typedef itself is unavailable. Also, extend the special behavior of block typedefs to abstract-function typedefs, which seems to be consistent with the expected behavior of the tests. Finally, I changed importType to take a new Bridgeability enum instead of a raw canFullyBridgeTypes bool. At the time, I was doing that because I was going to make it tri-valued; that turned out to be unnecessary, but I think it's an improvement anyway.
This commit is contained in:
@@ -2303,7 +2303,7 @@ namespace {
|
||||
SwiftType = Impl.importType(ClangType,
|
||||
ImportTypeKind::Typedef,
|
||||
isInSystemModule(DC),
|
||||
ClangType->isBlockPointerType(),
|
||||
getTypedefBridgeability(ClangType),
|
||||
OTK_Optional);
|
||||
}
|
||||
|
||||
@@ -2410,7 +2410,7 @@ namespace {
|
||||
auto underlyingType = Impl.importType(decl->getIntegerType(),
|
||||
ImportTypeKind::Enum,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!underlyingType)
|
||||
return nullptr;
|
||||
|
||||
@@ -2447,7 +2447,7 @@ namespace {
|
||||
// Compute the underlying type.
|
||||
auto underlyingType = Impl.importType(
|
||||
decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/ false);
|
||||
Bridgeability::None);
|
||||
if (!underlyingType)
|
||||
return nullptr;
|
||||
|
||||
@@ -3063,7 +3063,7 @@ namespace {
|
||||
auto type = Impl.importType(clangContext.getTagDeclType(clangEnum),
|
||||
ImportTypeKind::Value,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!type)
|
||||
return nullptr;
|
||||
// FIXME: Importing the type will recursively revisit this same
|
||||
@@ -3101,7 +3101,7 @@ namespace {
|
||||
Impl.getClangASTContext().getTagDeclType(clangEnum),
|
||||
ImportTypeKind::Value,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!enumType)
|
||||
return nullptr;
|
||||
|
||||
@@ -3162,7 +3162,7 @@ namespace {
|
||||
auto type = Impl.importType(decl->getType(),
|
||||
ImportTypeKind::Variable,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!type)
|
||||
return nullptr;
|
||||
|
||||
@@ -3385,7 +3385,7 @@ namespace {
|
||||
auto type = Impl.importType(decl->getType(),
|
||||
ImportTypeKind::RecordField,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!type)
|
||||
return nullptr;
|
||||
|
||||
@@ -3454,7 +3454,7 @@ namespace {
|
||||
(isAudited ? ImportTypeKind::AuditedVariable
|
||||
: ImportTypeKind::Variable),
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
|
||||
if (!type)
|
||||
return nullptr;
|
||||
@@ -4332,7 +4332,7 @@ namespace {
|
||||
superclassType = Impl.importType(clangSuperclassType,
|
||||
ImportTypeKind::Abstract,
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (superclassType) {
|
||||
assert(superclassType->is<ClassType>() ||
|
||||
superclassType->is<BoundGenericClassType>());
|
||||
@@ -4938,7 +4938,7 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
|
||||
// Import the type of the underlying storage
|
||||
auto storedUnderlyingType = Impl.importType(
|
||||
decl->getUnderlyingType(), ImportTypeKind::Value, isInSystemModule(dc),
|
||||
decl->getUnderlyingType()->isBlockPointerType(), OTK_None);
|
||||
Bridgeability::None, OTK_None);
|
||||
|
||||
if (auto objTy = storedUnderlyingType->getAnyOptionalObjectType())
|
||||
storedUnderlyingType = objTy;
|
||||
@@ -4956,7 +4956,7 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
|
||||
// Find a bridged type, which may be different
|
||||
auto computedPropertyUnderlyingType = Impl.importType(
|
||||
decl->getUnderlyingType(), ImportTypeKind::Property, isInSystemModule(dc),
|
||||
decl->getUnderlyingType()->isBlockPointerType(), OTK_None);
|
||||
Bridgeability::Full, OTK_None);
|
||||
if (auto objTy = computedPropertyUnderlyingType->getAnyOptionalObjectType())
|
||||
computedPropertyUnderlyingType = objTy;
|
||||
|
||||
@@ -5173,7 +5173,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
|
||||
// Compute the underlying type.
|
||||
auto underlyingType = Impl.importType(
|
||||
decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/ false);
|
||||
Bridgeability::None);
|
||||
if (!underlyingType)
|
||||
return nullptr;
|
||||
|
||||
@@ -5492,7 +5492,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
|
||||
Type swiftPropertyType = Impl.importType(
|
||||
propertyType, ImportTypeKind::Property,
|
||||
Impl.shouldAllowNSUIntegerAsInt(isFromSystemModule, getter),
|
||||
/*isFullyBridgeable*/ true, OTK_ImplicitlyUnwrappedOptional);
|
||||
Bridgeability::Full, OTK_ImplicitlyUnwrappedOptional);
|
||||
if (!swiftPropertyType)
|
||||
return nullptr;
|
||||
|
||||
@@ -6406,7 +6406,8 @@ Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
|
||||
clangBound->stripObjCKindOfTypeAndQuals(Impl.getClangASTContext());
|
||||
Type superclassType =
|
||||
Impl.importType(clang::QualType(unqualifiedClangBound, 0),
|
||||
ImportTypeKind::Abstract, false, false);
|
||||
ImportTypeKind::Abstract, false,
|
||||
Bridgeability::None);
|
||||
if (!superclassType) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
|
||||
auto clangTy = parsed->getType();
|
||||
auto literalType = Impl.importType(clangTy, ImportTypeKind::Value,
|
||||
isInSystemModule(DC),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!literalType)
|
||||
return nullptr;
|
||||
|
||||
@@ -123,7 +123,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
|
||||
} else {
|
||||
constantType = Impl.importType(castType, ImportTypeKind::Value,
|
||||
isInSystemModule(DC),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!constantType)
|
||||
return nullptr;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ static Optional<std::pair<llvm::APSInt, Type>>
|
||||
auto type = impl.importType(literal->getType(),
|
||||
ImportTypeKind::Value,
|
||||
isInSystemModule(DC),
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
return {{ value, type }};
|
||||
}
|
||||
|
||||
|
||||
@@ -176,14 +176,14 @@ namespace {
|
||||
{
|
||||
ClangImporter::Implementation &Impl;
|
||||
bool AllowNSUIntegerAsInt;
|
||||
bool CanFullyBridgeTypes;
|
||||
Bridgeability Bridging;
|
||||
|
||||
public:
|
||||
SwiftTypeConverter(ClangImporter::Implementation &impl,
|
||||
bool allowNSUIntegerAsInt,
|
||||
bool canFullyBridgeTypes)
|
||||
Bridgeability bridging)
|
||||
: Impl(impl), AllowNSUIntegerAsInt(allowNSUIntegerAsInt),
|
||||
CanFullyBridgeTypes(canFullyBridgeTypes) {}
|
||||
Bridging(bridging) {}
|
||||
|
||||
using TypeVisitor::Visit;
|
||||
ImportResult Visit(clang::QualType type) {
|
||||
@@ -356,7 +356,7 @@ namespace {
|
||||
pointeeType = Impl.importType(pointeeQualType,
|
||||
ImportTypeKind::Pointee,
|
||||
AllowNSUIntegerAsInt,
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
|
||||
// If the pointed-to type is unrepresentable in Swift, import as
|
||||
// OpaquePointer.
|
||||
@@ -404,7 +404,7 @@ namespace {
|
||||
Type pointeeType = Impl.importType(type->getPointeeType(),
|
||||
ImportTypeKind::Abstract,
|
||||
AllowNSUIntegerAsInt,
|
||||
CanFullyBridgeTypes);
|
||||
Bridging);
|
||||
if (!pointeeType)
|
||||
return Type();
|
||||
FunctionType *fTy = pointeeType->castTo<FunctionType>();
|
||||
@@ -443,7 +443,7 @@ namespace {
|
||||
Type elementType = Impl.importType(type->getElementType(),
|
||||
ImportTypeKind::Pointee,
|
||||
AllowNSUIntegerAsInt,
|
||||
/*isFullyBridgeable*/false);
|
||||
Bridgeability::None);
|
||||
if (!elementType)
|
||||
return Type();
|
||||
|
||||
@@ -498,7 +498,7 @@ namespace {
|
||||
auto resultTy = Impl.importType(type->getReturnType(),
|
||||
ImportTypeKind::Result,
|
||||
AllowNSUIntegerAsInt,
|
||||
CanFullyBridgeTypes,
|
||||
Bridging,
|
||||
OTK_Optional);
|
||||
if (!resultTy)
|
||||
return Type();
|
||||
@@ -509,7 +509,7 @@ namespace {
|
||||
param != paramEnd; ++param) {
|
||||
auto swiftParamTy = Impl.importType(*param, ImportTypeKind::Parameter,
|
||||
AllowNSUIntegerAsInt,
|
||||
CanFullyBridgeTypes,
|
||||
Bridging,
|
||||
OTK_Optional);
|
||||
if (!swiftParamTy)
|
||||
return Type();
|
||||
@@ -534,7 +534,7 @@ namespace {
|
||||
auto resultTy = Impl.importType(type->getReturnType(),
|
||||
ImportTypeKind::Result,
|
||||
AllowNSUIntegerAsInt,
|
||||
CanFullyBridgeTypes,
|
||||
Bridging,
|
||||
OTK_Optional);
|
||||
if (!resultTy)
|
||||
return Type();
|
||||
@@ -665,12 +665,32 @@ namespace {
|
||||
}
|
||||
// Any other interesting mapped types should be hinted here.
|
||||
|
||||
// Otherwise, recurse on the underlying type in order to compute
|
||||
// the hint correctly.
|
||||
// Otherwise, recurse on the underlying type. We need to recompute
|
||||
// the hint, and if the typedef uses different bridgeability than the
|
||||
// context then we may also need to bypass the typedef.
|
||||
} else {
|
||||
auto underlyingType = type->desugar();
|
||||
|
||||
// Figure out the bridgeability we would normally use for this typedef.
|
||||
auto typedefBridgeability = getTypedefBridgeability(underlyingType);
|
||||
|
||||
// Figure out the typedef we should actually use.
|
||||
auto underlyingBridgeability =
|
||||
(Bridging == Bridgeability::Full
|
||||
? typedefBridgeability : Bridgeability::None);
|
||||
SwiftTypeConverter innerConverter(Impl, AllowNSUIntegerAsInt,
|
||||
/*can fully bridge*/false);
|
||||
auto underlyingResult = innerConverter.Visit(type->desugar());
|
||||
underlyingBridgeability);
|
||||
auto underlyingResult = innerConverter.Visit(underlyingType);
|
||||
|
||||
// If we used different bridgeability than this typedef normally
|
||||
// would because we're in a non-bridgeable context, and therefore
|
||||
// the underlying type is different from the mapping of the typedef,
|
||||
// use the underlying type.
|
||||
if (underlyingBridgeability != typedefBridgeability &&
|
||||
!underlyingResult.AbstractType->isEqual(mappedType)) {
|
||||
return underlyingResult;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
switch (underlyingResult.Hint) {
|
||||
case ImportHint::Block:
|
||||
@@ -960,7 +980,7 @@ namespace {
|
||||
Type importedTypeArg = Impl.importType(typeArg,
|
||||
ImportTypeKind::BridgedValue,
|
||||
AllowNSUIntegerAsInt,
|
||||
CanFullyBridgeTypes,
|
||||
Bridging,
|
||||
OTK_None);
|
||||
if (!importedTypeArg) {
|
||||
importedTypeArgs.clear();
|
||||
@@ -1146,7 +1166,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
ImportTypeKind importKind,
|
||||
ImportHint hint,
|
||||
bool allowNSUIntegerAsInt,
|
||||
bool canFullyBridgeTypes,
|
||||
Bridgeability bridging,
|
||||
OptionalTypeKind optKind,
|
||||
bool resugarNSErrorPointer) {
|
||||
if (importKind == ImportTypeKind::Abstract) {
|
||||
@@ -1261,10 +1281,14 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
importedType = outParamTy;
|
||||
}
|
||||
|
||||
// Turn block pointer types back into normal function types in any
|
||||
// context where bridging is possible, unless the block has a typedef.
|
||||
// SwiftTypeConverter turns block pointers into @convention(block) types.
|
||||
// In a bridgeable context, or in the direct structure of a typedef,
|
||||
// we would prefer to instead use the default Swift convention. But this
|
||||
// does means that, when we're using a typedef of a block pointer type in
|
||||
// an unbridgable context, we need to go back and do a fully-unbridged
|
||||
// import of the underlying type.
|
||||
if (hint == ImportHint::Block) {
|
||||
if (!canFullyBridgeTypes) {
|
||||
if (bridging == Bridgeability::None) {
|
||||
if (auto typedefType = clangType->getAs<clang::TypedefType>()) {
|
||||
// In non-bridged contexts, drop the typealias sugar for blocks.
|
||||
// FIXME: This will do the wrong thing if there's any adjustment to do
|
||||
@@ -1272,7 +1296,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
Type underlyingTy = impl.importType(typedefType->desugar(),
|
||||
importKind,
|
||||
allowNSUIntegerAsInt,
|
||||
canFullyBridgeTypes,
|
||||
bridging,
|
||||
OTK_None);
|
||||
if (Type unwrappedTy = underlyingTy->getAnyOptionalObjectType())
|
||||
underlyingTy = unwrappedTy;
|
||||
@@ -1281,7 +1305,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
}
|
||||
}
|
||||
|
||||
if (canBridgeTypes(importKind) || importKind == ImportTypeKind::Typedef) {
|
||||
if (bridging == Bridgeability::Full) {
|
||||
auto fTy = importedType->castTo<FunctionType>();
|
||||
FunctionType::ExtInfo einfo = fTy->getExtInfo();
|
||||
if (einfo.getRepresentation() != FunctionTypeRepresentation::Swift) {
|
||||
@@ -1294,7 +1318,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
// Turn BOOL and DarwinBoolean into Bool in contexts that can bridge types
|
||||
// losslessly.
|
||||
if ((hint == ImportHint::BOOL || hint == ImportHint::Boolean) &&
|
||||
canFullyBridgeTypes && canBridgeTypes(importKind)) {
|
||||
bridging == Bridgeability::Full && canBridgeTypes(importKind)) {
|
||||
return impl.SwiftContext.getBoolDecl()->getDeclaredType();
|
||||
}
|
||||
|
||||
@@ -1323,7 +1347,9 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
|
||||
// If we have a bridged Objective-C type and we are allowed to
|
||||
// bridge, do so.
|
||||
if (hint == ImportHint::ObjCBridged && canBridgeTypes(importKind) &&
|
||||
if (hint == ImportHint::ObjCBridged &&
|
||||
bridging == Bridgeability::Full &&
|
||||
canBridgeTypes(importKind) &&
|
||||
importKind != ImportTypeKind::PropertyWithReferenceSemantics) {
|
||||
// id and Any can be bridged without Foundation. There would be
|
||||
// bootstrapping issues with the ObjectiveC module otherwise.
|
||||
@@ -1373,7 +1399,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
|
||||
Type ClangImporter::Implementation::importType(clang::QualType type,
|
||||
ImportTypeKind importKind,
|
||||
bool allowNSUIntegerAsInt,
|
||||
bool canFullyBridgeTypes,
|
||||
Bridgeability bridging,
|
||||
OptionalTypeKind optionality,
|
||||
bool resugarNSErrorPointer) {
|
||||
if (type.isNull())
|
||||
@@ -1414,14 +1440,13 @@ Type ClangImporter::Implementation::importType(clang::QualType type,
|
||||
}
|
||||
|
||||
// Perform abstract conversion, ignoring how the type is actually used.
|
||||
SwiftTypeConverter converter(*this, allowNSUIntegerAsInt,canFullyBridgeTypes);
|
||||
SwiftTypeConverter converter(*this, allowNSUIntegerAsInt, bridging);
|
||||
auto importResult = converter.Visit(type);
|
||||
|
||||
// Now fix up the type based on we're concretely using it.
|
||||
return adjustTypeForConcreteImport(*this, type, importResult.AbstractType,
|
||||
importKind, importResult.Hint,
|
||||
allowNSUIntegerAsInt,
|
||||
canFullyBridgeTypes,
|
||||
allowNSUIntegerAsInt, bridging,
|
||||
optionality,
|
||||
resugarNSErrorPointer);
|
||||
}
|
||||
@@ -1493,7 +1518,7 @@ Type ClangImporter::Implementation::importPropertyType(
|
||||
OptionalTypeKind optionality = OTK_ImplicitlyUnwrappedOptional;
|
||||
return importType(decl->getType(), importKind,
|
||||
shouldAllowNSUIntegerAsInt(isFromSystemModule, decl),
|
||||
/*isFullyBridgeable*/ true, optionality);
|
||||
Bridgeability::Full, optionality);
|
||||
}
|
||||
|
||||
/// Apply the @noescape attribute
|
||||
@@ -1566,7 +1591,7 @@ Type ClangImporter::Implementation::importFunctionReturnType(
|
||||
(isAuditedResult ? ImportTypeKind::AuditedResult
|
||||
: ImportTypeKind::Result),
|
||||
allowNSUIntegerAsInt,
|
||||
/*isFullyBridgeable*/ true, OptionalityOfReturn);
|
||||
Bridgeability::Full, OptionalityOfReturn);
|
||||
}
|
||||
|
||||
Type ClangImporter::Implementation::
|
||||
@@ -1628,7 +1653,7 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
|
||||
// Import the parameter type into Swift.
|
||||
Type swiftParamTy =
|
||||
importType(paramTy, importKind, allowNSUIntegerAsInt,
|
||||
/*isFullyBridgeable*/ true, OptionalityOfParam);
|
||||
Bridgeability::Full, OptionalityOfParam);
|
||||
if (!swiftParamTy)
|
||||
return nullptr;
|
||||
|
||||
@@ -1919,7 +1944,7 @@ Type ClangImporter::Implementation::importMethodType(
|
||||
clang::QualType resultType = clangDecl->getReturnType();
|
||||
swiftResultTy = importType(resultType, resultKind,
|
||||
allowNSUIntegerAsIntInResult,
|
||||
/*isFullyBridgeable*/true,
|
||||
Bridgeability::Full,
|
||||
OptionalityOfReturn);
|
||||
// Adjust the result type for a throwing function.
|
||||
if (swiftResultTy && errorInfo) {
|
||||
@@ -1927,7 +1952,7 @@ Type ClangImporter::Implementation::importMethodType(
|
||||
// Get the original unbridged result type.
|
||||
origSwiftResultTy = importType(resultType, resultKind,
|
||||
allowNSUIntegerAsIntInResult,
|
||||
/*isFullyBridgeable*/false,
|
||||
Bridgeability::None,
|
||||
OptionalityOfReturn)
|
||||
->getCanonicalType();
|
||||
|
||||
@@ -2042,7 +2067,7 @@ Type ClangImporter::Implementation::importMethodType(
|
||||
// being lazier.)
|
||||
swiftParamTy = importType(paramTy, importKind,
|
||||
allowNSUIntegerAsIntInParam,
|
||||
/*isFullyBridgeable*/true,
|
||||
Bridgeability::Full,
|
||||
optionalityOfParam,
|
||||
/*resugarNSErrorPointer=*/!paramIsError);
|
||||
}
|
||||
|
||||
@@ -181,6 +181,22 @@ enum class ImportTypeKind {
|
||||
Enum
|
||||
};
|
||||
|
||||
enum class Bridgeability {
|
||||
/// This context does not permit bridging at all. For example, the
|
||||
/// target of a C pointer.
|
||||
None,
|
||||
|
||||
/// This context permits all kinds of bridging. For example, the
|
||||
/// imported result of a method declaration.
|
||||
Full
|
||||
};
|
||||
|
||||
static inline Bridgeability getTypedefBridgeability(clang::QualType type) {
|
||||
return (type->isBlockPointerType() || type->isFunctionType())
|
||||
? Bridgeability::Full
|
||||
: Bridgeability::None;
|
||||
}
|
||||
|
||||
/// \brief Describes the kind of the C type that can be mapped to a stdlib
|
||||
/// swift type.
|
||||
enum class MappedCTypeKind {
|
||||
@@ -893,16 +909,17 @@ public:
|
||||
/// \param allowNSUIntegerAsInt If true, NSUInteger will be imported as Int
|
||||
/// in certain contexts. If false, it will always be imported as UInt.
|
||||
///
|
||||
/// \param canFullyBridgeTypes True if we can bridge types losslessly.
|
||||
/// This is an additional guarantee on top of the ImportTypeKind
|
||||
/// cases that allow bridging, and applies to the entire type.
|
||||
/// \param bridgeability Whether we can bridge types in this context.
|
||||
/// This may restrict the ability to bridge types even in contexts
|
||||
/// that otherwise allow bridging, such as function results and
|
||||
/// parameters.
|
||||
///
|
||||
/// \returns The imported type, or null if this type could
|
||||
/// not be represented in Swift.
|
||||
Type importType(clang::QualType type,
|
||||
ImportTypeKind kind,
|
||||
bool allowNSUIntegerAsInt,
|
||||
bool canFullyBridgeTypes,
|
||||
Bridgeability bridgeability,
|
||||
OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional,
|
||||
bool resugarNSErrorPointer = true);
|
||||
|
||||
|
||||
@@ -24,3 +24,10 @@ idLover.takesArray(ofId: &y) // expected-error{{argument type 'Any' does not con
|
||||
|
||||
idLover.takesId(x)
|
||||
idLover.takesId(y)
|
||||
|
||||
install_global_event_handler(idLover) // expected-error {{cannot convert value of type 'NSIdLover' to expected argument type 'event_handler?' (aka 'Optional<@convention(c) (AnyObject) -> ()>')}}
|
||||
|
||||
// FIXME: this should not type-check!
|
||||
// Function conversions are not legal when converting to a thin function type.
|
||||
let handler: @convention(c) (Any) -> () = { object in () }
|
||||
install_global_event_handler(handler)
|
||||
|
||||
@@ -40,9 +40,13 @@ ObjCBoolBlock testObjCBoolFnToBlockTypedef(ObjCBoolFn);
|
||||
DarwinBooleanBlock testDarwinBooleanFnToBlockTypedef(DarwinBooleanFn);
|
||||
|
||||
typedef __typeof(testCBoolFnToBlockTypedef) CBoolFnToBlockType;
|
||||
typedef __typeof(testObjCBoolFnToBlockTypedef) ObjCCBoolFnToBlockType;
|
||||
typedef __typeof(testObjCBoolFnToBlockTypedef) ObjCBoolFnToBlockType;
|
||||
typedef __typeof(testDarwinBooleanFnToBlockTypedef) DarwinBooleanFnToBlockType;
|
||||
|
||||
extern ObjCBoolFnToBlockType *globalObjCBoolFnToBlockFP;
|
||||
extern ObjCBoolFnToBlockType * __nonnull * __nullable globalObjCBoolFnToBlockFPP;
|
||||
extern ObjCBoolFnToBlockType ^globalObjCBoolFnToBlockBP;
|
||||
|
||||
extern CBoolFn globalCBoolFn;
|
||||
extern ObjCBoolFn globalObjCBoolFn;
|
||||
extern DarwinBooleanFn globalDarwinBooleanFn;
|
||||
|
||||
@@ -43,8 +43,12 @@ func testObjCBoolFnToBlockTypedef(_: @escaping ObjCBoolFn) -> ObjCBoolBlock
|
||||
func testDarwinBooleanFnToBlockTypedef(_: @escaping DarwinBooleanFn) -> DarwinBooleanBlock
|
||||
|
||||
typealias CBoolFnToBlockType = (CBoolFn) -> CBoolBlock
|
||||
typealias ObjCCBoolFnToBlockType = (ObjCBoolFn) -> (ObjCBool) -> ObjCBool
|
||||
typealias DarwinBooleanFnToBlockType = (DarwinBooleanFn) -> (DarwinBoolean) -> DarwinBoolean
|
||||
typealias ObjCBoolFnToBlockType = (ObjCBoolFn) -> ObjCBoolBlock
|
||||
typealias DarwinBooleanFnToBlockType = (DarwinBooleanFn) -> DarwinBooleanBlock
|
||||
|
||||
var globalObjCBoolFnToBlockFP: @convention(c) (ObjCBoolFn) -> @convention(block) (ObjCBool) -> ObjCBool
|
||||
var globalObjCBoolFnToBlockFPP: UnsafeMutablePointer<@convention(c) (ObjCBoolFn) -> @convention(block) (ObjCBool) -> ObjCBool>?
|
||||
var globalObjCBoolFnToBlockBP: @convention(block) (ObjCBoolFn) -> @convention(block) (ObjCBool) -> ObjCBool
|
||||
|
||||
var globalCBoolFn: CBoolFn
|
||||
var globalObjCBoolFn: ObjCBoolFn
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
// CHECK-FOUNDATION: func doSomethingElse(with: NSCopying & NSObjectProtocol)
|
||||
|
||||
// Note: Function type -> "Function".
|
||||
// CHECK-FOUNDATION: func sort(_: @escaping @convention(c) (Any, Any) -> Int)
|
||||
// CHECK-FOUNDATION: func sort(_: @escaping @convention(c) (AnyObject, AnyObject) -> Int)
|
||||
|
||||
// Note: Plural: NSArray without type arguments -> "Objects".
|
||||
// CHECK-FOUNDATION: func remove(_: [Any])
|
||||
|
||||
@@ -1110,3 +1110,6 @@ typedef enum __attribute__((ns_error_domain(NSLaundryErrorDomain))) __attribute_
|
||||
NSLaundryErrorTooMuchSoap = 1,
|
||||
NSLaundryErrorCatInWasher = 2
|
||||
};
|
||||
|
||||
typedef void (*event_handler)(__nonnull id);
|
||||
void install_global_event_handler(__nullable event_handler handler);
|
||||
|
||||
Reference in New Issue
Block a user