Skip to content

Commit ae90b60

Browse files
authored
[APINotes] Add SwiftDestroyOp API note to map to the "destroy" function (#153261)
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 d9bc548 commit ae90b60

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
@@ -206,6 +206,17 @@ declaration kind), all of which are optional:
206206
- Name: tzdb
207207
SwiftCopyable: false
208208

209+
A non-copyable type can have a "destroy" operation, specified with
210+
`SwiftDestroyOp`, which will be invoked on the instance when it is no
211+
longer in use to free up resources.
212+
213+
::
214+
215+
Tags:
216+
- Name: WGPUAdapterInfo
217+
SwiftCopyable: false
218+
SwiftDestroyOp: wgpuAdapterInfoFreeMembers
219+
209220
:SwiftConformsTo:
210221

211222
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
@@ -751,6 +751,7 @@ class TagInfo : public CommonTypeInfo {
751751
std::optional<std::string> SwiftImportAs;
752752
std::optional<std::string> SwiftRetainOp;
753753
std::optional<std::string> SwiftReleaseOp;
754+
std::optional<std::string> SwiftDestroyOp;
754755
std::optional<std::string> SwiftDefaultOwnership;
755756

756757
std::optional<EnumExtensibilityKind> EnumExtensibility;
@@ -798,6 +799,8 @@ class TagInfo : public CommonTypeInfo {
798799
SwiftRetainOp = RHS.SwiftRetainOp;
799800
if (!SwiftReleaseOp)
800801
SwiftReleaseOp = RHS.SwiftReleaseOp;
802+
if (!SwiftDestroyOp)
803+
SwiftDestroyOp = RHS.SwiftDestroyOp;
801804
if (!SwiftDefaultOwnership)
802805
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
803806

@@ -826,6 +829,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
826829
LHS.SwiftImportAs == RHS.SwiftImportAs &&
827830
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
828831
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
832+
LHS.SwiftDestroyOp == RHS.SwiftDestroyOp &&
829833
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
830834
LHS.isFlagEnum() == RHS.isFlagEnum() &&
831835
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&

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
@@ -636,6 +636,13 @@ class TagTableInfo
636636
reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
637637
Data += DefaultOwnershipLength - 1;
638638
}
639+
unsigned DestroyOpLength =
640+
endian::readNext<uint16_t, llvm::endianness::little>(Data);
641+
if (DestroyOpLength > 0) {
642+
Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
643+
DestroyOpLength - 1);
644+
Data += DestroyOpLength - 1;
645+
}
639646

640647
ReadCommonTypeInfo(Data, Info);
641648
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,7 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
12801280
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
12811281
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
12821282
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1283+
2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
12831284
2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
12841285
3 + getCommonTypeInfoSize(TI);
12851286
// clang-format on
@@ -1334,6 +1335,12 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13341335
} else {
13351336
writer.write<uint16_t>(0);
13361337
}
1338+
if (auto DestroyOp = TI.SwiftDestroyOp) {
1339+
writer.write<uint16_t>(DestroyOp->size() + 1);
1340+
OS.write(DestroyOp->c_str(), DestroyOp->size());
1341+
} else {
1342+
writer.write<uint16_t>(0);
1343+
}
13371344

13381345
emitCommonTypeInfo(OS, TI);
13391346
}

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ struct Tag {
462462
std::optional<std::string> SwiftImportAs;
463463
std::optional<std::string> SwiftRetainOp;
464464
std::optional<std::string> SwiftReleaseOp;
465+
std::optional<std::string> SwiftDestroyOp;
465466
std::optional<std::string> SwiftDefaultOwnership;
466467
std::optional<std::string> SwiftConformance;
467468
std::optional<EnumExtensibilityKind> EnumExtensibility;
@@ -503,6 +504,7 @@ template <> struct MappingTraits<Tag> {
503504
IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
504505
IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
505506
IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
507+
IO.mapOptional("SwiftDestroyOp", T.SwiftDestroyOp);
506508
IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership);
507509
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
508510
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
@@ -996,6 +998,8 @@ class YAMLConverter {
996998
TI.SwiftRetainOp = T.SwiftRetainOp;
997999
if (T.SwiftReleaseOp)
9981000
TI.SwiftReleaseOp = T.SwiftReleaseOp;
1001+
if (T.SwiftDestroyOp)
1002+
TI.SwiftDestroyOp = T.SwiftDestroyOp;
9991003
if (T.SwiftDefaultOwnership)
10001004
TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
10011005

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
698698
if (auto ReleaseOp = Info.SwiftReleaseOp)
699699
D->addAttr(
700700
SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
701+
if (auto DestroyOp = Info.SwiftDestroyOp)
702+
D->addAttr(
703+
SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
701704
if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
702705
D->addAttr(SwiftAttrAttr::Create(
703706
S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Tags:
3232
SwiftEscapable: false
3333
- Name: EscapableType
3434
SwiftEscapable: true
35+
- Name: NoncopyableWithDestroyType
36+
SwiftCopyable: false
37+
SwiftDestroyOp: NCDDestroy
3538

3639
Functions:
3740
- Name: functionReturningFrt__

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

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

3333
typedef unsigned WrappedOptions;
34+
35+
struct NoncopyableWithDestroyType {
36+
};
37+
38+
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
@@ -15,6 +15,7 @@
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_unretained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-UNRETAINED %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 methodReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-RETAINED %s
1717
// 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
18+
// 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
1819

1920
#include <SwiftImportAs.h>
2021

@@ -97,3 +98,8 @@
9798
// CHECK-WRAPPED-OPTIONS: TypedefDecl{{.*}}WrappedOptions 'unsigned int'
9899
// CHECK-WRAPPED-OPTIONS: SwiftNewTypeAttr {{.*}} swift_wrapper NK_Struct
99100
// CHECK-WRAPPED-OPTIONS: SwiftAttrAttr {{.*}} "conforms_to:Swift.OptionSet"
101+
102+
// CHECK-NONCOPYABLE-WITH-DESTROY: Dumping NoncopyableWithDestroyType
103+
// CHECK-NONCOPYABLE-WITH-DESTROY: RecordDecl {{.*}}struct NoncopyableWithDestroyType
104+
// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "destroy:NCDDestroy"
105+
// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "~Copyable"

0 commit comments

Comments
 (0)