diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 5b216847cd321..6a5e7a1f14562 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -2925,8 +2925,11 @@ class AnyFunctionType : public TypeBase { friend ExtInfo; friend class AnyFunctionType; friend class FunctionType; - // We preserve a full clang::Type *, not a clang::FunctionType *, so - // we can keep sugar in case we need to present an error to the user. + // We preserve a full clang::Type *, not a clang::FunctionType * as: + // 1. We need to keep sugar in case we need to present an error to the user. + // 2. The actual type being stored is [ignoring sugar] either a + // clang::PointerType or a clang::BlockPointerType which points to a + // clang::FunctionType. const clang::Type *ClangFunctionType; bool empty() const { return !ClangFunctionType; } diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index 1af858ef82a6e..56b07d0dcd17b 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -118,32 +118,38 @@ const clang::Type *ClangTypeConverter::getFunctionType( ArrayRef params, Type resultTy, AnyFunctionType::Representation repr) { - SmallVector paramsTy; - for (auto p : params) - paramsTy.push_back(p.getPlainType()); - auto resultClangTy = convert(resultTy); if (resultClangTy.isNull()) return nullptr; - SmallVector paramsClangTy; - for (auto p : paramsTy) { - auto pc = convert(p); + SmallVector extParamInfos; + SmallVector paramsClangTy; + bool someParamIsConsumed = false; + for (auto p : params) { + auto pc = convert(p.getPlainType()); if (pc.isNull()) return nullptr; + clang::FunctionProtoType::ExtParameterInfo extParamInfo; + if (p.getParameterFlags().isOwned()) { + someParamIsConsumed = true; + extParamInfo = extParamInfo.withIsConsumed(true); + } + extParamInfos.push_back(extParamInfo); paramsClangTy.push_back(pc); } clang::FunctionProtoType::ExtProtoInfo info(clang::CallingConv::CC_C); + if (someParamIsConsumed) + info.ExtParameterInfos = extParamInfos.begin(); auto fn = ClangASTContext.getFunctionType(resultClangTy, paramsClangTy, info); if (fn.isNull()) return nullptr; switch (repr) { case AnyFunctionType::Representation::CFunctionPointer: - return fn.getTypePtr(); + return ClangASTContext.getPointerType(fn).getTypePtr(); case AnyFunctionType::Representation::Block: - return ClangASTContext.getBlockPointerType(fn).getTypePtrOrNull(); + return ClangASTContext.getBlockPointerType(fn).getTypePtr(); case AnyFunctionType::Representation::Swift: case AnyFunctionType::Representation::Thin: llvm_unreachable("Expected a C-compatible representation."); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1ac3ef765ef3a..01e89ce6247b8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3235,10 +3235,13 @@ Type ProtocolCompositionType::get(const ASTContext &C, void AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { #ifndef NDEBUG - if (!type->isFunctionType()) { - llvm::errs() << "Expected a Clang function type but found\n"; - type->dump(llvm::errs()); - llvm_unreachable(""); + if (!(type->isFunctionPointerType() || type->isBlockPointerType())) { + SmallString<256> buf; + llvm::raw_svector_ostream os(buf); + os << "Expected a Clang function type wrapped in a pointer type or " + << "a block pointer type but found:\n"; + type->dump(os); + llvm_unreachable(os.str().data()); } #endif return; @@ -3250,7 +3253,7 @@ const clang::Type *AnyFunctionType::getClangFunctionType() const { return cast(this)->getClangFunctionType(); case TypeKind::GenericFunction: // Generic functions do not have C types. - return nullptr; + return nullptr; default: llvm_unreachable("Illegal type kind for AnyFunctionType."); } diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 94425388d6516..8e112ab39efce 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -421,7 +421,7 @@ namespace { funcTy->getExtInfo() .withRepresentation( AnyFunctionType::Representation::CFunctionPointer) - .withClangFunctionType(pointeeQualType.getTypePtr())), + .withClangFunctionType(type)), ImportHint::CFunctionPointer }; }