diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 7bf39297ee23..6c8ed0bbeb0c 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -4424,12 +4424,29 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) { if (!c.hasDecl()) return SILFunctionTypeRepresentation::CFunctionPointer; - if (auto method = - dyn_cast_or_null(c.getDecl()->getClangDecl())) - return isa(method) || method->isStatic() - ? SILFunctionTypeRepresentation::CFunctionPointer - : SILFunctionTypeRepresentation::CXXMethod; + if (auto clangDecl = c.getDecl()->getClangDecl()) { + if (auto method = dyn_cast(clangDecl)) { + return isa(method) || method->isStatic() + ? SILFunctionTypeRepresentation::CFunctionPointer + : SILFunctionTypeRepresentation::CXXMethod; + } + + if (auto function = dyn_cast(clangDecl)) { + if (auto fnType = function->getType()->getAs()) { + switch (fnType->getCallConv()) { + case clang::CC_Swift: + return SILFunctionTypeRepresentation::Thin; + case clang::CC_C: + return SILFunctionTypeRepresentation::CFunctionPointer; + + default: + // Fall back to heuristics below. + break; + } + } + } + } // For example, if we have a function in a namespace: if (c.getDecl()->isImportAsMember()) diff --git a/test/IRGen/c_calling_conventions.swift b/test/IRGen/c_calling_conventions.swift new file mode 100644 index 000000000000..f33580e86f62 --- /dev/null +++ b/test/IRGen/c_calling_conventions.swift @@ -0,0 +1,26 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t +// RUN: %target-swift-frontend -I%t %t/caller.swift -emit-ir | %FileCheck %s + +//--- c_funcs.h + +__attribute__((swiftcall)) +extern void with_swiftcc(void); + +//--- module.modulemap + +module c_funcs { + header "c_funcs.h" +} + +//--- caller.swift + +import c_funcs + +func test() { + // CHECK: call swiftcc void @with_swiftcc() + with_swiftcc() +} +// CHECK: declare {{.*}}swiftcc void @with_swiftcc() + +test()