Skip to content

Commit f20eaac

Browse files
authored
Merge pull request #63946 from hyp/eng/avail
[interop][SwiftToCxx] print availability attributes for Swift decls i…
2 parents e059be1 + f8c3895 commit f20eaac

14 files changed

+364
-139
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 132 additions & 112 deletions
Large diffs are not rendered by default.

lib/PrintAsClang/DeclAndTypePrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class DeclAndTypePrinter {
8181
void print(const Decl *D);
8282
void print(Type ty);
8383

84+
void printAvailability(raw_ostream &os, const Decl *D);
85+
8486
/// Is \p ED empty of members and protocol conformances to include?
8587
bool isEmptyExtensionDecl(const ExtensionDecl *ED);
8688

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,14 @@ class ModuleWriter {
289289
return;
290290
auto it = seenClangTypes.insert(clangType.getTypePtr());
291291
if (it.second)
292-
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M);
292+
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M,
293+
printer);
293294
}
294295

295296
void forwardDeclareCxxValueTypeIfNeeded(const NominalTypeDecl *NTD) {
296-
forwardDeclare(NTD,
297-
[&]() { ClangValueTypePrinter::forwardDeclType(os, NTD); });
297+
forwardDeclare(NTD, [&]() {
298+
ClangValueTypePrinter::forwardDeclType(os, NTD, printer);
299+
});
298300
}
299301

