[cxx-interop] Emit C++ inline function thunks that with correct primitive types

This commit is contained in:
Alex Lorenz
2022-03-29 13:32:38 -07:00
parent 68fc606510
commit f7902a6095
11 changed files with 418 additions and 40 deletions

View File

@@ -716,8 +716,7 @@ private:
/// Print the core function declaration for a given function with the given
/// name.
void printFunctionDeclAsCFunctionDecl(FuncDecl *FD, StringRef name,
Type resultTy,
bool printEmptyParamNames = false) {
Type resultTy) {
// The result type may be a partial function type we need to close
// up later.
PrintMultiPartType multiPart(*this);
@@ -737,12 +736,8 @@ private:
Type objTy;
std::tie(objTy, kind) =
getObjectTypeAndOptionality(param, param->getInterfaceType());
std::string paramName =
param->getName().empty() ? "" : param->getName().str().str();
if (printEmptyParamNames && paramName.empty()) {
llvm::raw_string_ostream os(paramName);
os << "_" << index;
}
StringRef paramName =
param->getName().empty() ? "" : param->getName().str();
print(objTy, kind, paramName, IsFunctionParam);
++index;
});
@@ -868,9 +863,9 @@ private:
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
os << "inline ";
printFunctionDeclAsCFunctionDecl(FD,
FD->getName().getBaseIdentifier().get(),
resultTy, /*printEmptyParamNames=*/true);
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.typeMapping);
funcPrinter.printFunctionDeclAsCxxFunctionDecl(
FD, FD->getName().getBaseIdentifier().get(), resultTy);
// FIXME: Support throwing exceptions for Swift errors.
os << " noexcept";
printFunctionClangAttributes(FD, funcTy);
@@ -1998,7 +1993,7 @@ private:
/// visitPart().
public:
void print(Type ty, Optional<OptionalTypeKind> optionalKind,
std::string name = "",
StringRef name = "",
IsFunctionParam_t isFuncParam = IsNotFunctionParam) {
PrettyStackTraceType trace(getASTContext(), "printing", ty);

View File

@@ -24,11 +24,20 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
CLANG_REPR, \
Optional<StringRef>(CLANG_REPR), \
Optional<StringRef>(CLANG_REPR), \
NEEDS_NULLABILITY \
}
#define MAP_C(SWIFT_NAME, OBJC_REPR, C_REPR, NEEDS_NULLABILITY) \
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
OBJC_REPR, Optional<StringRef>(C_REPR), NEEDS_NULLABILITY}
OBJC_REPR, \
Optional<StringRef>(C_REPR), \
Optional<StringRef>(C_REPR), \
NEEDS_NULLABILITY \
}
#define MAP_CXX(SWIFT_NAME, OBJC_REPR, C_REPR, CXX_REPR, NEEDS_NULLABILITY) \
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
OBJC_REPR, Optional<StringRef>(C_REPR), Optional<StringRef>(CXX_REPR), \
NEEDS_NULLABILITY}
MAP(CBool, "bool", false);
@@ -66,8 +75,8 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
MAP(Float32, "float", false);
MAP(Float64, "double", false);
MAP_C(Int, "NSInteger", "ptrdiff_t", false);
MAP_C(UInt, "NSUInteger", "size_t", false);
MAP_CXX(Int, "NSInteger", "ptrdiff_t", "swift::Int", false);
MAP_CXX(UInt, "NSUInteger", "size_t", "swift::UInt", false);
MAP_C(Bool, "BOOL", "bool", false);
MAP(OpaquePointer, "void *", true);
@@ -76,33 +85,33 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
Identifier ID_ObjectiveC = ctx.Id_ObjectiveC;
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("ObjCBool")}] = {
"BOOL", None, false};
"BOOL", None, None, false};
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("Selector")}] = {
"SEL", None, true};
"SEL", None, None, true};
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier(ctx.getSwiftName(
KnownFoundationEntity::NSZone))}] = {
"struct _NSZone *", None, true};
"struct _NSZone *", None, None, true};
mappedTypeNames[{ctx.Id_Darwin, ctx.getIdentifier("DarwinBoolean")}] = {
"Boolean", None, false};
"Boolean", None, None, false};
mappedTypeNames[{ctx.Id_CoreGraphics, ctx.Id_CGFloat}] = {"CGFloat", None,
false};
None, false};
mappedTypeNames[{ctx.Id_CoreFoundation, ctx.Id_CGFloat}] = {"CGFloat", None,
false};
None, false};
// Use typedefs we set up for SIMD vector types.
#define MAP_SIMD_TYPE(BASENAME, _, __) \
StringRef simd2##BASENAME = "swift_" #BASENAME "2"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] = { \
"swift_" #BASENAME "2", Optional<StringRef>("swift_" #BASENAME "2"), \
false}; \
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false}; \
StringRef simd3##BASENAME = "swift_" #BASENAME "3"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] = { \
"swift_" #BASENAME "3", Optional<StringRef>("swift_" #BASENAME "3"), \
false}; \
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false}; \
StringRef simd4##BASENAME = "swift_" #BASENAME "4"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] = { \
"swift_" #BASENAME "4", Optional<StringRef>("swift_" #BASENAME "4"), \
false};
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false};
#include "swift/ClangImporter/SIMDMappedTypes.def"
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
"must add or remove special name mappings if max number of "
@@ -137,3 +146,12 @@ PrimitiveTypeMapping::getKnownCTypeInfo(const TypeDecl *typeDecl) {
}
return None;
}
Optional<PrimitiveTypeMapping::CxxClangTypeInfo>
PrimitiveTypeMapping::getKnownCxxTypeInfo(const TypeDecl *typeDecl) {
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl)) {
if (typeInfo->cxxName)
return CxxClangTypeInfo{*typeInfo->cxxName, typeInfo->canBeNullable};
}
return None;
}

