-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[APINotes] Add SwiftDestroyOp API note to map to the "destroy" function #153261
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
Conversation
|
@llvm/pr-subscribers-clang Author: Doug Gregor (DougGregor) ChangesLike retain/release for reference types, "destroy" lets us specify an operation that is used to deinitialize an instance of a noncopyable type. Full diff: https://github.com/llvm/llvm-project/pull/153261.diff 10 Files Affected:
diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst
index e5ec154237b0d..dec4b186ff72f 100644
--- a/clang/docs/APINotes.rst
+++ b/clang/docs/APINotes.rst
@@ -206,6 +206,17 @@ declaration kind), all of which are optional:
- Name: tzdb
SwiftCopyable: false
+ A non-copyable type can have a "destroy" operation, specified with
+ `SwiftDestroyOp`, which will be invoked on the instance when it is no
+ longer in use to free up resources.
+
+ ::
+
+ Tags:
+ - Name: WGPUAdapterInfo
+ SwiftCopyable: false
+ SwiftDestroyOp: wgpuAdapterInfoFreeMembers
+
:SwiftConformsTo:
Allows annotating a C++ class as conforming to a Swift protocol. Equivalent
diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h
index 8708b4b092f28..71625715bda19 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -751,6 +751,7 @@ class TagInfo : public CommonTypeInfo {
std::optional<std::string> SwiftImportAs;
std::optional<std::string> SwiftRetainOp;
std::optional<std::string> SwiftReleaseOp;
+ std::optional<std::string> SwiftDestroyOp;
std::optional<std::string> SwiftDefaultOwnership;
std::optional<EnumExtensibilityKind> EnumExtensibility;
@@ -798,6 +799,8 @@ class TagInfo : public CommonTypeInfo {
SwiftRetainOp = RHS.SwiftRetainOp;
if (!SwiftReleaseOp)
SwiftReleaseOp = RHS.SwiftReleaseOp;
+ if (!SwiftDestroyOp)
+ SwiftDestroyOp = RHS.SwiftDestroyOp;
if (!SwiftDefaultOwnership)
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
@@ -826,6 +829,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
LHS.SwiftImportAs == RHS.SwiftImportAs &&
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
+ LHS.SwiftDestroyOp == RHS.SwiftDestroyOp &&
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
LHS.isFlagEnum() == RHS.isFlagEnum() &&
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h
index 1ac486a2dd94c..69d180e7b3eb5 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
/// API notes file minor version number.
///
/// When the format changes IN ANY WAY, this number should be incremented.
-const uint16_t VERSION_MINOR = 36; // Typedef SwiftConformsTo
+const uint16_t VERSION_MINOR = 37; // SwiftDestroyOp
const uint8_t kSwiftConforms = 1;
const uint8_t kSwiftDoesNotConform = 2;
diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp
index 8b3812613b166..573356f97ff73 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -636,6 +636,13 @@ class TagTableInfo
reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
Data += DefaultOwnershipLength - 1;
}
+ unsigned DestroyOpLength =
+ endian::readNext<uint16_t, llvm::endianness::little>(Data);
+ if (DestroyOpLength > 0) {
+ Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
+ DestroyOpLength - 1);
+ Data += DestroyOpLength - 1;
+ }
ReadCommonTypeInfo(Data, Info);
return Info;
diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp
index c013201d677bf..cf88d118d0979 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -1280,6 +1280,7 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
+ 2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
3 + getCommonTypeInfoSize(TI);
// clang-format on
@@ -1334,6 +1335,12 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
} else {
writer.write<uint16_t>(0);
}
+ if (auto DestroyOp = TI.SwiftDestroyOp) {
+ writer.write<uint16_t>(DestroyOp->size() + 1);
+ OS.write(DestroyOp->c_str(), DestroyOp->size());
+ } else {
+ writer.write<uint16_t>(0);
+ }
emitCommonTypeInfo(OS, TI);
}
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index fcc1d9d54b1c6..a91a1eea03d81 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -462,6 +462,7 @@ struct Tag {
std::optional<std::string> SwiftImportAs;
std::optional<std::string> SwiftRetainOp;
std::optional<std::string> SwiftReleaseOp;
+ std::optional<std::string> SwiftDestroyOp;
std::optional<std::string> SwiftDefaultOwnership;
std::optional<std::string> SwiftConformance;
std::optional<EnumExtensibilityKind> EnumExtensibility;
@@ -503,6 +504,7 @@ template <> struct MappingTraits<Tag> {
IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
+ IO.mapOptional("SwiftDestroyOp", T.SwiftDestroyOp);
IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership);
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
@@ -996,6 +998,8 @@ class YAMLConverter {
TI.SwiftRetainOp = T.SwiftRetainOp;
if (T.SwiftReleaseOp)
TI.SwiftReleaseOp = T.SwiftReleaseOp;
+ if (T.SwiftDestroyOp)
+ TI.SwiftDestroyOp = T.SwiftDestroyOp;
if (T.SwiftDefaultOwnership)
TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 272069e5fcc7d..4cc1b76264340 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -698,6 +698,9 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
if (auto ReleaseOp = Info.SwiftReleaseOp)
D->addAttr(
SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
+ if (auto DestroyOp = Info.SwiftDestroyOp)
+ D->addAttr(
+ SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
D->addAttr(SwiftAttrAttr::Create(
S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
index cf739ee81c0a9..15c806842d08f 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
@@ -32,6 +32,9 @@ Tags:
SwiftEscapable: false
- Name: EscapableType
SwiftEscapable: true
+- Name: NoncopyableWithDestroyType
+ SwiftCopyable: false
+ SwiftDestroyOp: NCDDestroy
Functions:
- Name: functionReturningFrt__
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
index 4ff45c754fe88..978b4fbbb3b00 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
@@ -31,3 +31,8 @@ inline void ORCRetain(struct OpaqueRefCountedType *x);
inline void ORCRelease(struct OpaqueRefCountedType *x);
typedef unsigned WrappedOptions;
+
+struct NoncopyableWithDestroyType {
+};
+
+void NCDDestroy(NoncopyableWithDestroyType instance);
diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp
index 64c8c6f202f98..f5d08df7c6a1b 100644
--- a/clang/test/APINotes/swift-import-as.cpp
+++ b/clang/test/APINotes/swift-import-as.cpp
@@ -15,6 +15,7 @@
// 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
// 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
// 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
+// 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
#include <SwiftImportAs.h>
@@ -97,3 +98,8 @@
// CHECK-WRAPPED-OPTIONS: TypedefDecl{{.*}}WrappedOptions 'unsigned int'
// CHECK-WRAPPED-OPTIONS: SwiftNewTypeAttr {{.*}} swift_wrapper NK_Struct
// CHECK-WRAPPED-OPTIONS: SwiftAttrAttr {{.*}} "conforms_to:Swift.OptionSet"
+
+// CHECK-NONCOPYABLE-WITH-DESTROY: Dumping NoncopyableWithDestroyType
+// CHECK-NONCOPYABLE-WITH-DESTROY: RecordDecl {{.*}}struct NoncopyableWithDestroyType
+// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "destroy:NCDDestroy"
+// CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "~Copyable"
|
|
Hmph, documentation build failure is from OpenMP documentation files that aren't touched by this PR. |
egorzhdan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Like retain/release for reference types, "destroy" lets us specify an operation that is used to deinitialize an instance of a noncopyable type.
87f0863 to
169a5a7
Compare
Like retain/release for reference types, "destroy" lets us specify an operation that is used to deinitialize an instance of a noncopyable type.