Skip to content

Commit aa76eca

Browse files
committed
[APINotes] Add SwiftDestroyAs API note to map to the "destroy" function
Like retain/release for reference types, "destroy" lets us specify an operation that is used to deinitialize an instance of a noncopyable type.
1 parent 5cb0db1 commit aa76eca

File tree

10 files changed

+51
-1
lines changed

10 files changed

+51
-1
lines changed

clang/docs/APINotes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@ declaration kind), all of which are optional:
188188
- Name: tzdb
189189
SwiftCopyable: false
190190

191+
A non-copyable type can have a "destroy" operation, specified with
192+
`SwiftDestroyOp`, which will be invoked on the instance when it is no
193+
longer in use to free up resources.
194+
195+
::
196+
197+
Tags:
198+
- Name: WGPUAdapterInfo
199+
SwiftCopyable: false
200+
SwiftDestroyOp: wgpuAdapterInfoFreeMembers
201+
191202
:SwiftConformsTo:
192203

193204
Allows annotating a C++ class as conforming to a Swift protocol. Equivalent

clang/include/clang/APINotes/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,7 @@ class TagInfo : public CommonTypeInfo {
837837
std::optional<std::string> SwiftImportAs;
838838
std::optional<std::string> SwiftRetainOp;
839839
std::optional<std::string> SwiftReleaseOp;
840+
std::optional<std::string> SwiftDestroyOp;
840841

841842
std::optional<EnumExtensibilityKind> EnumExtensibility;
842843

@@ -883,6 +884,8 @@ class TagInfo : public CommonTypeInfo {
883884
SwiftRetainOp = RHS.SwiftRetainOp;
884885
if (!SwiftReleaseOp)
885886
SwiftReleaseOp = RHS.SwiftReleaseOp;
887+
if (!SwiftDestroyOp)
888+
SwiftDestroyOp = RHS.SwiftDestroyOp;
886889

887890
if (!HasFlagEnum)
888891
setFlagEnum(RHS.isFlagEnum());
@@ -909,6 +912,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
909912
LHS.SwiftImportAs == RHS.SwiftImportAs &&
910913
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
911914
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
915+
LHS.SwiftDestroyOp == RHS.SwiftDestroyOp &&
912916
LHS.isFlagEnum() == RHS.isFlagEnum() &&
913917
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
914918
LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&

clang/lib/APINotes/APINotesFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
2424
/// API notes file minor version number.
2525
///
2626
/// When the format changes IN ANY WAY, this number should be incremented.
27-
const uint16_t VERSION_MINOR = 36; // Typedef SwiftConformsTo
27+
const uint16_t VERSION_MINOR = 37; // SwiftDestroyOp
2828

2929
const uint8_t kSwiftConforms = 1;
3030
const uint8_t kSwiftDoesNotConform = 2;

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,13 @@ class TagTableInfo
670670
ReleaseOpLength - 1);
671671
Data += ReleaseOpLength - 1;
672672
}
673+
unsigned DestroyOpLength =
674+
endian::readNext<uint16_t, llvm::endianness::little>(Data);
675+
if (DestroyOpLength > 0) {
676+
Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
677+
DestroyOpLength - 1);
678+
Data += DestroyOpLength - 1;
679+
}
673680

674681
ReadCommonTypeInfo(Data, Info);
675682
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13481348
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
13491349
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
13501350
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1351+
2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
13511352
3 + getCommonTypeInfoSize(TI);
13521353
// clang-format on
13531354
}
@@ -1395,6 +1396,12 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13951396
} else {
13961397
writer.write<uint16_t>(0);
13971398
}
1399+
if (auto DestroyOp = TI.SwiftDestroyOp) {
1400+
writer.write<uint16_t>(DestroyOp->size() + 1);
1401+
OS.write(DestroyOp->c_str(), DestroyOp->size());
1402+
} else {
1403+
writer.write<uint16_t>(0);
1404+
}
13981405

13991406
emitCommonTypeInfo(OS, TI);
14001407
}

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ struct Tag {
630630
std::optional<std::string> SwiftImportAs;
631631
std::optional<std::string> SwiftRetainOp;
632632
std::optional<std::string> SwiftReleaseOp;
633+
std::optional<std::string> SwiftDestroyOp;
633634
std::optional<std::string> SwiftConformance;
634635
std::optional<EnumExtensibilityKind> EnumExtensibility;
635636
std::optional<bool> FlagEnum;
@@ -670,6 +671,7 @@ template <> struct MappingTraits<Tag> {
670671
IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
671672
IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
672673
IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
674+
IO.mapOptional("SwiftDestroyOp", T.SwiftDestroyOp);
673675
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
674676
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
675677
IO.mapOptional("FlagEnum", T.FlagEnum);
@@ -1180,6 +1182,8 @@ class YAMLConverter {
11801182
TI.SwiftRetainOp = T.SwiftRetainOp;
11811183
if (T.SwiftReleaseOp)
11821184
TI.SwiftReleaseOp = T.SwiftReleaseOp;
1185+
if (T.SwiftDestroyOp)
1186+
TI.SwiftDestroyOp = T.SwiftDestroyOp;
11831187

11841188
if (T.SwiftCopyable)
11851189
TI.setSwiftCopyable(T.SwiftCopyable);

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,9 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
779779
if (auto ReleaseOp = Info.SwiftReleaseOp)
780780
D->addAttr(
781781
SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
782+
if (auto DestroyOp = Info.SwiftDestroyOp)
783+
D->addAttr(
784+
SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
782785

783786
if (auto Copyable = Info.isSwiftCopyable()) {
784787
if (!*Copyable)

clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ Tags:
2727
SwiftEscapable: false
2828
- Name: EscapableType
2929
SwiftEscapable: true
30+
- Name: NoncopyableWithDestroyType
31+
SwiftCopyable: false
32+
SwiftDestroyOp: NCDDestroy
3033

3134
Functions:
3235
- Name: functionReturningFrt__

clang/test/APINotes/Inputs/Headers/SwiftImportAs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ inline void ORCRetain(struct OpaqueRefCountedType *x);
2727
inline void ORCRelease(struct OpaqueRefCountedType *x);
2828

2929
typedef unsigned WrappedOptions;
30+
31+
struct NoncopyableWithDestroyType {
32+
};
33+
34+
void NCDDestroy(NoncopyableWithDestroyType instance);

clang/test/APINotes/swift-import-as.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt_returns_unretained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-UNRETAINED %s
1515
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-RETAINED %s
1616
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter WrappedOptions | FileCheck -check-prefix=CHECK-WRAPPED-OPTIONS %s
17+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NoncopyableWithDestroyType | FileCheck -check-prefix=CHECK-NONCOPYABLE-WITH-DESTROY %s
1718

1819
#include <SwiftImportAs.h>
1920

@@ -89,3 +90,8 @@
8990
// CHECK-WRAPPED-OPTIONS: TypedefDecl{{.*}}WrappedOptions 'unsigned int'
9091
// CHECK-WRAPPED-OPTIONS: SwiftNewTypeAttr {{.*}} swift_wrapper NK_Struct
9192
// CHECK-WRAPPED-OPTIONS: SwiftAttrAttr {{.*}} "conforms_to:Swift.OptionSet"
93+
94+
// CHECK-NONCOPYABLE-WITH-DESTROY: Dumping NoncopyableWithDestroyType
95+
// CHECK-NONCOPYABLE-WITH-DESTROY: RecordDecl {{.*}}struct NoncopyableWithDestroyType
96+
// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "destroy:NCDDestroy"
97+
// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "~Copyable"

0 commit comments

Comments
 (0)