Skip to content

[interop][SwiftToCxx] print availability attributes for Swift decls i… #63946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 132 additions & 112 deletions lib/PrintAsClang/DeclAndTypePrinter.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions lib/PrintAsClang/DeclAndTypePrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class DeclAndTypePrinter {
void print(const Decl *D);
void print(Type ty);

void printAvailability(raw_ostream &os, const Decl *D);

/// Is \p ED empty of members and protocol conformances to include?
bool isEmptyExtensionDecl(const ExtensionDecl *ED);

Expand Down
8 changes: 5 additions & 3 deletions lib/PrintAsClang/ModuleContentsWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,14 @@ class ModuleWriter {
return;
auto it = seenClangTypes.insert(clangType.getTypePtr());
if (it.second)
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M);
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M,
printer);
}

void forwardDeclareCxxValueTypeIfNeeded(const NominalTypeDecl *NTD) {
forwardDeclare(NTD,
[&]() { ClangValueTypePrinter::forwardDeclType(os, NTD); });
forwardDeclare(NTD, [&]() {
ClangValueTypePrinter::forwardDeclType(os, NTD, printer);
});
}

void forwardDeclareType(const TypeDecl *TD) {
Expand Down
15 changes: 11 additions & 4 deletions lib/PrintAsClang/PrintClangClassType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@

#include "PrintClangClassType.h"
#include "ClangSyntaxPrinter.h"
#include "DeclAndTypePrinter.h"
#include "PrintClangValueType.h"
#include "swift/AST/Decl.h"
#include "swift/IRGen/Linking.h"

using namespace swift;

void ClangClassTypePrinter::printClassTypeDecl(
const ClassDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter) {
const ClassDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter,
DeclAndTypePrinter &declAndTypePrinter) {
auto printCxxImplClassName = ClangValueTypePrinter::printCxxImplClassName;

ClangSyntaxPrinter printer(os);
Expand All @@ -31,7 +33,9 @@ void ClangClassTypePrinter::printClassTypeDecl(
// Print out a forward declaration of the "hidden" _impl class.
printer.printNamespace(cxx_synthesis::getCxxImplNamespaceName(),
[&](raw_ostream &os) {
os << "class ";
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
os << ' ';
printCxxImplClassName(os, typeDecl);
os << ";\n";
// Print out special functions, like functions that
Expand All @@ -57,6 +61,7 @@ void ClangClassTypePrinter::printClassTypeDecl(
}

os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
os << ' ';
printer.printBaseName(typeDecl);
Expand All @@ -83,7 +88,9 @@ void ClangClassTypePrinter::printClassTypeDecl(
// Print out the "hidden" _impl class.
printer.printNamespace(
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
os << "class ";
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
os << ' ';
printCxxImplClassName(os, typeDecl);
os << " {\n";
os << "public:\n";
Expand All @@ -98,7 +105,7 @@ void ClangClassTypePrinter::printClassTypeDecl(

ClangValueTypePrinter::printTypeGenericTraits(
os, typeDecl, typeMetadataFuncName, /*genericRequirements=*/{},
typeDecl->getModuleContext());
typeDecl->getModuleContext(), declAndTypePrinter);
}

void ClangClassTypePrinter::printClassTypeReturnScaffold(
Expand Down
4 changes: 3 additions & 1 deletion lib/PrintAsClang/PrintClangClassType.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace swift {

class ClassDecl;
class ModuleDecl;
class DeclAndTypePrinter;

/// Responsible for printing a Swift class decl or in C or C++ mode, to
/// be included in a Swift module's generated clang header.
Expand All @@ -30,7 +31,8 @@ class ClangClassTypePrinter {

/// Print the C++ class definition that corresponds to the given Swift class.
void printClassTypeDecl(const ClassDecl *typeDecl,
llvm::function_ref<void(void)> bodyPrinter);
llvm::function_ref<void(void)> bodyPrinter,
DeclAndTypePrinter &declAndTypePrinter);

static void
printClassTypeReturnScaffold(raw_ostream &os, const ClassDecl *type,
Expand Down
6 changes: 6 additions & 0 deletions lib/PrintAsClang/PrintClangFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,7 @@ static StringRef getConstructorName(const AbstractFunctionDecl *FD) {
}

void DeclAndTypeClangFunctionPrinter::printCxxMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isStatic, bool isDefinition,
Expand All @@ -1401,6 +1402,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
resultTy, FunctionSignatureKind::CxxInlineThunk, modifiers);
assert(!result.isUnsupported() && "C signature should be unsupported too");

declAndTypePrinter.printAvailability(os, FD);
if (!isDefinition) {
os << ";\n";
return;
Expand Down Expand Up @@ -1446,6 +1448,7 @@ static std::string remapPropertyName(const AccessorDecl *accessor,
}

void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isStatic, bool isDefinition,
Expand All @@ -1466,6 +1469,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
accessor, signature, remapPropertyName(accessor, resultTy), resultTy,
FunctionSignatureKind::CxxInlineThunk, modifiers);
assert(!result.isUnsupported() && "C signature should be unsupported too!");
declAndTypePrinter.printAvailability(os, accessor->getStorage());
if (!isDefinition) {
os << ";\n";
return;
Expand All @@ -1480,6 +1484,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
}

void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
DeclAndTypePrinter &declAndTypePrinter,
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
Type resultTy, bool isDefinition,
Expand All @@ -1494,6 +1499,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
printFunctionSignature(accessor, signature, "operator []", resultTy,
FunctionSignatureKind::CxxInlineThunk, modifiers);
assert(!result.isUnsupported() && "C signature should be unsupported too!");
declAndTypePrinter.printAvailability(os, accessor->getStorage());
if (!isDefinition) {
os << ";\n";
return;
Expand Down
3 changes: 3 additions & 0 deletions lib/PrintAsClang/PrintClangFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,23 @@ class DeclAndTypeClangFunctionPrinter {
/// 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,
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,
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,
Expand Down
39 changes: 26 additions & 13 deletions lib/PrintAsClang/PrintClangValueType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "PrintClangValueType.h"
#include "ClangSyntaxPrinter.h"
#include "DeclAndTypePrinter.h"
#include "OutputLanguageMode.h"
#include "PrimitiveTypeMapping.h"
#include "SwiftToClangInteropContext.h"
Expand Down Expand Up @@ -81,14 +82,16 @@ printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl,
os << "};\n\n";
}

void ClangValueTypePrinter::forwardDeclType(raw_ostream &os,
const NominalTypeDecl *typeDecl) {
void ClangValueTypePrinter::forwardDeclType(
raw_ostream &os, const NominalTypeDecl *typeDecl,
DeclAndTypePrinter &declAndTypePrinter) {
if (typeDecl->isGeneric()) {
auto genericSignature =
typeDecl->getGenericSignature().getCanonicalSignature();
ClangSyntaxPrinter(os).printGenericSignature(genericSignature);
}
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
os << ' ';
ClangSyntaxPrinter(os).printBaseName(typeDecl);
Expand Down Expand Up @@ -173,8 +176,8 @@ static void addCppExtensionsToStdlibType(const NominalTypeDecl *typeDecl,
}

void ClangValueTypePrinter::printValueTypeDecl(
const NominalTypeDecl *typeDecl,
llvm::function_ref<void(void)> bodyPrinter) {
const NominalTypeDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter,
DeclAndTypePrinter &declAndTypePrinter) {
// FIXME: Add support for generic structs.
llvm::Optional<IRABIDetailsProvider::SizeAndAlignment> typeSizeAlign;
Optional<CanGenericSignature> genericSignature;
Expand Down Expand Up @@ -221,7 +224,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
printer.printNamespace(cxx_synthesis::getCxxImplNamespaceName(),
[&](raw_ostream &os) {
printGenericSignature(os);
os << "class ";
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
os << ' ';
printCxxImplClassName(os, typeDecl);
os << ";\n\n";

Expand Down Expand Up @@ -263,6 +268,7 @@ void ClangValueTypePrinter::printValueTypeDecl(
// Print out the C++ class itself.
printGenericSignature(os);
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
os << ' ';
ClangSyntaxPrinter(os).printBaseName(typeDecl);
Expand Down Expand Up @@ -408,7 +414,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
printer.printNamespace(
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
printGenericSignature(os);
os << "class ";
os << "class";
declAndTypePrinter.printAvailability(os, typeDecl);
os << ' ';
printCxxImplClassName(os, typeDecl);
os << " {\n";
os << "public:\n";
Expand Down Expand Up @@ -461,7 +469,7 @@ void ClangValueTypePrinter::printValueTypeDecl(

printTypeGenericTraits(os, typeDecl, typeMetadataFuncName,
typeMetadataFuncGenericParams,
typeDecl->getModuleContext());
typeDecl->getModuleContext(), declAndTypePrinter);
}

void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
Expand Down Expand Up @@ -512,8 +520,8 @@ void ClangValueTypePrinter::printValueTypeReturnScaffold(
}

void ClangValueTypePrinter::printClangTypeSwiftGenericTraits(
raw_ostream &os, const TypeDecl *typeDecl,
const ModuleDecl *moduleContext) {
raw_ostream &os, const TypeDecl *typeDecl, const ModuleDecl *moduleContext,
DeclAndTypePrinter &declAndTypePrinter) {
assert(typeDecl->hasClangNode());
// Do not reference unspecialized templates.
if (isa<clang::ClassTemplateDecl>(typeDecl->getClangDecl()))
Expand All @@ -522,7 +530,8 @@ void ClangValueTypePrinter::printClangTypeSwiftGenericTraits(
typeDecl->getDeclaredInterfaceType()->getCanonicalType());
std::string typeMetadataFuncName = typeMetadataFunc.mangleAsString();
printTypeGenericTraits(os, typeDecl, typeMetadataFuncName,
/*typeMetadataFuncRequirements=*/{}, moduleContext);
/*typeMetadataFuncRequirements=*/{}, moduleContext,
declAndTypePrinter);
}

void ClangValueTypePrinter::printTypePrecedingGenericTraits(
Expand Down Expand Up @@ -553,7 +562,7 @@ void ClangValueTypePrinter::printTypePrecedingGenericTraits(
void ClangValueTypePrinter::printTypeGenericTraits(
raw_ostream &os, const TypeDecl *typeDecl, StringRef typeMetadataFuncName,
ArrayRef<GenericRequirement> typeMetadataFuncRequirements,
const ModuleDecl *moduleContext) {
const ModuleDecl *moduleContext, DeclAndTypePrinter &declAndTypePrinter) {
auto *NTD = dyn_cast<NominalTypeDecl>(typeDecl);
ClangSyntaxPrinter printer(os);
// FIXME: avoid popping out of the module's namespace here.
Expand All @@ -580,7 +589,9 @@ void ClangValueTypePrinter::printTypeGenericTraits(
}
if (!NTD || printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(NTD))
os << "template<>\n";
os << "struct TypeMetadataTrait<";
os << "struct";
declAndTypePrinter.printAvailability(os, typeDecl);
os << " TypeMetadataTrait<";
if (typeDecl->hasClangNode()) {
printer.printClangTypeReference(typeDecl->getClangDecl());
} else {
Expand Down Expand Up @@ -635,7 +646,9 @@ void ClangValueTypePrinter::printTypeGenericTraits(
if (!typeDecl->hasClangNode() && typeMetadataFuncRequirements.empty()) {
assert(NTD);
os << "template<>\n";
os << "struct implClassFor<";
os << "struct";
declAndTypePrinter.printAvailability(os, typeDecl);
os << " implClassFor<";
printer.printBaseName(typeDecl->getModuleContext());
os << "::";
printer.printBaseName(typeDecl);
Expand Down
17 changes: 11 additions & 6 deletions lib/PrintAsClang/PrintClangValueType.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

namespace swift {

class DeclAndTypePrinter;
class ModuleDecl;
class NominalTypeDecl;
class PrimitiveTypeMapping;
Expand All @@ -39,7 +40,9 @@ class ClangValueTypePrinter {
/// Print the C++ class definition that
/// corresponds to the given structure or enum declaration.
void printValueTypeDecl(const NominalTypeDecl *typeDecl,
llvm::function_ref<void(void)> bodyPrinter);
llvm::function_ref<void(void)> bodyPrinter,

DeclAndTypePrinter &declAndTypePrinter);

/// Print the use of a C++ struct/enum parameter value as it's passed to the
/// underlying C function that represents the native Swift function.
Expand Down Expand Up @@ -93,19 +96,21 @@ class ClangValueTypePrinter {
static void printTypeGenericTraits(
raw_ostream &os, const TypeDecl *typeDecl, StringRef typeMetadataFuncName,
ArrayRef<GenericRequirement> typeMetadataFuncRequirements,
const ModuleDecl *moduleContext);
const ModuleDecl *moduleContext, DeclAndTypePrinter &declAndTypePrinter);

static void printTypePrecedingGenericTraits(raw_ostream &os,
const NominalTypeDecl *typeDecl,
const ModuleDecl *moduleContext);

static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl);
static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl,
DeclAndTypePrinter &declAndTypePrinter);

/// Print out the type traits that allow a C++ type be used a Swift generic
/// context.
static void printClangTypeSwiftGenericTraits(raw_ostream &os,
const TypeDecl *typeDecl,
const ModuleDecl *moduleContext);
static void
printClangTypeSwiftGenericTraits(raw_ostream &os, const TypeDecl *typeDecl,
const ModuleDecl *moduleContext,
DeclAndTypePrinter &declAndTypePrinter);

private:
raw_ostream &os;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name Class -clang-header-expose-decls=all-public -emit-clang-header-path %t/class.h
// RUN: %FileCheck %s < %t/class.h

// RUN: %check-interop-cxx-header-in-clang(%t/class.h)

@available(macOS 11, *)
public final class ClassWithMacAvailability {
var field: Int64

init() {
field = 0
}
}

// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) _impl_ClassWithMacAvailability;
// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) SWIFT_SYMBOL("s:5Class0A19WithMacAvailabilityC") ClassWithMacAvailability final
// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) _impl_ClassWithMacAvailability {
// CHECK: struct SWIFT_AVAILABILITY(macos,introduced=11) TypeMetadataTrait<Class::ClassWithMacAvailability> {
// CHECK: struct SWIFT_AVAILABILITY(macos,introduced=11) implClassFor<Class::ClassWithMacAvailability>

@available(*, unavailable, message: "stuff happened")
public final class ClassWithUnavailable {
var field: Int64

init() {
field = 0
}
}

// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") _impl_ClassWithUnavailable;
// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") SWIFT_SYMBOL("s:5Class0A15WithUnavailableC") ClassWithUnavailable final
// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") _impl_ClassWithUnavailable {
// CHECK: struct SWIFT_UNAVAILABLE_MSG("stuff happened") TypeMetadataTrait<Class::ClassWithUnavailable> {
// CHECK: struct SWIFT_UNAVAILABLE_MSG("stuff happened") implClassFor<Class::ClassWithUnavailable>
Loading