View File

@@ -48,6 +48,15 @@ public:
/// primitive type declaration, or \c None if no such type name exists.
Optional<CClangTypeInfo> getKnownCTypeInfo(const TypeDecl *typeDecl);
struct CxxClangTypeInfo {
StringRef name;
bool canBeNullable;
};
/// Returns the C++ type name and nullability for the given Swift
/// primitive type declaration, or \c None if no such type name exists.
Optional<CxxClangTypeInfo> getKnownCxxTypeInfo(const TypeDecl *typeDecl);
private:
void initialize(ASTContext &ctx);
@@ -56,6 +65,8 @@ private:
StringRef objcName;
// The C name of the Swift type.
Optional<StringRef> cName;
// The C++ name of the Swift type.
Optional<StringRef> cxxName;
bool canBeNullable;
};

View File

@@ -304,6 +304,15 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
emitCxxConditional(
out, [&] { emitMacro("SWIFT_NOEXCEPT", "noexcept"); },
[&] { emitMacro("SWIFT_NOEXCEPT"); });
emitCxxConditional(out, [&] {
out << "#if !defined(SWIFT_CXX_INT_DEFINED)\n";
out << "#define SWIFT_CXX_INT_DEFINED\n";
out << "namespace swift {\n";
out << "using Int = ptrdiff_t;\n";
out << "using UInt = size_t;\n";
out << "}\n";
out << "#endif\n";
});
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
"need to add SIMD typedefs here if max elements is increased");
}

View File

