// -*- C -*- //===------------------ bridging - C and Swift Interop ----------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file provides common utilities and annotations that are useful for C++ // codebases that interoperate with Swift. // //===----------------------------------------------------------------------===// #ifndef SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H #define SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H #ifdef __has_attribute #define _CXX_INTEROP_HAS_ATTRIBUTE(x) __has_attribute(x) #else #define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0 #endif #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) /// Specifies that a C++ `class` or `struct` owns and controls the lifetime of all /// of the objects it references. Such type should not reference any objects whose /// lifetime is controlled externally. This annotation allows Swift to import methods /// that return a `class` or `struct` type that is annotated with this macro. #define SWIFT_SELF_CONTAINED __attribute__((swift_attr("import_owned"))) /// Specifies that a method returns a value that is presumed to contain /// objects whose lifetime is not dependent on `this` or other parameters passed /// to the method. #define SWIFT_RETURNS_INDEPENDENT_VALUE __attribute__((swift_attr("import_unsafe"))) #define _CXX_INTEROP_STRINGIFY(_x) #_x #define _CXX_INTEROP_CONCAT_(a,b,c,d,e,f,g,i,j,k,l,m,n,o,p,...) \ #a "," #b "," #c "," #d "," #e "," #f "," #g "," #i "," #j "," #k "," \ #l "," #m "," #n "," #o "," #p #define _CXX_INTEROP_CONCAT(...) \ _CXX_INTEROP_CONCAT_(__VA_ARGS__,,,,,,,,,,,,,,,,,) /// Specifies that a `class` or `struct` is reference-counted using /// the given `retain` and `release` functions. This annotation lets Swift import /// such a type as reference counted type in Swift, taking advantage of Swift's /// automatic reference counting. /// /// This example shows how to use this macro to let Swift know that /// a non-copyable reference counted C++ class can be imported as a reference counted type in Swift: /// ```c++ /// class SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject) /// SharedObject : NonCopyable, IntrusiveReferenceCounted { /// public: /// static SharedObject* create(); /// void doSomething(); /// }; /// /// void retainSharedObject(SharedObject *); /// void releaseSharedObject(SharedObject *); /// ``` /// /// Then, the Swift programmer would be able to use it in the following manner: /// /// ```swift /// let object = SharedObject.create() /// object.doSomething() /// // The Swift compiler will release object here. /// ``` #define SWIFT_SHARED_REFERENCE(_retain, _release) \ __attribute__((swift_attr("import_reference"))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:_retain)))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:_release)))) /// Specifies that a `class` or `struct` is a reference type whose lifetime /// is presumed to be immortal, i.e. the reference to such object is presumed to /// always be valid. This annotation lets Swift import such a type as a reference /// type in Swift. //// /// This example shows how to use this macro to let Swift know that /// a non-copyable singleton C++ class can be imported as a reference type in Swift: /// ```c++ /// class SWIFT_IMMORTAL_REFERENCE /// LoggerSingleton : NonCopyable { /// public: /// static LoggerSingleton &getInstance(); /// void log(int x); /// }; /// ``` /// /// Then, the Swift programmer would be able to use it in the following manner: /// /// ```swift /// let logger = LoggerSingleton.getInstance() /// logger.log(123) /// ``` #define SWIFT_IMMORTAL_REFERENCE \ __attribute__((swift_attr("import_reference"))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) /// Specifies that a `class` or `struct` is a reference type whose lifetime /// is not managed automatically. The programmer must validate that any reference /// to such object is valid themselves. This annotation lets Swift import such a type as a reference type in Swift. #define SWIFT_UNSAFE_REFERENCE \ __attribute__((swift_attr("import_reference"))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) \ __attribute__((swift_attr("unsafe"))) /// Specifies a name that will be used in Swift for this declaration instead of its original name. #define SWIFT_NAME(_name) __attribute__((swift_name(#_name))) /// Specifies that a specific `class` or `struct` conforms to a /// a specific Swift protocol. /// /// This example shows how to use this macro to conform a class template to a Swift protocol: /// ``` /// template /// class SWIFT_CONFORMS_TO_PROTOCOL(SwiftModule.ProtocolName) /// CustomClass {}; /// ``` #define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(conforms_to:_moduleName_protocolName)))) /// Specifies that a specific C++ method should be imported as a computed /// property. If this macro is specified on a getter, a getter will be /// synthesized. If this macro is specified on a setter, both a getter and /// setter will be synthesized. /// /// For example: /// ``` /// int getX() SWIFT_COMPUTED_PROPERTY; /// ``` /// Will be imported as `var x: CInt {...}`. #define SWIFT_COMPUTED_PROPERTY \ __attribute__((swift_attr("import_computed_property"))) /// Specifies that a specific **constant** C++ member function should be imported as /// `mutating` Swift method. This annotation should be added to constant C++ member functions /// that mutate `mutable` fields in a C++ object, to let Swift know that this function is still mutating /// and thus that it should become a `mutating` method in Swift. #define SWIFT_MUTATING \ __attribute__((swift_attr("mutating"))) /// Specifies that a specific class or struct should be imported as type marked /// as `@unchecked Sendable` type in swift. If this annotation is used, the type is therefore allowed to /// use safely across async contexts. /// /// For example /// ``` /// class SWIFT_UNCHECKED_SENDABLE CustomUserType /// { ... } /// ``` /// Will be imported as `struct CustomUserType: @unchecked Sendable` #define SWIFT_UNCHECKED_SENDABLE \ __attribute__((swift_attr("@Sendable"))) /// Specifies that a `class` or `struct` should be imported as a non-copyable /// Swift value type. #define SWIFT_NONCOPYABLE \ __attribute__((swift_attr("~Copyable"))) /// Specifies that a `class` or `struct` should be imported as a non-copyable /// Swift value type that calls the given `_destroy` function when a value is no /// longer used. /// /// This example shows how to use this macro to let Swift know that /// a given C struct should have its members freed when it goes out of scope: /// ```c /// typedef struct SWIFT_NONCOPYABLE_WITH_DESTROY(mytypeFreeMembers) MyType { /// void *storage /// } MyType; /// /// void mytypeFreeMembers(MyType toBeDestroyed); /// MyType mytypeCreate(void); /// ``` /// /// Usage in Swift: /// ```swift /// let mt = mytypeCreate() /// let mt2 = mt // consumes mt /// // once mt2 is unused, Swift will call mytypeFreeMembers(mt2) /// ``` #define SWIFT_NONCOPYABLE_WITH_DESTROY(_destroy) \ __attribute__((swift_attr("~Copyable"))) \ __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(destroy:_destroy)))) /// Specifies that a specific class or struct should be imported /// as a non-escapable Swift value type. #define SWIFT_NONESCAPABLE \ __attribute__((swift_attr("~Escapable"))) /// Specifies that a specific class or struct should be imported /// as an escapable Swift value. While this matches the default behavior, /// in safe mode interop mode it ensures that the type is not marked as /// unsafe. #define SWIFT_ESCAPABLE \ __attribute__((swift_attr("Escapable"))) /// Specifies that a C++ `class` or `struct` should be imported as a escapable /// Swift value if all of the specified template arguments are escapable. #define SWIFT_ESCAPABLE_IF(...) \ __attribute__((swift_attr("escapable_if:" _CXX_INTEROP_CONCAT(__VA_ARGS__)))) /// Specifies that the return value is passed as owned for functions and /// methods returning types annotated as `SWIFT_SHARED_REFERENCE` #define SWIFT_RETURNS_RETAINED __attribute__((swift_attr("returns_retained"))) /// Specifies that the return value is passed as unowned for functions and /// methods returning types annotated as `SWIFT_SHARED_REFERENCE` #define SWIFT_RETURNS_UNRETAINED \ __attribute__((swift_attr("returns_unretained"))) /// Applied to a foreign reference type annotated with /// SWIFT_SHARED_REFERENCE. Indicates that APIs returning this type are /// assumed to return an unowned (+0) value by default, unless explicitly annotated /// with SWIFT_RETURNS_RETAINED. /// /// For example: /// ```c++ /// struct SWIFT_SHARED_REFERENCE(retainBar, releaseBar) /// SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT /// Bar { ... }; /// ``` /// /// In Swift, APIs returning `Bar*` will be assumed to return an unowned /// value. #define SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT \ __attribute__((swift_attr("returned_as_unretained_by_default"))) /// Specifies that the non-public members of a C++ class, struct, or union can /// be accessed from extensions of that type, in the given file ID. /// /// In other words, Swift's access controls will behave as if the non-public /// members of the annotated C++ class were privated declared in the specified /// Swift source file, rather than in a C++ header file/Clang module. /// /// For example, we can annotate a C++ class definition like this: /// /// ```c++ /// class SWIFT_PRIVATE_FILEID("MySwiftModule/MySwiftFile.swift") /// MyCxxClass { /// private: /// void privateMethod(); /// int privateStorage; /// }; /// ``` /// /// Then, Swift extensions of `MyCxxClass` in `MySwiftModule/MySwiftFile.swift` /// are allowed to access `privateMethod()` and `privateStorage`: /// /// ```swift /// //-- MySwiftModule/SwiftFile.swift /// extension MyCxxClass { /// func ext() { /// privateMethod() /// print("\(privateStorage)") /// } /// } /// ``` /// /// Non-public access is still forbidden outside of extensions and outside of /// the designated file ID. #define SWIFT_PRIVATE_FILEID(_fileID) \ __attribute__((swift_attr("private_fileid:" _fileID))) #else // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) // Empty defines for compilers that don't support `attribute(swift_attr)`. #define SWIFT_SELF_CONTAINED #define SWIFT_RETURNS_INDEPENDENT_VALUE #define SWIFT_SHARED_REFERENCE(_retain, _release) #define SWIFT_IMMORTAL_REFERENCE #define SWIFT_UNSAFE_REFERENCE #define SWIFT_NAME(_name) #define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) #define SWIFT_COMPUTED_PROPERTY #define SWIFT_MUTATING #define SWIFT_UNCHECKED_SENDABLE #define SWIFT_NONCOPYABLE #define SWIDT_NONCOPYABLE_WITH_DESTROY(_destroy) #define SWIFT_NONESCAPABLE #define SWIFT_ESCAPABLE #define SWIFT_ESCAPABLE_IF(...) #define SWIFT_RETURNS_RETAINED #define SWIFT_RETURNS_UNRETAINED #define SWIFT_PRIVATE_FILEID(_fileID) #endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) #undef _CXX_INTEROP_HAS_ATTRIBUTE #endif // SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H