Skip to content

Commit e7c3828

Browse files
DougGregorAnthonyLatsis
authored andcommitted
[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. (cherry picked from commit aa76eca)
1 parent 26bb450 commit e7c3828

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
@@ -838,6 +838,7 @@ class TagInfo : public CommonTypeInfo {
838838
std::optional<std::string> SwiftRetainOp;
839839
std::optional<std::string> SwiftReleaseOp;
840840
std::optional<std::string> SwiftDefaultOwnership;
841+
std::optional<std::string> SwiftDestroyOp;
841842

842843
std::optional<EnumExtensibilityKind> EnumExtensibility;
843844

@@ -886,6 +887,8 @@ class TagInfo : public CommonTypeInfo {
886887
SwiftReleaseOp = RHS.SwiftReleaseOp;
887888
if (!SwiftDefaultOwnership)
888889
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
890+
if (!SwiftDestroyOp)
891+
SwiftDestroyOp = RHS.SwiftDestroyOp;
889892

890893
if (!HasFlagEnum)
891894
setFlagEnum(RHS.isFlagEnum());
@@ -913,6 +916,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
913916
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
914917
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
915918
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
919+
LHS.SwiftDestroyOp == RHS.SwiftDestroyOp &&
916920
LHS.isFlagEnum() == RHS.isFlagEnum() &&
917921
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
918922
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 = 37; // Typedef SwiftConformsTo
27+
const uint16_t VERSION_MINOR = 38; // 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
@@ -675,6 +675,13 @@ class TagTableInfo
675675
reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
676676
Data += DefaultOwnershipLength - 1;
677677
}
678+
unsigned DestroyOpLength =
679+
endian::readNext<uint16_t, llvm::endianness::little>(Data);
680+
if (DestroyOpLength > 0) {
681+
Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
682+
DestroyOpLength - 1);
683+
Data += DestroyOpLength - 1;
684+
}
678685

679686
ReadCommonTypeInfo(Data, Info);
680687
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,7 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13381338
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
13391339
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
13401340
2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1341+
2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
13411342
3 + getCommonTypeInfoSize(TI);
13421343
// clang-format on
13431344
}
@@ -1391,6 +1392,12 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13911392
} else {
13921393
writer.write<uint16_t>(0);
13931394
}
1395+
if (auto DestroyOp = TI.SwiftDestroyOp) {
1396+
writer.write<uint16_t>(DestroyOp->size() + 1);
1397+
OS.write(DestroyOp->c_str(), DestroyOp->size());
1398+
} else {
1399+
writer.write<uint16_t>(0);
1400+
}
13941401

13951402
emitCommonTypeInfo(OS, TI);
13961403
}

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ struct Tag {
631631
std::optional<std::string> SwiftRetainOp;
632632
std::optional<std::string> SwiftReleaseOp;
633633
std::optional<std::string> SwiftDefaultOwnership;
634+
std::optional<std::string> SwiftDestroyOp;
634635
std::optional<std::string> SwiftConformance;
635636
std::optional<EnumExtensibilityKind> EnumExtensibility;
636637
std::optional<bool> FlagEnum;
@@ -672,6 +673,7 @@ template <> struct MappingTraits<Tag> {
672673
IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
673674
IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
674675
IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership);
676+
IO.mapOptional("SwiftDestroyOp", T.SwiftDestroyOp);
675677
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
676678
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
677679
IO.mapOptional("FlagEnum", T.FlagEnum);
@@ -1184,6 +1186,8 @@ class YAMLConverter {
11841186
TI.SwiftReleaseOp = T.SwiftReleaseOp;
11851187
if (T.SwiftDefaultOwnership)
11861188
TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
1189+
if (T.SwiftDestroyOp)
1190+
TI.SwiftDestroyOp = T.SwiftDestroyOp;
11871191

11881192
if (T.SwiftCopyable)
11891193
TI.setSwiftCopyable(T.SwiftCopyable);

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,9 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
780780
if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
781781
D->addAttr(SwiftAttrAttr::Create(
782782
S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
783+
if (auto DestroyOp = Info.SwiftDestroyOp)
784+
D->addAttr(
785+
SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
783786

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

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)