@@ -13,6 +13,7 @@
#include "PrintClangFunction.h"
#include "ClangSyntaxPrinter.h"
#include "DeclAndTypePrinter.h"
#include "OutputLanguageMode.h"
#include "PrimitiveTypeMapping.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ParameterList.h"
@@ -23,6 +24,22 @@
using namespace swift;
namespace {
class ClangFunctionSignatureTypePrinter : private ClangSyntaxPrinter {
public:
ClangFunctionSignatureTypePrinter(raw_ostream &os) : ClangSyntaxPrinter(os) {}
void printIfSimpleType(StringRef name, bool canBeNullable,
Optional<OptionalTypeKind> optionalKind) {
os << name;
if (canBeNullable)
printNullability(optionalKind);
}
void printVoidType() { os << "void"; }
};
// Prints types in the C function signature that corresponds to the
// native Swift function/method.
class CFunctionSignatureTypePrinter
@@ -31,11 +48,22 @@ class CFunctionSignatureTypePrinter
private ClangSyntaxPrinter {
public:
CFunctionSignatureTypePrinter(raw_ostream &os,
PrimitiveTypeMapping &typeMapping)
: ClangSyntaxPrinter(os), typeMapping(typeMapping) {}
PrimitiveTypeMapping &typeMapping,
OutputLanguageMode languageMode)
: ClangSyntaxPrinter(os), typeMapping(typeMapping),
languageMode(languageMode) {}
bool printIfKnownSimpleType(const TypeDecl *typeDecl,
Optional<OptionalTypeKind> optionalKind) {
if (languageMode == OutputLanguageMode::Cxx) {
auto knownTypeInfo = typeMapping.getKnownCxxTypeInfo(typeDecl);
if (!knownTypeInfo)
return false;
os << knownTypeInfo->name;
if (knownTypeInfo->canBeNullable)
printNullability(optionalKind);
return true;
}
auto knownTypeInfo = typeMapping.getKnownCTypeInfo(typeDecl);
if (!knownTypeInfo)
return false;
@@ -83,8 +111,11 @@ public:
private:
PrimitiveTypeMapping &typeMapping;
OutputLanguageMode languageMode;
};
} // end namespace
void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
FuncDecl *FD, StringRef name, Type resultTy) {
// FIXME: Might need a PrintMultiPartType here.
@@ -92,7 +123,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
StringRef name) {
// FIXME: add support for noescape and PrintMultiPartType,
// see DeclAndTypePrinter::print.
CFunctionSignatureTypePrinter typePrinter(os, typeMapping);
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
OutputLanguageMode::ObjC);
typePrinter.visit(ty, optionalKind);
if (!name.empty()) {
@@ -106,7 +138,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
Type objTy;
std::tie(objTy, kind) =
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
CFunctionSignatureTypePrinter typePrinter(os, typeMapping);
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
OutputLanguageMode::ObjC);
typePrinter.visit(objTy, kind);
os << ' ' << name << '(';
@@ -128,3 +161,53 @@ void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
}
os << ')';
}
void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCxxFunctionDecl(
FuncDecl *FD, StringRef name, Type resultTy) {
// FIXME: Might need a PrintMultiPartType here.
auto print = [this](Type ty, Optional<OptionalTypeKind> optionalKind,
StringRef name) {
// FIXME: add support for noescape and PrintMultiPartType,
// see DeclAndTypePrinter::print.
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
OutputLanguageMode::Cxx);
typePrinter.visit(ty, optionalKind);
if (!name.empty()) {
os << ' ';
ClangSyntaxPrinter(os).printIdentifier(name);
}
};
// Print out the return type.
OptionalTypeKind kind;
Type objTy;
std::tie(objTy, kind) =
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
OutputLanguageMode::Cxx);
typePrinter.visit(objTy, kind);
os << ' ' << name << '(';
// Print out the parameter types.
auto params = FD->getParameters();
if (params->size()) {
size_t paramIndex = 1;
llvm::interleaveComma(*params, os, [&](const ParamDecl *param) {
OptionalTypeKind kind;
Type objTy;
std::tie(objTy, kind) = DeclAndTypePrinter::getObjectTypeAndOptionality(
param, param->getInterfaceType());
std::string paramName =
param->getName().empty() ? "" : param->getName().str().str();
if (paramName.empty()) {
llvm::raw_string_ostream os(paramName);
os << "_" << paramIndex;
}
print(objTy, kind, paramName);
++paramIndex;
});
}
os << ')';
}

View File

@@ -36,6 +36,11 @@ public:
void printFunctionDeclAsCFunctionDecl(FuncDecl *FD, StringRef name,
Type resultTy);
/// Print the inline C++ function thunk declaration that corresponds to the
/// given Swift function declaration.
void printFunctionDeclAsCxxFunctionDecl(FuncDecl *FD, StringRef name,
Type resultTy);
private:
raw_ostream &os;
PrimitiveTypeMapping &typeMapping;

View File

@@ -16,22 +16,22 @@
// CHECK: }
// CHECK: inline void alwaysDeprecated(void) noexcept SWIFT_DEPRECATED {
// CHECK: inline void alwaysDeprecated() noexcept SWIFT_DEPRECATED {
@available(*, deprecated)
public func alwaysDeprecated() {}
// CHECK: inline void alwaysDeprecatedTwo(void) noexcept SWIFT_DEPRECATED_MSG("it should not be used")
// CHECK: inline void alwaysDeprecatedTwo() noexcept SWIFT_DEPRECATED_MSG("it should not be used")
@available(*, deprecated, message: "it should not be used")
public func alwaysDeprecatedTwo() {}
// CHECK: inline void alwaysUnavailable(void) noexcept SWIFT_UNAVAILABLE
// CHECK: inline void alwaysUnavailable() noexcept SWIFT_UNAVAILABLE
@available(*, unavailable)
public func alwaysUnavailable() {}
// CHECK: inline void alwaysUnavailableMessage(void) noexcept SWIFT_UNAVAILABLE_MSG("stuff happened")
// CHECK: inline void alwaysUnavailableMessage() noexcept SWIFT_UNAVAILABLE_MSG("stuff happened")
@available(*, unavailable, message: "stuff happened")
public func alwaysUnavailableMessage() {}
// CHECK: inline void singlePlatAvailability(void) noexcept SWIFT_AVAILABILITY(macos,introduced=11)
// CHECK: inline void singlePlatAvailability() noexcept SWIFT_AVAILABILITY(macos,introduced=11)
@available(macOS 11, *)
public func singlePlatAvailability() {}

