Files
swift-mirror/lib/PrintAsClang/PrintClangFunction.h
Gabor Horvath 0e03d342fe [cxx-interop] Support ObjC protocols in C++ interop
This patch introduces handling of ObjC protocols similar to how ObjC
classes work. Since this only works in ObjC++, all declarations
containing ObjC protocols will be protected by the __OBJC__ macro.

This patch results in some `_bridgeObjC` methods being exposed, we might
end up hiding those in the future, but there is no harm having them in
the interop header for the interim period.

rdar://136757913
2024-10-16 18:51:35 +01:00

205 lines
7.9 KiB
C++

//===--- PrintClangFunction.h - Printer for C/C++ functions -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_PRINTASCLANG_PRINTCLANGFUNCTION_H
#define SWIFT_PRINTASCLANG_PRINTCLANGFUNCTION_H
#include "OutputLanguageMode.h"
#include "swift/AST/Type.h"
#include "swift/Basic/LLVM.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/IRGen/GenericRequirement.h"
#include "swift/IRGen/IRABIDetailsProvider.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
namespace swift {
class AbstractFunctionDecl;
class AccessorDecl;
class AnyFunctionType;
class FuncDecl;
class GenericTypeParamType;
class ModuleDecl;
class NominalTypeDecl;
class LoweredFunctionSignature;
class ParamDecl;
class ParameterList;
class PrimitiveTypeMapping;
class SwiftToClangInteropContext;
class DeclAndTypePrinter;
struct ClangRepresentation {
enum Kind { representable, objcxxonly, unsupported };
ClangRepresentation(Kind kind) : kind(kind) {}
/// Returns true if the given Swift node is unsupported in Clang in any
/// language mode.
bool isUnsupported() const { return kind == unsupported; }
/// Returns true if the given Swift node is only supported in
/// Objective C++ mode.
bool isObjCxxOnly() const { return kind == objcxxonly; }
const ClangRepresentation &merge(ClangRepresentation other) {
if (other.kind == unsupported)
kind = unsupported;
else if (kind == representable)
kind = other.kind;
return *this;
}
private:
Kind kind;
};
/// Responsible for printing a Swift function decl or type in C or C++ mode, to
/// be included in a Swift module's generated clang header.
class DeclAndTypeClangFunctionPrinter {
public:
DeclAndTypeClangFunctionPrinter(raw_ostream &os, raw_ostream &cPrologueOS,
PrimitiveTypeMapping &typeMapping,
SwiftToClangInteropContext &interopContext,
DeclAndTypePrinter &declPrinter)
: os(os), cPrologueOS(cPrologueOS), typeMapping(typeMapping),
interopContext(interopContext), declPrinter(declPrinter) {}
/// What kind of function signature should be emitted for the given Swift
/// function.
enum class FunctionSignatureKind {
/// Emit a signature for the C function prototype.
CFunctionProto,
/// Emit a signature for the inline C++ function thunk.
CxxInlineThunk
};
/// Optional modifiers that can be applied to function signature.
struct FunctionSignatureModifiers {
/// Additional qualifier to add before the function's name.
const NominalTypeDecl *qualifierContext = nullptr;
bool isStatic = false;
bool isInline = false;
bool isConst = false;
bool isNoexcept = false;
bool hasSymbolUSR = true;
/// Specific declaration that should be used to emit the symbol's
/// USR instead of the original function declaration.
const ValueDecl *symbolUSROverride = nullptr;
FunctionSignatureModifiers() {}
};
/// Print the C function declaration or the C++ function thunk that
/// corresponds to the given function declaration.
///
/// \return value describing in which Clang language mode the function is
/// supported, if any.
ClangRepresentation printFunctionSignature(
const AbstractFunctionDecl *FD, const LoweredFunctionSignature &signature,
StringRef name, Type resultTy, FunctionSignatureKind kind,
FunctionSignatureModifiers modifiers = {});
/// Print the body of the inline C++ function thunk that calls the underlying
/// Swift function.
void printCxxThunkBody(
const AbstractFunctionDecl *FD, const LoweredFunctionSignature &signature,
StringRef swiftSymbolName, const NominalTypeDecl *typeDeclContext,
const ModuleDecl *moduleContext, Type resultTy,
const ParameterList *params, bool hasThrows = false,
const AnyFunctionType *funcType = nullptr, bool isStaticMethod = false,
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo =
std::nullopt);
/// Print the Swift method as C++ method declaration/definition, including
/// constructors.
void printCxxMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isStatic, bool isDefinition,
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
/// Print the C++ getter/setter method signature.
void printCxxPropertyAccessorMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isStatic, bool isDefinition,
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
/// Print the C++ subscript method.
void printCxxSubscriptAccessorMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isDefinition,
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
/// Print Swift type as C/C++ type, as the return type of a C/C++ function.
ClangRepresentation printClangFunctionReturnType(
raw_ostream &stream, Type ty, OptionalTypeKind optKind,
ModuleDecl *moduleContext, OutputLanguageMode outputLang);
static void printGenericReturnSequence(
raw_ostream &os, const GenericTypeParamType *gtpt,
llvm::function_ref<void(StringRef)> invocationPrinter,
std::optional<StringRef> initializeWithTakeFromValue = std::nullopt);
using PrinterTy =
llvm::function_ref<void(llvm::MapVector<Type, std::string> &)>;
/// Print generated C++ helper function
void printCustomCxxFunction(const SmallVector<Type> &neededTypes,
bool NeedsReturnTypes,
PrinterTy retTypeAndNamePrinter,
PrinterTy paramPrinter, bool isConstFunc,
PrinterTy bodyPrinter, ValueDecl *valueDecl,
ModuleDecl *emittedModule,
raw_ostream &outOfLineOS);
static ClangRepresentation
getTypeRepresentation(PrimitiveTypeMapping &typeMapping,
SwiftToClangInteropContext &interopContext,
DeclAndTypePrinter &declPrinter,
const ModuleDecl *emittedModule, Type ty);
/// Prints the name of the type including generic arguments.
void printTypeName(Type ty, const ModuleDecl *moduleContext);
private:
void printCxxToCFunctionParameterUse(Type type, StringRef name,
const ModuleDecl *moduleContext,
bool isInOut, bool isIndirect,
std::string directTypeEncoding,
bool isSelf);
// Print out the full type specifier that refers to the
// _impl::_impl_<typename> C++ class for the given Swift type.
void printTypeImplTypeSpecifier(Type type, const ModuleDecl *moduleContext);
bool hasKnownOptionalNullableCxxMapping(Type type);
raw_ostream &os;
raw_ostream &cPrologueOS;
PrimitiveTypeMapping &typeMapping;
SwiftToClangInteropContext &interopContext;
DeclAndTypePrinter &declPrinter;
};
} // end namespace swift
#endif