Author: Doug Gregor Date: 2025-08-15T08:02:14+01:00 New Revision: ae90b60fc8661956250a0b8185be37e8fb92c0d7
URL: https://github.com/llvm/llvm-project/commit/ae90b60fc8661956250a0b8185be37e8fb92c0d7 DIFF: https://github.com/llvm/llvm-project/commit/ae90b60fc8661956250a0b8185be37e8fb92c0d7.diff LOG: [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. Added: Modified: clang/docs/APINotes.rst clang/include/clang/APINotes/Types.h clang/lib/APINotes/APINotesFormat.h clang/lib/APINotes/APINotesReader.cpp clang/lib/APINotes/APINotesWriter.cpp clang/lib/APINotes/APINotesYAMLCompiler.cpp clang/lib/Sema/SemaAPINotes.cpp clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes clang/test/APINotes/Inputs/Headers/SwiftImportAs.h clang/test/APINotes/swift-import-as.cpp Removed: ################################################################################ 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" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits