Merge pull request #10832 from rjmccall/fix-function-component-bridging-import

Bridge types during import only if we are in a fully-bridgeable context.
This commit is contained in:
John McCall
2017-07-09 16:47:01 -04:00
committed by GitHub
9 changed files with 118 additions and 57 deletions

View File

@@ -2303,7 +2303,7 @@ namespace {
SwiftType = Impl.importType(ClangType, SwiftType = Impl.importType(ClangType,
ImportTypeKind::Typedef, ImportTypeKind::Typedef,
isInSystemModule(DC), isInSystemModule(DC),
ClangType->isBlockPointerType(), getTypedefBridgeability(ClangType),
OTK_Optional); OTK_Optional);
} }
@@ -2410,7 +2410,7 @@ namespace {
auto underlyingType = Impl.importType(decl->getIntegerType(), auto underlyingType = Impl.importType(decl->getIntegerType(),
ImportTypeKind::Enum, ImportTypeKind::Enum,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!underlyingType) if (!underlyingType)
return nullptr; return nullptr;
@@ -2447,7 +2447,7 @@ namespace {
// Compute the underlying type. // Compute the underlying type.
auto underlyingType = Impl.importType( auto underlyingType = Impl.importType(
decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc), decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
/*isFullyBridgeable*/ false); Bridgeability::None);
if (!underlyingType) if (!underlyingType)
return nullptr; return nullptr;
@@ -3063,7 +3063,7 @@ namespace {
auto type = Impl.importType(clangContext.getTagDeclType(clangEnum), auto type = Impl.importType(clangContext.getTagDeclType(clangEnum),
ImportTypeKind::Value, ImportTypeKind::Value,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!type) if (!type)
return nullptr; return nullptr;
// FIXME: Importing the type will recursively revisit this same // FIXME: Importing the type will recursively revisit this same
@@ -3101,7 +3101,7 @@ namespace {
Impl.getClangASTContext().getTagDeclType(clangEnum), Impl.getClangASTContext().getTagDeclType(clangEnum),
ImportTypeKind::Value, ImportTypeKind::Value,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!enumType) if (!enumType)
return nullptr; return nullptr;
@@ -3162,7 +3162,7 @@ namespace {
auto type = Impl.importType(decl->getType(), auto type = Impl.importType(decl->getType(),
ImportTypeKind::Variable, ImportTypeKind::Variable,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!type) if (!type)
return nullptr; return nullptr;
@@ -3385,7 +3385,7 @@ namespace {
auto type = Impl.importType(decl->getType(), auto type = Impl.importType(decl->getType(),
ImportTypeKind::RecordField, ImportTypeKind::RecordField,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!type) if (!type)
return nullptr; return nullptr;
@@ -3454,7 +3454,7 @@ namespace {
(isAudited ? ImportTypeKind::AuditedVariable (isAudited ? ImportTypeKind::AuditedVariable
: ImportTypeKind::Variable), : ImportTypeKind::Variable),
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!type) if (!type)
return nullptr; return nullptr;
@@ -4332,7 +4332,7 @@ namespace {
superclassType = Impl.importType(clangSuperclassType, superclassType = Impl.importType(clangSuperclassType,
ImportTypeKind::Abstract, ImportTypeKind::Abstract,
isInSystemModule(dc), isInSystemModule(dc),
/*isFullyBridgeable*/false); Bridgeability::None);
if (superclassType) { if (superclassType) {
assert(superclassType->is<ClassType>() || assert(superclassType->is<ClassType>() ||
superclassType->is<BoundGenericClassType>()); superclassType->is<BoundGenericClassType>());
@@ -4938,7 +4938,7 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
// Import the type of the underlying storage // Import the type of the underlying storage
auto storedUnderlyingType = Impl.importType( auto storedUnderlyingType = Impl.importType(
decl->getUnderlyingType(), ImportTypeKind::Value, isInSystemModule(dc), decl->getUnderlyingType(), ImportTypeKind::Value, isInSystemModule(dc),
decl->getUnderlyingType()->isBlockPointerType(), OTK_None); Bridgeability::None, OTK_None);
if (auto objTy = storedUnderlyingType->getAnyOptionalObjectType()) if (auto objTy = storedUnderlyingType->getAnyOptionalObjectType())
storedUnderlyingType = objTy; storedUnderlyingType = objTy;
@@ -4956,7 +4956,7 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
// Find a bridged type, which may be different // Find a bridged type, which may be different
auto computedPropertyUnderlyingType = Impl.importType( auto computedPropertyUnderlyingType = Impl.importType(
decl->getUnderlyingType(), ImportTypeKind::Property, isInSystemModule(dc), decl->getUnderlyingType(), ImportTypeKind::Property, isInSystemModule(dc),
decl->getUnderlyingType()->isBlockPointerType(), OTK_None); Bridgeability::Full, OTK_None);
if (auto objTy = computedPropertyUnderlyingType->getAnyOptionalObjectType()) if (auto objTy = computedPropertyUnderlyingType->getAnyOptionalObjectType())
computedPropertyUnderlyingType = objTy; computedPropertyUnderlyingType = objTy;
@@ -5173,7 +5173,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
// Compute the underlying type. // Compute the underlying type.
auto underlyingType = Impl.importType( auto underlyingType = Impl.importType(
decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc), decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
/*isFullyBridgeable*/ false); Bridgeability::None);
if (!underlyingType) if (!underlyingType)
return nullptr; return nullptr;
@@ -5492,7 +5492,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
Type swiftPropertyType = Impl.importType( Type swiftPropertyType = Impl.importType(
propertyType, ImportTypeKind::Property, propertyType, ImportTypeKind::Property,
Impl.shouldAllowNSUIntegerAsInt(isFromSystemModule, getter), Impl.shouldAllowNSUIntegerAsInt(isFromSystemModule, getter),
/*isFullyBridgeable*/ true, OTK_ImplicitlyUnwrappedOptional); Bridgeability::Full, OTK_ImplicitlyUnwrappedOptional);
if (!swiftPropertyType) if (!swiftPropertyType)
return nullptr; return nullptr;
@@ -6406,7 +6406,8 @@ Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
clangBound->stripObjCKindOfTypeAndQuals(Impl.getClangASTContext()); clangBound->stripObjCKindOfTypeAndQuals(Impl.getClangASTContext());
Type superclassType = Type superclassType =
Impl.importType(clang::QualType(unqualifiedClangBound, 0), Impl.importType(clang::QualType(unqualifiedClangBound, 0),
ImportTypeKind::Abstract, false, false); ImportTypeKind::Abstract, false,
Bridgeability::None);
if (!superclassType) { if (!superclassType) {
return None; return None;
} }

View File

@@ -113,7 +113,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
auto clangTy = parsed->getType(); auto clangTy = parsed->getType();
auto literalType = Impl.importType(clangTy, ImportTypeKind::Value, auto literalType = Impl.importType(clangTy, ImportTypeKind::Value,
isInSystemModule(DC), isInSystemModule(DC),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!literalType) if (!literalType)
return nullptr; return nullptr;
@@ -123,7 +123,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
} else { } else {
constantType = Impl.importType(castType, ImportTypeKind::Value, constantType = Impl.importType(castType, ImportTypeKind::Value,
isInSystemModule(DC), isInSystemModule(DC),
/*isFullyBridgeable*/false); Bridgeability::None);
if (!constantType) if (!constantType)
return nullptr; return nullptr;
} }
@@ -300,7 +300,7 @@ static Optional<std::pair<llvm::APSInt, Type>>
auto type = impl.importType(literal->getType(), auto type = impl.importType(literal->getType(),
ImportTypeKind::Value, ImportTypeKind::Value,
isInSystemModule(DC), isInSystemModule(DC),
/*isFullyBridgeable*/false); Bridgeability::None);
return {{ value, type }}; return {{ value, type }};
} }

View File

@@ -176,14 +176,14 @@ namespace {
{ {
ClangImporter::Implementation &Impl; ClangImporter::Implementation &Impl;
bool AllowNSUIntegerAsInt; bool AllowNSUIntegerAsInt;
bool CanFullyBridgeTypes; Bridgeability Bridging;
public: public:
SwiftTypeConverter(ClangImporter::Implementation &impl, SwiftTypeConverter(ClangImporter::Implementation &impl,
bool allowNSUIntegerAsInt, bool allowNSUIntegerAsInt,
bool canFullyBridgeTypes) Bridgeability bridging)
: Impl(impl), AllowNSUIntegerAsInt(allowNSUIntegerAsInt), : Impl(impl), AllowNSUIntegerAsInt(allowNSUIntegerAsInt),
CanFullyBridgeTypes(canFullyBridgeTypes) {} Bridging(bridging) {}
using TypeVisitor::Visit; using TypeVisitor::Visit;
ImportResult Visit(clang::QualType type) { ImportResult Visit(clang::QualType type) {
@@ -356,7 +356,7 @@ namespace {
pointeeType = Impl.importType(pointeeQualType, pointeeType = Impl.importType(pointeeQualType,
ImportTypeKind::Pointee, ImportTypeKind::Pointee,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
/*isFullyBridgeable*/false); Bridgeability::None);
// If the pointed-to type is unrepresentable in Swift, import as // If the pointed-to type is unrepresentable in Swift, import as
// OpaquePointer. // OpaquePointer.
@@ -404,7 +404,7 @@ namespace {
Type pointeeType = Impl.importType(type->getPointeeType(), Type pointeeType = Impl.importType(type->getPointeeType(),
ImportTypeKind::Abstract, ImportTypeKind::Abstract,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
CanFullyBridgeTypes); Bridging);
if (!pointeeType) if (!pointeeType)
return Type(); return Type();
FunctionType *fTy = pointeeType->castTo<FunctionType>(); FunctionType *fTy = pointeeType->castTo<FunctionType>();
@@ -443,7 +443,7 @@ namespace {
Type elementType = Impl.importType(type->getElementType(), Type elementType = Impl.importType(type->getElementType(),
ImportTypeKind::Pointee, ImportTypeKind::Pointee,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
/*isFullyBridgeable*/false); Bridgeability::None);
if (!elementType) if (!elementType)
return Type(); return Type();
@@ -498,7 +498,7 @@ namespace {
auto resultTy = Impl.importType(type->getReturnType(), auto resultTy = Impl.importType(type->getReturnType(),
ImportTypeKind::Result, ImportTypeKind::Result,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
CanFullyBridgeTypes, Bridging,
OTK_Optional); OTK_Optional);
if (!resultTy) if (!resultTy)
return Type(); return Type();
@@ -509,7 +509,7 @@ namespace {
param != paramEnd; ++param) { param != paramEnd; ++param) {
auto swiftParamTy = Impl.importType(*param, ImportTypeKind::Parameter, auto swiftParamTy = Impl.importType(*param, ImportTypeKind::Parameter,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
CanFullyBridgeTypes, Bridging,
OTK_Optional); OTK_Optional);
if (!swiftParamTy) if (!swiftParamTy)
return Type(); return Type();
@@ -534,7 +534,7 @@ namespace {
auto resultTy = Impl.importType(type->getReturnType(), auto resultTy = Impl.importType(type->getReturnType(),
ImportTypeKind::Result, ImportTypeKind::Result,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
CanFullyBridgeTypes, Bridging,
OTK_Optional); OTK_Optional);
if (!resultTy) if (!resultTy)
return Type(); return Type();
@@ -665,12 +665,32 @@ namespace {
} }
// Any other interesting mapped types should be hinted here. // Any other interesting mapped types should be hinted here.
// Otherwise, recurse on the underlying type in order to compute // Otherwise, recurse on the underlying type. We need to recompute
// the hint correctly. // the hint, and if the typedef uses different bridgeability than the
// context then we may also need to bypass the typedef.
} else { } 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, SwiftTypeConverter innerConverter(Impl, AllowNSUIntegerAsInt,
/*can fully bridge*/false); underlyingBridgeability);
auto underlyingResult = innerConverter.Visit(type->desugar()); 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 #ifndef NDEBUG
switch (underlyingResult.Hint) { switch (underlyingResult.Hint) {
case ImportHint::Block: case ImportHint::Block:
@@ -960,7 +980,7 @@ namespace {
Type importedTypeArg = Impl.importType(typeArg, Type importedTypeArg = Impl.importType(typeArg,
ImportTypeKind::BridgedValue, ImportTypeKind::BridgedValue,
AllowNSUIntegerAsInt, AllowNSUIntegerAsInt,
CanFullyBridgeTypes, Bridging,
OTK_None); OTK_None);
if (!importedTypeArg) { if (!importedTypeArg) {
importedTypeArgs.clear(); importedTypeArgs.clear();
@@ -1146,7 +1166,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
ImportTypeKind importKind, ImportTypeKind importKind,
ImportHint hint, ImportHint hint,
bool allowNSUIntegerAsInt, bool allowNSUIntegerAsInt,
bool canFullyBridgeTypes, Bridgeability bridging,
OptionalTypeKind optKind, OptionalTypeKind optKind,
bool resugarNSErrorPointer) { bool resugarNSErrorPointer) {
if (importKind == ImportTypeKind::Abstract) { if (importKind == ImportTypeKind::Abstract) {
@@ -1261,10 +1281,14 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
importedType = outParamTy; importedType = outParamTy;
} }
// Turn block pointer types back into normal function types in any // SwiftTypeConverter turns block pointers into @convention(block) types.
// context where bridging is possible, unless the block has a typedef. // 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 (hint == ImportHint::Block) {
if (!canFullyBridgeTypes) { if (bridging == Bridgeability::None) {
if (auto typedefType = clangType->getAs<clang::TypedefType>()) { if (auto typedefType = clangType->getAs<clang::TypedefType>()) {
// In non-bridged contexts, drop the typealias sugar for blocks. // In non-bridged contexts, drop the typealias sugar for blocks.
// FIXME: This will do the wrong thing if there's any adjustment to do // 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(), Type underlyingTy = impl.importType(typedefType->desugar(),
importKind, importKind,
allowNSUIntegerAsInt, allowNSUIntegerAsInt,
canFullyBridgeTypes, bridging,
OTK_None); OTK_None);
if (Type unwrappedTy = underlyingTy->getAnyOptionalObjectType()) if (Type unwrappedTy = underlyingTy->getAnyOptionalObjectType())
underlyingTy = unwrappedTy; 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>(); auto fTy = importedType->castTo<FunctionType>();
FunctionType::ExtInfo einfo = fTy->getExtInfo(); FunctionType::ExtInfo einfo = fTy->getExtInfo();
if (einfo.getRepresentation() != FunctionTypeRepresentation::Swift) { 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 // Turn BOOL and DarwinBoolean into Bool in contexts that can bridge types
// losslessly. // losslessly.
if ((hint == ImportHint::BOOL || hint == ImportHint::Boolean) && if ((hint == ImportHint::BOOL || hint == ImportHint::Boolean) &&
canFullyBridgeTypes && canBridgeTypes(importKind)) { bridging == Bridgeability::Full && canBridgeTypes(importKind)) {
return impl.SwiftContext.getBoolDecl()->getDeclaredType(); 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 // If we have a bridged Objective-C type and we are allowed to
// bridge, do so. // bridge, do so.
if (hint == ImportHint::ObjCBridged && canBridgeTypes(importKind) && if (hint == ImportHint::ObjCBridged &&
bridging == Bridgeability::Full &&
canBridgeTypes(importKind) &&
importKind != ImportTypeKind::PropertyWithReferenceSemantics) { importKind != ImportTypeKind::PropertyWithReferenceSemantics) {
// id and Any can be bridged without Foundation. There would be // id and Any can be bridged without Foundation. There would be
// bootstrapping issues with the ObjectiveC module otherwise. // bootstrapping issues with the ObjectiveC module otherwise.
@@ -1373,7 +1399,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
Type ClangImporter::Implementation::importType(clang::QualType type, Type ClangImporter::Implementation::importType(clang::QualType type,
ImportTypeKind importKind, ImportTypeKind importKind,
bool allowNSUIntegerAsInt, bool allowNSUIntegerAsInt,
bool canFullyBridgeTypes, Bridgeability bridging,
OptionalTypeKind optionality, OptionalTypeKind optionality,
bool resugarNSErrorPointer) { bool resugarNSErrorPointer) {
if (type.isNull()) if (type.isNull())
@@ -1414,14 +1440,13 @@ Type ClangImporter::Implementation::importType(clang::QualType type,
} }
// Perform abstract conversion, ignoring how the type is actually used. // 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); auto importResult = converter.Visit(type);
// Now fix up the type based on we're concretely using it. // Now fix up the type based on we're concretely using it.
return adjustTypeForConcreteImport(*this, type, importResult.AbstractType, return adjustTypeForConcreteImport(*this, type, importResult.AbstractType,
importKind, importResult.Hint, importKind, importResult.Hint,
allowNSUIntegerAsInt, allowNSUIntegerAsInt, bridging,
canFullyBridgeTypes,
optionality, optionality,
resugarNSErrorPointer); resugarNSErrorPointer);
} }
@@ -1493,7 +1518,7 @@ Type ClangImporter::Implementation::importPropertyType(
OptionalTypeKind optionality = OTK_ImplicitlyUnwrappedOptional; OptionalTypeKind optionality = OTK_ImplicitlyUnwrappedOptional;
return importType(decl->getType(), importKind, return importType(decl->getType(), importKind,
shouldAllowNSUIntegerAsInt(isFromSystemModule, decl), shouldAllowNSUIntegerAsInt(isFromSystemModule, decl),
/*isFullyBridgeable*/ true, optionality); Bridgeability::Full, optionality);
} }
/// Apply the @noescape attribute /// Apply the @noescape attribute
@@ -1566,7 +1591,7 @@ Type ClangImporter::Implementation::importFunctionReturnType(
(isAuditedResult ? ImportTypeKind::AuditedResult (isAuditedResult ? ImportTypeKind::AuditedResult
: ImportTypeKind::Result), : ImportTypeKind::Result),
allowNSUIntegerAsInt, allowNSUIntegerAsInt,
/*isFullyBridgeable*/ true, OptionalityOfReturn); Bridgeability::Full, OptionalityOfReturn);
} }
Type ClangImporter::Implementation:: Type ClangImporter::Implementation::
@@ -1628,7 +1653,7 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
// Import the parameter type into Swift. // Import the parameter type into Swift.
Type swiftParamTy = Type swiftParamTy =
importType(paramTy, importKind, allowNSUIntegerAsInt, importType(paramTy, importKind, allowNSUIntegerAsInt,
/*isFullyBridgeable*/ true, OptionalityOfParam); Bridgeability::Full, OptionalityOfParam);
if (!swiftParamTy) if (!swiftParamTy)
return nullptr; return nullptr;
@@ -1919,7 +1944,7 @@ Type ClangImporter::Implementation::importMethodType(
clang::QualType resultType = clangDecl->getReturnType(); clang::QualType resultType = clangDecl->getReturnType();
swiftResultTy = importType(resultType, resultKind, swiftResultTy = importType(resultType, resultKind,
allowNSUIntegerAsIntInResult, allowNSUIntegerAsIntInResult,
/*isFullyBridgeable*/true, Bridgeability::Full,
OptionalityOfReturn); OptionalityOfReturn);
// Adjust the result type for a throwing function. // Adjust the result type for a throwing function.
if (swiftResultTy && errorInfo) { if (swiftResultTy && errorInfo) {
@@ -1927,7 +1952,7 @@ Type ClangImporter::Implementation::importMethodType(
// Get the original unbridged result type. // Get the original unbridged result type.
origSwiftResultTy = importType(resultType, resultKind, origSwiftResultTy = importType(resultType, resultKind,
allowNSUIntegerAsIntInResult, allowNSUIntegerAsIntInResult,
/*isFullyBridgeable*/false, Bridgeability::None,
OptionalityOfReturn) OptionalityOfReturn)
->getCanonicalType(); ->getCanonicalType();
@@ -2042,7 +2067,7 @@ Type ClangImporter::Implementation::importMethodType(
// being lazier.) // being lazier.)
swiftParamTy = importType(paramTy, importKind, swiftParamTy = importType(paramTy, importKind,
allowNSUIntegerAsIntInParam, allowNSUIntegerAsIntInParam,
/*isFullyBridgeable*/true, Bridgeability::Full,
optionalityOfParam, optionalityOfParam,
/*resugarNSErrorPointer=*/!paramIsError); /*resugarNSErrorPointer=*/!paramIsError);
} }

View File

@@ -181,6 +181,22 @@ enum class ImportTypeKind {
Enum 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 /// \brief Describes the kind of the C type that can be mapped to a stdlib
/// swift type. /// swift type.
enum class MappedCTypeKind { enum class MappedCTypeKind {
@@ -893,16 +909,17 @@ public:
/// \param allowNSUIntegerAsInt If true, NSUInteger will be imported as Int /// \param allowNSUIntegerAsInt If true, NSUInteger will be imported as Int
/// in certain contexts. If false, it will always be imported as UInt. /// in certain contexts. If false, it will always be imported as UInt.
/// ///
/// \param canFullyBridgeTypes True if we can bridge types losslessly. /// \param bridgeability Whether we can bridge types in this context.
/// This is an additional guarantee on top of the ImportTypeKind /// This may restrict the ability to bridge types even in contexts
/// cases that allow bridging, and applies to the entire type. /// that otherwise allow bridging, such as function results and
/// parameters.
/// ///
/// \returns The imported type, or null if this type could /// \returns The imported type, or null if this type could
/// not be represented in Swift. /// not be represented in Swift.
Type importType(clang::QualType type, Type importType(clang::QualType type,
ImportTypeKind kind, ImportTypeKind kind,
bool allowNSUIntegerAsInt, bool allowNSUIntegerAsInt,
bool canFullyBridgeTypes, Bridgeability bridgeability,
OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional, OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional,
bool resugarNSErrorPointer = true); bool resugarNSErrorPointer = true);

View File

@@ -24,3 +24,10 @@ idLover.takesArray(ofId: &y) // expected-error{{argument type 'Any' does not con
idLover.takesId(x) idLover.takesId(x)
idLover.takesId(y) 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)

View File

@@ -40,9 +40,13 @@ ObjCBoolBlock testObjCBoolFnToBlockTypedef(ObjCBoolFn);
DarwinBooleanBlock testDarwinBooleanFnToBlockTypedef(DarwinBooleanFn); DarwinBooleanBlock testDarwinBooleanFnToBlockTypedef(DarwinBooleanFn);
typedef __typeof(testCBoolFnToBlockTypedef) CBoolFnToBlockType; typedef __typeof(testCBoolFnToBlockTypedef) CBoolFnToBlockType;
typedef __typeof(testObjCBoolFnToBlockTypedef) ObjCCBoolFnToBlockType; typedef __typeof(testObjCBoolFnToBlockTypedef) ObjCBoolFnToBlockType;
typedef __typeof(testDarwinBooleanFnToBlockTypedef) DarwinBooleanFnToBlockType; typedef __typeof(testDarwinBooleanFnToBlockTypedef) DarwinBooleanFnToBlockType;
extern ObjCBoolFnToBlockType *globalObjCBoolFnToBlockFP;
extern ObjCBoolFnToBlockType * __nonnull * __nullable globalObjCBoolFnToBlockFPP;
extern ObjCBoolFnToBlockType ^globalObjCBoolFnToBlockBP;
extern CBoolFn globalCBoolFn; extern CBoolFn globalCBoolFn;
extern ObjCBoolFn globalObjCBoolFn; extern ObjCBoolFn globalObjCBoolFn;
extern DarwinBooleanFn globalDarwinBooleanFn; extern DarwinBooleanFn globalDarwinBooleanFn;

View File

@@ -43,8 +43,12 @@ func testObjCBoolFnToBlockTypedef(_: @escaping ObjCBoolFn) -> ObjCBoolBlock
func testDarwinBooleanFnToBlockTypedef(_: @escaping DarwinBooleanFn) -> DarwinBooleanBlock func testDarwinBooleanFnToBlockTypedef(_: @escaping DarwinBooleanFn) -> DarwinBooleanBlock
typealias CBoolFnToBlockType = (CBoolFn) -> CBoolBlock typealias CBoolFnToBlockType = (CBoolFn) -> CBoolBlock
typealias ObjCCBoolFnToBlockType = (ObjCBoolFn) -> (ObjCBool) -> ObjCBool typealias ObjCBoolFnToBlockType = (ObjCBoolFn) -> ObjCBoolBlock
typealias DarwinBooleanFnToBlockType = (DarwinBooleanFn) -> (DarwinBoolean) -> DarwinBoolean 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 globalCBoolFn: CBoolFn
var globalObjCBoolFn: ObjCBoolFn var globalObjCBoolFn: ObjCBoolFn

View File

@@ -143,7 +143,7 @@
// CHECK-FOUNDATION: func doSomethingElse(with: NSCopying & NSObjectProtocol) // CHECK-FOUNDATION: func doSomethingElse(with: NSCopying & NSObjectProtocol)
// Note: Function type -> "Function". // 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". // Note: Plural: NSArray without type arguments -> "Objects".
// CHECK-FOUNDATION: func remove(_: [Any]) // CHECK-FOUNDATION: func remove(_: [Any])

View File

@@ -1110,3 +1110,6 @@ typedef enum __attribute__((ns_error_domain(NSLaundryErrorDomain))) __attribute_
NSLaundryErrorTooMuchSoap = 1, NSLaundryErrorTooMuchSoap = 1,
NSLaundryErrorCatInWasher = 2 NSLaundryErrorCatInWasher = 2
}; };
typedef void (*event_handler)(__nonnull id);
void install_global_event_handler(__nullable event_handler handler);