300302
void forwardDeclareType(const TypeDecl *TD) {

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212

1313
#include "PrintClangClassType.h"
1414
#include "ClangSyntaxPrinter.h"
15+
#include "DeclAndTypePrinter.h"
1516
#include "PrintClangValueType.h"
1617
#include "swift/AST/Decl.h"
1718
#include "swift/IRGen/Linking.h"
1819

1920
using namespace swift;
2021

2122
void ClangClassTypePrinter::printClassTypeDecl(
22-
const ClassDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter) {
23+
const ClassDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter,
24+
DeclAndTypePrinter &declAndTypePrinter) {
2325
auto printCxxImplClassName = ClangValueTypePrinter::printCxxImplClassName;
2426

2527
ClangSyntaxPrinter printer(os);
@@ -31,7 +33,9 @@ void ClangClassTypePrinter::printClassTypeDecl(
3133
// Print out a forward declaration of the "hidden" _impl class.
3234
printer.printNamespace(cxx_synthesis::getCxxImplNamespaceName(),
3335
[&](raw_ostream &os) {
34-
os << "class ";
36+
os << "class";
37+
declAndTypePrinter.printAvailability(os, typeDecl);
38+
os << ' ';
3539
printCxxImplClassName(os, typeDecl);
3640
os << ";\n";
3741
// Print out special functions, like functions that
@@ -57,6 +61,7 @@ void ClangClassTypePrinter::printClassTypeDecl(
5761
}
5862

5963
os << "class";
64+
declAndTypePrinter.printAvailability(os, typeDecl);
6065
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
6166
os << ' ';
6267
printer.printBaseName(typeDecl);
@@ -83,7 +88,9 @@ void ClangClassTypePrinter::printClassTypeDecl(
8388
// Print out the "hidden" _impl class.
8489
printer.printNamespace(
8590
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
86-
os << "class ";
91+
os << "class";
92+
declAndTypePrinter.printAvailability(os, typeDecl);
93+
os << ' ';
8794
printCxxImplClassName(os, typeDecl);
8895
os << " {\n";
8996
os << "public:\n";
@@ -98,7 +105,7 @@ void ClangClassTypePrinter::printClassTypeDecl(
98105

99106
ClangValueTypePrinter::printTypeGenericTraits(
100107
os, typeDecl, typeMetadataFuncName, /*genericRequirements=*/{},
101-
typeDecl->getModuleContext());
108+
typeDecl->getModuleContext(), declAndTypePrinter);
102109
}
103110

104111
void ClangClassTypePrinter::printClassTypeReturnScaffold(

lib/PrintAsClang/PrintClangClassType.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace swift {
2121

2222
class ClassDecl;
2323
class ModuleDecl;
24+
class DeclAndTypePrinter;
2425

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

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

3537
static void
3638
printClassTypeReturnScaffold(raw_ostream &os, const ClassDecl *type,

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,7 @@ static StringRef getConstructorName(const AbstractFunctionDecl *FD) {
13771377
}
13781378

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

1405+
declAndTypePrinter.printAvailability(os, FD);
14041406
if (!isDefinition) {
14051407
os << ";\n";
14061408
return;
@@ -1446,6 +1448,7 @@ static std::string remapPropertyName(const AccessorDecl *accessor,
14461448
}
14471449

14481450
void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
1451+
DeclAndTypePrinter &declAndTypePrinter,
14491452
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
14501453
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
14511454
Type resultTy, bool isStatic, bool isDefinition,
@@ -1466,6 +1469,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
14661469
accessor, signature, remapPropertyName(accessor, resultTy), resultTy,
14671470
FunctionSignatureKind::CxxInlineThunk, modifiers);
14681471
assert(!result.isUnsupported() && "C signature should be unsupported too!");
1472+
declAndTypePrinter.printAvailability(os, accessor->getStorage());
14691473
if (!isDefinition) {
14701474
os << ";\n";
14711475
return;
@@ -1480,6 +1484,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
14801484
}
14811485

14821486
void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
1487+
DeclAndTypePrinter &declAndTypePrinter,
14831488
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
14841489
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
14851490
Type resultTy, bool isDefinition,
@@ -1494,6 +1499,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
14941499
printFunctionSignature(accessor, signature, "operator []", resultTy,
14951500
FunctionSignatureKind::CxxInlineThunk, modifiers);
14961501
assert(!result.isUnsupported() && "C signature should be unsupported too!");
1502+
declAndTypePrinter.printAvailability(os, accessor->getStorage());
14971503
if (!isDefinition) {
14981504
os << ";\n";
14991505
return;

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,23 @@ class DeclAndTypeClangFunctionPrinter {
119119
/// Print the Swift method as C++ method declaration/definition, including
120120
/// constructors.
121121
void printCxxMethod(
122+
DeclAndTypePrinter &declAndTypePrinter,
122123
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
123124
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
124125
Type resultTy, bool isStatic, bool isDefinition,
125126
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
126127

127128
/// Print the C++ getter/setter method signature.
128129
void printCxxPropertyAccessorMethod(
130+
DeclAndTypePrinter &declAndTypePrinter,
129131
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
130132
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
131133
Type resultTy, bool isStatic, bool isDefinition,
132134
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
133135

134136
/// Print the C++ subscript method.
135137
void printCxxSubscriptAccessorMethod(
138+
DeclAndTypePrinter &declAndTypePrinter,
136139
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
137140
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
138141
Type resultTy, bool isDefinition,

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "PrintClangValueType.h"
1414
#include "ClangSyntaxPrinter.h"
15+
#include "DeclAndTypePrinter.h"
1516
#include "OutputLanguageMode.h"
1617
#include "PrimitiveTypeMapping.h"
1718
#include "SwiftToClangInteropContext.h"
@@ -81,14 +82,16 @@ printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl,
8182
os << "};\n\n";
8283
}
8384

84-
void ClangValueTypePrinter::forwardDeclType(raw_ostream &os,
85-
const NominalTypeDecl *typeDecl) {
85+
void ClangValueTypePrinter::forwardDeclType(
86+
raw_ostream &os, const NominalTypeDecl *typeDecl,
87+
DeclAndTypePrinter &declAndTypePrinter) {
8688
if (typeDecl->isGeneric()) {
8789
auto genericSignature =
8890
typeDecl->getGenericSignature().getCanonicalSignature();
8991
ClangSyntaxPrinter(os).printGenericSignature(genericSignature);
9092
}
9193
os << "class";
94+
declAndTypePrinter.printAvailability(os, typeDecl);
9295
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
9396
os << ' ';
9497
ClangSyntaxPrinter(os).printBaseName(typeDecl);
@@ -173,8 +176,8 @@ static void addCppExtensionsToStdlibType(const NominalTypeDecl *typeDecl,
173176
}
174177

175178
void ClangValueTypePrinter::printValueTypeDecl(
176-
const NominalTypeDecl *typeDecl,
177-
llvm::function_ref<void(void)> bodyPrinter) {
179+
const NominalTypeDecl *typeDecl, llvm::function_ref<void(void)> bodyPrinter,
180+
DeclAndTypePrinter &declAndTypePrinter) {
178181
// FIXME: Add support for generic structs.
179182
llvm::Optional<IRABIDetailsProvider::SizeAndAlignment> typeSizeAlign;
180183
Optional<CanGenericSignature> genericSignature;
@@ -221,7 +224,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
221224
printer.printNamespace(cxx_synthesis::getCxxImplNamespaceName(),
222225
[&](raw_ostream &os) {
223226
printGenericSignature(os);
224-
os << "class ";
227+
os << "class";
228+
declAndTypePrinter.printAvailability(os, typeDecl);
229+
os << ' ';
225230
printCxxImplClassName(os, typeDecl);
226231
os << ";\n\n";
227232

@@ -263,6 +268,7 @@ void ClangValueTypePrinter::printValueTypeDecl(
263268
// Print out the C++ class itself.
264269
printGenericSignature(os);
265270
os << "class";
271+
declAndTypePrinter.printAvailability(os, typeDecl);
266272
ClangSyntaxPrinter(os).printSymbolUSRAttribute(typeDecl);
267273
os << ' ';
268274
ClangSyntaxPrinter(os).printBaseName(typeDecl);
@@ -408,7 +414,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
408414
printer.printNamespace(
409415
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
410416
printGenericSignature(os);
411-
os << "class ";
417+
os << "class";
418+
declAndTypePrinter.printAvailability(os, typeDecl);
419+
os << ' ';
412420
printCxxImplClassName(os, typeDecl);
413421
os << " {\n";
414422
os << "public:\n";
@@ -461,7 +469,7 @@ void ClangValueTypePrinter::printValueTypeDecl(
461469

462470
printTypeGenericTraits(os, typeDecl, typeMetadataFuncName,
463471
typeMetadataFuncGenericParams,
464-
typeDecl->getModuleContext());
472+
typeDecl->getModuleContext(), declAndTypePrinter);
465473
}
466474

467475
void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
@@ -512,8 +520,8 @@ void ClangValueTypePrinter::printValueTypeReturnScaffold(
512520
}
513521

514522
void ClangValueTypePrinter::printClangTypeSwiftGenericTraits(
515-
raw_ostream &os, const TypeDecl *typeDecl,
516-
const ModuleDecl *moduleContext) {
523+
raw_ostream &os, const TypeDecl *typeDecl, const ModuleDecl *moduleContext,
524+
DeclAndTypePrinter &declAndTypePrinter) {
517525
assert(typeDecl->hasClangNode());
518526
// Do not reference unspecialized templates.
519527
if (isa<clang::ClassTemplateDecl>(typeDecl->getClangDecl()))
@@ -522,7 +530,8 @@ void ClangValueTypePrinter::printClangTypeSwiftGenericTraits(
522530
typeDecl->getDeclaredInterfaceType()->getCanonicalType());
523531
std::string typeMetadataFuncName = typeMetadataFunc.mangleAsString();
524532
printTypeGenericTraits(os, typeDecl, typeMetadataFuncName,
525-
/*typeMetadataFuncRequirements=*/{}, moduleContext);
533+
/*typeMetadataFuncRequirements=*/{}, moduleContext,
534+
declAndTypePrinter);
526535
}
527536

528537
void ClangValueTypePrinter::printTypePrecedingGenericTraits(
@@ -553,7 +562,7 @@ void ClangValueTypePrinter::printTypePrecedingGenericTraits(
553562
void ClangValueTypePrinter::printTypeGenericTraits(
554563
raw_ostream &os, const TypeDecl *typeDecl, StringRef typeMetadataFuncName,
555564
ArrayRef<GenericRequirement> typeMetadataFuncRequirements,
556-
const ModuleDecl *moduleContext) {
565+
const ModuleDecl *moduleContext, DeclAndTypePrinter &declAndTypePrinter) {
557566
auto *NTD = dyn_cast<NominalTypeDecl>(typeDecl);
558567
ClangSyntaxPrinter printer(os);
559568
// FIXME: avoid popping out of the module's namespace here.
@@ -580,7 +589,9 @@ void ClangValueTypePrinter::printTypeGenericTraits(
580589
}
581590
if (!NTD || printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(NTD))
582591
os << "template<>\n";
583-
os << "struct TypeMetadataTrait<";
592+
os << "struct";
593+
declAndTypePrinter.printAvailability(os, typeDecl);
594+
os << " TypeMetadataTrait<";
584595
if (typeDecl->hasClangNode()) {
585596
printer.printClangTypeReference(typeDecl->getClangDecl());
586597
} else {
@@ -635,7 +646,9 @@ void ClangValueTypePrinter::printTypeGenericTraits(
635646
if (!typeDecl->hasClangNode() && typeMetadataFuncRequirements.empty()) {
636647
assert(NTD);
637648
os << "template<>\n";
638-
os << "struct implClassFor<";
649+
os << "struct";
650+
declAndTypePrinter.printAvailability(os, typeDecl);
651+
os << " implClassFor<";
639652
printer.printBaseName(typeDecl->getModuleContext());
640653
os << "::";
641654
printer.printBaseName(typeDecl);

lib/PrintAsClang/PrintClangValueType.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
namespace swift {
2424

25+
class DeclAndTypePrinter;
2526
class ModuleDecl;
2627
class NominalTypeDecl;
2728
class PrimitiveTypeMapping;
@@ -39,7 +40,9 @@ class ClangValueTypePrinter {
3940
/// Print the C++ class definition that
4041
/// corresponds to the given structure or enum declaration.
4142
void printValueTypeDecl(const NominalTypeDecl *typeDecl,
42-
llvm::function_ref<void(void)> bodyPrinter);
43+
llvm::function_ref<void(void)> bodyPrinter,
44+
45+
DeclAndTypePrinter &declAndTypePrinter);
4346

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

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

102-
static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl);
105+
static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl,
106+
DeclAndTypePrinter &declAndTypePrinter);
103107

104108
/// Print out the type traits that allow a C++ type be used a Swift generic
105109
/// context.
106-
static void printClangTypeSwiftGenericTraits(raw_ostream &os,
107-
const TypeDecl *typeDecl,
108-
const ModuleDecl *moduleContext);
110+
static void
111+
printClangTypeSwiftGenericTraits(raw_ostream &os, const TypeDecl *typeDecl,
112+
const ModuleDecl *moduleContext,
113+
DeclAndTypePrinter &declAndTypePrinter);
109114

110115
private:
111116
raw_ostream &os;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Class -clang-header-expose-decls=all-public -emit-clang-header-path %t/class.h
3+
// RUN: %FileCheck %s < %t/class.h
4+
5+
// RUN: %check-interop-cxx-header-in-clang(%t/class.h)
6+
7+
@available(macOS 11, *)
8+
public final class ClassWithMacAvailability {
9+
var field: Int64
10+
11+
init() {
12+
field = 0
13+
}
14+
}
15+
16+
// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) _impl_ClassWithMacAvailability;
17+
// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) SWIFT_SYMBOL("s:5Class0A19WithMacAvailabilityC") ClassWithMacAvailability final
18+
// CHECK: class SWIFT_AVAILABILITY(macos,introduced=11) _impl_ClassWithMacAvailability {
19+
// CHECK: struct SWIFT_AVAILABILITY(macos,introduced=11) TypeMetadataTrait<Class::ClassWithMacAvailability> {
20+
// CHECK: struct SWIFT_AVAILABILITY(macos,introduced=11) implClassFor<Class::ClassWithMacAvailability>
21+
22+
@available(*, unavailable, message: "stuff happened")
23+
public final class ClassWithUnavailable {
24+
var field: Int64
25+
26+
init() {
27+
field = 0
28+
}
29+
}
30+
31+
// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") _impl_ClassWithUnavailable;
32+
// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") SWIFT_SYMBOL("s:5Class0A15WithUnavailableC") ClassWithUnavailable final
33+
// CHECK: class SWIFT_UNAVAILABLE_MSG("stuff happened") _impl_ClassWithUnavailable {
34+
// CHECK: struct SWIFT_UNAVAILABLE_MSG("stuff happened") TypeMetadataTrait<Class::ClassWithUnavailable> {
35+
// CHECK: struct SWIFT_UNAVAILABLE_MSG("stuff happened") implClassFor<Class::ClassWithUnavailable>

0 commit comments

Comments
 (0)