View File

@@ -45,6 +45,6 @@ public func passTwoIntReturnIntNoArgLabelParamName(_ x2: CInt, _ y2: CInt) -> CI
public func passVoidReturnVoid() { print("passVoidReturnVoid") }
// CHECK: inline void passVoidReturnVoid(void) noexcept {
// CHECK: inline void passVoidReturnVoid() noexcept {
// CHECK: return _impl::$s9Functions014passVoidReturnC0yyF();
// CHECK: }

View File

@@ -0,0 +1,191 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %FileCheck %s < %t/functions.h
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h)
// CHECK: inline float passThrougCFloat(float x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThrougCFloatyS2fF(x);
// CHECK-NEXT: }
// CHECK: inline bool passThroughBool(bool x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions15passThroughBoolyS2bF(x);
// CHECK-NEXT: }
// CHECK: inline bool passThroughCBool(bool x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughCBoolyS2bF(x);
// CHECK-NEXT: }
// CHECK: inline char passThroughCChar(char x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughCCharys4Int8VADF(x);
// CHECK-NEXT: }
// CHECK: inline char16_t passThroughCChar16(char16_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions18passThroughCChar16ys6UInt16VADF(x);
// CHECK-NEXT: }
// CHECK: inline char32_t passThroughCChar32(char32_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions18passThroughCChar32ys7UnicodeO6ScalarVAFF(x);
// CHECK-NEXT: }
// CHECK: inline double passThroughCDouble(double x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions18passThroughCDoubleyS2dF(x);
// CHECK-NEXT: }
// CHECK: inline int passThroughCInt(int x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions15passThroughCIntys5Int32VADF(x);
// CHECK-NEXT: }
// CHECK: inline long long passThroughCLongLong(long long x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions20passThroughCLongLongys5Int64VADF(x);
// CHECK-NEXT: }
// CHECK: inline short passThroughCShort(short x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions17passThroughCShortys5Int16VADF(x);
// CHECK-NEXT: }
// CHECK: inline signed char passThroughCSignedChar(signed char x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions22passThroughCSignedCharys4Int8VADF(x);
// CHECK-NEXT: }
// CHECK: inline unsigned int passThroughCUnsignedInt(unsigned int x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions23passThroughCUnsignedIntys6UInt32VADF(x);
// CHECK-NEXT: }
// CHECK: inline unsigned long long passThroughCUnsignedLongLong(unsigned long long x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions024passThroughCUnsignedLongE0ys6UInt64VADF(x);
// CHECK-NEXT: }
// CHECK: inline unsigned short passThroughCUnsignedShort(unsigned short x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions25passThroughCUnsignedShortys6UInt16VADF(x);
// CHECK-NEXT: }
// CHECK: inline unsigned char passThroughCUnsignedSignedChar(unsigned char x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions30passThroughCUnsignedSignedCharys5UInt8VADF(x);
// CHECK-NEXT: }
// CHECK: inline wchar_t passThroughCWideChar(wchar_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF(x);
// CHECK-NEXT: }
// CHECK: inline double passThroughDouble(double x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions17passThroughDoubleyS2dF(x);
// CHECK-NEXT: }
// CHECK: inline float passThroughFloat(float x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughFloatyS2fF(x);
// CHECK-NEXT: }
// CHECK: inline float passThroughFloat32(float x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions18passThroughFloat32yS2fF(x);
// CHECK-NEXT: }
// CHECK: inline double passThroughFloat64(double x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions18passThroughFloat64yS2dF(x);
// CHECK-NEXT: }
// CHECK: inline swift::Int passThroughInt(swift::Int x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions14passThroughIntyS2iF(x);
// CHECK-NEXT: }
// CHECK: inline int16_t passThroughInt16(int16_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughInt16ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline int32_t passThroughInt32(int32_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughInt32ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline int64_t passThroughInt64(int64_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughInt64ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline int8_t passThroughInt8(int8_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions15passThroughInt8ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline void * _Nonnull passThroughOpaquePointer(void * _Nonnull x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions24passThroughOpaquePointerys0dE0VADF(x);
// CHECK-NEXT: }
// CHECK: inline swift::UInt passThroughUInt(swift::UInt x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions15passThroughUIntyS2uF(x);
// CHECK-NEXT: }
// CHECK: inline uint16_t passThroughUInt16(uint16_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions17passThroughUInt16ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline uint32_t passThroughUInt32(uint32_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions17passThroughUInt32ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline uint64_t passThroughUInt64(uint64_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions17passThroughUInt64ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline uint8_t passThroughUInt8(uint8_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions16passThroughUInt8ys0D0VADF(x);
// CHECK-NEXT: }
// CHECK: inline void * _Nonnull passThroughUnsafeMutableRawPointer(void * _Nonnull x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions34passThroughUnsafeMutableRawPointeryS2vF(x);
// CHECK-NEXT: }
// CHECK: inline void const * _Nonnull passThroughUnsafeRawPointer(void const * _Nonnull x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions27passThroughUnsafeRawPointeryS2VF(x);
// CHECK-NEXT: }
// CHECK: inline void * _Nullable roundTwoPassThroughUnsafeMutableRawPointer(void * _Nullable x) noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: return _impl::$s9Functions42roundTwoPassThroughUnsafeMutableRawPointerySvSgACF(x);
// CHECK-NEXT: }
public func passThroughCBool(_ x: CBool) -> CBool { return x }
public func passThroughCChar(_ x: CChar) -> CChar { return x }
public func passThroughCWideChar(_ x: CWideChar) -> CWideChar { return x }
public func passThroughCChar16(_ x: CChar16) -> CChar16 { return x }
public func passThroughCChar32(_ x: CChar32) -> CChar32 { return x }
// Don't test CLong as it's platform specific. See long-lp64 test instead.
public func passThroughCSignedChar(_ x: CSignedChar) -> CSignedChar { return x }
public func passThroughCShort(_ x: CShort) -> CShort { return x }
public func passThroughCInt(_ x: CInt) -> CInt { return x }
public func passThroughCLongLong(_ x: CLongLong) -> CLongLong { return x }
// Don't test CUnsignedLong as it's platform specific. See long-lp64 test instead.
public func passThroughCUnsignedSignedChar(_ x: CUnsignedChar) -> CUnsignedChar { return x }
public func passThroughCUnsignedShort(_ x: CUnsignedShort) -> CUnsignedShort { return x }
public func passThroughCUnsignedInt(_ x: CUnsignedInt) -> CUnsignedInt { return x }
public func passThroughCUnsignedLongLong(_ x: CUnsignedLongLong) -> CUnsignedLongLong { return x }
public func passThrougCFloat(_ x: CFloat) -> CFloat { return x }
public func passThroughCDouble(_ x: CDouble) -> CDouble { return x }
public func passThroughInt8(_ x: Int8) -> Int8 { return x }
public func passThroughInt16(_ x: Int16) -> Int16 { return x }
public func passThroughInt32(_ x: Int32) -> Int32 { return x }
public func passThroughInt64(_ x: Int64) -> Int64 { return x }
public func passThroughUInt8(_ x: UInt8) -> UInt8 { return x }
public func passThroughUInt16(_ x: UInt16) -> UInt16 { return x }
public func passThroughUInt32(_ x: UInt32) -> UInt32 { return x }
public func passThroughUInt64(_ x: UInt64) -> UInt64 { return x }
public func passThroughFloat(_ x: Float) -> Float { return x }
public func passThroughDouble(_ x: Double) -> Double { return x }
public func passThroughFloat32(_ x: Float32) -> Float32 { return x }
public func passThroughFloat64(_ x: Float64) -> Float64 { return x }
public func passThroughInt(_ x: Int) -> Int { return x }
public func passThroughUInt(_ x: UInt) -> UInt { return x }
public func passThroughBool(_ x: Bool) -> Bool { return x }
public func passThroughOpaquePointer(_ x: OpaquePointer) -> OpaquePointer { return x }
public func passThroughUnsafeRawPointer(_ x: UnsafeRawPointer) -> UnsafeRawPointer { return x }
public func passThroughUnsafeMutableRawPointer(_ x: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { return x }
public func roundTwoPassThroughUnsafeMutableRawPointer(_ x: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? { return x }

View File

@@ -0,0 +1,66 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/swift-primitive-functions-cxx-bridging.swift -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-functions-execution.o
// RUN: %target-interop-build-swift %S/swift-primitive-functions-cxx-bridging.swift -o %t/swift-functions-execution -Xlinker %t/swift-functions-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain
// RUN: %target-codesign %t/swift-functions-execution
// RUN: %target-run %t/swift-functions-execution
// REQUIRES: executable_test
#include <cassert>
#include "functions.h"
#define VERIFY_PASSTHROUGH_VALUE(function, value) assert(function(value) == (value));
int main() {
using namespace Functions;
VERIFY_PASSTHROUGH_VALUE(passThroughCBool, true);
VERIFY_PASSTHROUGH_VALUE(passThroughCChar, 'a');
VERIFY_PASSTHROUGH_VALUE(passThroughCWideChar, 'a');
VERIFY_PASSTHROUGH_VALUE(passThroughCChar16, 0xFE1);
VERIFY_PASSTHROUGH_VALUE(passThroughCChar32, 0x100FE);
VERIFY_PASSTHROUGH_VALUE(passThroughCSignedChar, -1);
VERIFY_PASSTHROUGH_VALUE(passThroughCShort, -512);
VERIFY_PASSTHROUGH_VALUE(passThroughCInt, -999999);
VERIFY_PASSTHROUGH_VALUE(passThroughCLongLong, -999998);
VERIFY_PASSTHROUGH_VALUE(passThroughCUnsignedSignedChar, 255);
VERIFY_PASSTHROUGH_VALUE(passThroughCUnsignedShort, 0xFFFF);
VERIFY_PASSTHROUGH_VALUE(passThroughCUnsignedInt, 0xFFFFFFFF);
VERIFY_PASSTHROUGH_VALUE(passThroughCUnsignedLongLong, 0xFFFFFFFF);
VERIFY_PASSTHROUGH_VALUE(passThrougCFloat, 1.0f);
VERIFY_PASSTHROUGH_VALUE(passThroughCDouble, 42.125f);
VERIFY_PASSTHROUGH_VALUE(passThroughInt8, -1);
VERIFY_PASSTHROUGH_VALUE(passThroughInt16, -512);
VERIFY_PASSTHROUGH_VALUE(passThroughInt32, -999999);
VERIFY_PASSTHROUGH_VALUE(passThroughInt64, -999999999999);
VERIFY_PASSTHROUGH_VALUE(passThroughUInt8, 255);
VERIFY_PASSTHROUGH_VALUE(passThroughUInt16, 0xffff);
VERIFY_PASSTHROUGH_VALUE(passThroughUInt32, 0xffffffff);
VERIFY_PASSTHROUGH_VALUE(passThroughUInt64, 0xffffffffffffffff);
VERIFY_PASSTHROUGH_VALUE(passThroughFloat, 1.0f);
VERIFY_PASSTHROUGH_VALUE(passThroughDouble, 42.125f);
VERIFY_PASSTHROUGH_VALUE(passThroughFloat32, 1.0f);
VERIFY_PASSTHROUGH_VALUE(passThroughFloat64, 42.125f);
VERIFY_PASSTHROUGH_VALUE(passThroughInt, -999997);
VERIFY_PASSTHROUGH_VALUE(passThroughUInt, 0xffffffff);
VERIFY_PASSTHROUGH_VALUE(passThroughBool, true);
VERIFY_PASSTHROUGH_VALUE(passThroughBool, false);
int x = 0;
VERIFY_PASSTHROUGH_VALUE(passThroughOpaquePointer, &x);
VERIFY_PASSTHROUGH_VALUE(passThroughUnsafeRawPointer, &x);
VERIFY_PASSTHROUGH_VALUE(passThroughUnsafeMutableRawPointer, &x);
VERIFY_PASSTHROUGH_VALUE(roundTwoPassThroughUnsafeMutableRawPointer, nullptr);
}

View File

@@ -583,13 +583,13 @@ extraCheckWarningFlags = (
# Don't warn about poison system directories in the Linux system paths.
'-Wno-poison-system-directories '
# For -fmodules-cache-path, when modules are off.
'-Wno-unused-command-line-argument ')
'-Wno-unused-command-line-argument '
# Don't warn about nullability specifiers in C/C++ code.
'-Wno-nullability-extension ')
# Verifies that a C++ file can be compiled without warnings except for some exceptions.
config.substitutions.insert(0, ('%check-c-header-in-clang',
'%clang -fsyntax-only -x c-header ' + extraCheckWarningFlags +
# Don't warn about nullability specifiers in C code.
'-Wno-nullability-extension '
# Use standard header/framework search paths.
'-F %%clang-importer-sdk-path/frameworks '
'-I %%clang-include-dir '