// -*- 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 reference counted C++ class can be imported as a reference counted type in Swift:
///  ```c++
///    class SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject)
///    SharedObject : IntrusiveReferenceCounted<SharedObject> {
///    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 singleton C++ class can be imported as a reference type in Swift:
///  ```c++
///    class SWIFT_IMMORTAL_REFERENCE LoggerSingleton {
///    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("retain:immortal")))     \
  __attribute__((swift_attr("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("retain:immortal")))     \
  __attribute__((swift_attr("release:immortal")))    \
  __attribute__((swift_attr("unsafe")))

/// This annotation makes smart pointers to intrusively reference counted
/// objects more ergonomic to use in Swift by:
///
/// * introducing explicit conversions between the smart pointer type and
///   the underlying reference type and
/// * importing C++ APIs that return the smart pointer type or take it as a
///   parameter as returning or taking the underlying reference type.
///
/// Place this annotation on a smart pointer class or struct. The argument
/// to the annotation names an accessor function, which can be a file-scope
/// function or (if prefixed by .) a member function of the smart pointer
/// class. The return type of the accessor function determines the underlying
/// reference type of the smart pointer; it must be a pointer to a class or
/// struct with the SWIFT_SHARED_REFERENCE annotation. Note that
/// SWIFT_SHARED_REFERENCE requires the underlying reference type
/// to provide independent retain and release operations; Swift does not
/// currently support this ergonomic import of smart pointers to objects
/// that can only be managed through a smart pointer class.
///
/// The Swift importer will diagnose a class with this annotation as an
/// error if it cannot determine an underlying reference type. If the class
/// is templated, this applies to instantiations of the template, not to the
/// template pattern. (That is, it is okay to have a templated smart pointer
/// type as long as the concrete instantiations used in your C++ interface
/// all have determinable underlying reference types.)
///
/// The smart pointer type is required to have a constructor that takes
/// either a raw pointer (`T*`) or an lvalue reference (`T&`) to the
/// underlying reference type. If both forms are provided, the
/// pointer-taking constructor is preferred. This constructor is
/// expected to perform a retain of the object. (In the +0 / +1 language
/// of Objective-C reference counting, it would be said to take the
/// object at +0: it does not take responsibility for a retain
/// performed by its caller.) Generally, this kind of constructor matches
/// with object models where the object constructor initializes the
/// reference count to 0.
///
/// The argument of this annotation is required to be the name of an
/// "accessor" method that returns either a raw pointer or an lvalue
/// reference to the object. This method is required to return without
/// changing the reference count.
///
/// Swift will define conversion operations using these functions to
/// convert between the raw pointer and the smart pointer representations.
///
/// By default, smart pointer types are assumed to have a valid null state.
/// Passing a null pointer to the raw-pointer constructor will create a smart
/// pointer in the null state, and calling the raw-pointer accessor method
/// on a smart pointer in the null state will return a null pointer. In case the
/// constructor and the raw-pointer accessor are annotated with _Nonnull, we
/// assume the smart pointer does not have a null state.
///
///  ```c++
///   template <class T>
///   struct SWIFT_REFCOUNTED_PTR(.getPtr) Ptr {
///     Ptr(T* ptr);
///     T *_Nullable getPtr() const { return ptr; }
///   };
///
///   using PtrOfSharedRef = Ptr<SharedRef>;
///  ```
///
/// In Swift, we can convert the smart pointer type to the corresponding native
/// Swift reference:
///  ```swift
///  func f(_ x: PtrOfSharedRef) {
///    let y = x.asReference
///  }
///  ```
///
/// Moreover, this annotation introduces implicit bridging for functions taking
/// or returning smart pointers by value:
///  ```c++
///   PtrOfSharedRef foo(PtrOfSharedRef param);
///  ```
/// Imported with the signature `func foo(_ param: SharedRef) -> SharedRef`
#define SWIFT_REFCOUNTED_PTR(_toRawPointer)                                            \
  __attribute__((swift_attr(                                                           \
      "@_refCountedPtr(ToRawPointer: \"" _CXX_INTEROP_STRINGIFY(_toRawPointer) "\")")))

/// 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 T>
///    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 C++ `class` or `struct` should be imported as a copyable
/// Swift value if all of the specified template arguments are copyable.
#define SWIFT_COPYABLE_IF(...) \
  __attribute__((swift_attr("copyable_if:" _CXX_INTEROP_CONCAT(__VA_ARGS__))))

/// 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)))

/// A type or function annotated with SWIFT_UNSAFE will be imported as an unsafe
/// declaration into Swift. Using these declarations will trigger a warning in
/// strictly memory safe Swift. The 'unsafe' keyword can be used to suppress
/// these warnings.
#define SWIFT_UNSAFE __attribute__((swift_attr("unsafe")))

/// A type or function annotated with SWIFT_SAFE safely encapsulates some
/// unsafe behavior. Such declarations will be considered safe even if they have
/// unsafe constituents.
#define SWIFT_SAFE __attribute__((swift_attr("safe")))

/// Do not generate a safe wrapper overload function even if this function
/// contains annotations that would trigger it otherwise.
#define SWIFT_NO_SAFE_WRAPPER __attribute__((swift_attr("no_safe_wrapper")))

#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_REFCOUNTED_PTR(_toRawPointer)
#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 SWIFT_NONCOPYABLE_WITH_DESTROY(_destroy)
#define SWIFT_COPYABLE_IF(...)
#define SWIFT_NONESCAPABLE
#define SWIFT_ESCAPABLE
#define SWIFT_ESCAPABLE_IF(...)
#define SWIFT_RETURNS_RETAINED
#define SWIFT_RETURNS_UNRETAINED
#define SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT
#define SWIFT_PRIVATE_FILEID(_fileID)
#define SWIFT_UNSAFE
#define SWIFT_SAFE
#define SWIFT_NO_SAFE_WRAPPER

#endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)

#undef _CXX_INTEROP_HAS_ATTRIBUTE

#endif // SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
