[clang] [clang][APINotes] Add support for the SwiftEscapable attribute (PR #115866)
Gábor Horváth via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 12 10:17:38 PST 2024
https://github.com/Xazax-hun updated https://github.com/llvm/llvm-project/pull/115866
>From cdb2a965d3aae112f6661ea80b62fdc25a7d3837 Mon Sep 17 00:00:00 2001
From: Gabor Horvath <gaborh at apple.com>
Date: Tue, 12 Nov 2024 13:07:01 +0000
Subject: [PATCH] [clang][APINotes] Add support for the SwiftEscapable
attribute
This is similar to SwiftCopyable. Also fix missing SwiftCopyable dump for
TagInfo.
---
clang/include/clang/APINotes/Types.h | 22 ++++++++++++++++++-
clang/lib/APINotes/APINotesFormat.h | 7 +++---
clang/lib/APINotes/APINotesReader.cpp | 10 +++++----
clang/lib/APINotes/APINotesTypes.cpp | 4 ++++
clang/lib/APINotes/APINotesWriter.cpp | 11 ++++++++--
clang/lib/APINotes/APINotesYAMLCompiler.cpp | 4 ++++
clang/lib/Sema/SemaAPINotes.cpp | 5 +++++
.../Inputs/Headers/SwiftImportAs.apinotes | 4 ++++
.../APINotes/Inputs/Headers/SwiftImportAs.h | 3 +++
clang/test/APINotes/swift-import-as.cpp | 10 +++++++++
10 files changed, 69 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h
index 6ad1c850701146..ff374ad3ada065 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -724,6 +724,11 @@ class TagInfo : public CommonTypeInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftCopyable : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SwiftEscapableSpecified : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SwiftEscapable : 1;
+
public:
std::optional<std::string> SwiftImportAs;
std::optional<std::string> SwiftRetainOp;
@@ -736,7 +741,8 @@ class TagInfo : public CommonTypeInfo {
TagInfo()
: HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
- SwiftCopyable(false) {}
+ SwiftCopyable(false), SwiftEscapableSpecified(false),
+ SwiftEscapable(false) {}
std::optional<bool> isFlagEnum() const {
if (HasFlagEnum)
@@ -757,6 +763,16 @@ class TagInfo : public CommonTypeInfo {
SwiftCopyable = Value.value_or(false);
}
+ std::optional<bool> isSwiftEscapable() const {
+ return SwiftEscapableSpecified ? std::optional<bool>(SwiftEscapable)
+ : std::nullopt;
+ }
+
+ void setSwiftEscapable(std::optional<bool> Value) {
+ SwiftEscapableSpecified = Value.has_value();
+ SwiftEscapable = Value.value_or(false);
+ }
+
TagInfo &operator|=(const TagInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS;
@@ -779,6 +795,9 @@ class TagInfo : public CommonTypeInfo {
if (!SwiftCopyableSpecified)
setSwiftCopyable(RHS.isSwiftCopyable());
+ if (!SwiftEscapableSpecified)
+ setSwiftEscapable(RHS.isSwiftEscapable());
+
return *this;
}
@@ -795,6 +814,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
LHS.SwiftConformance == RHS.SwiftConformance &&
LHS.isFlagEnum() == RHS.isFlagEnum() &&
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
+ LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&
LHS.EnumExtensibility == RHS.EnumExtensibility;
}
diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h
index 4d1c698ae6310d..a03cef36294dbb 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -24,11 +24,10 @@ 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 =
- 32; // implicit parameter support (at position -1)
+const uint16_t VERSION_MINOR = 33; // SwiftEscapable
-const uint8_t kSwiftCopyable = 1;
-const uint8_t kSwiftNonCopyable = 2;
+const uint8_t kSwiftConforms = 1;
+const uint8_t kSwiftDoesNotConform = 2;
using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
using IdentifierIDField = llvm::BCVBR<16>;
diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp
index 0f8fa1355bfb0a..45a344c13f470e 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -589,10 +589,12 @@ class TagTableInfo
uint8_t Copyable =
endian::readNext<uint8_t, llvm::endianness::little>(Data);
- if (Copyable == kSwiftNonCopyable)
- Info.setSwiftCopyable(std::optional(false));
- else if (Copyable == kSwiftCopyable)
- Info.setSwiftCopyable(std::optional(true));
+ if (Copyable == kSwiftConforms || Copyable == kSwiftDoesNotConform)
+ Info.setSwiftCopyable(std::optional(Copyable == kSwiftConforms));
+ uint8_t Escapable =
+ endian::readNext<uint8_t, llvm::endianness::little>(Data);
+ if (Escapable == kSwiftConforms || Escapable == kSwiftDoesNotConform)
+ Info.setSwiftEscapable(std::optional(Escapable == kSwiftConforms));
unsigned ImportAsLength =
endian::readNext<uint16_t, llvm::endianness::little>(Data);
diff --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp
index b92faa0acc7482..d06277fa367274 100644
--- a/clang/lib/APINotes/APINotesTypes.cpp
+++ b/clang/lib/APINotes/APINotesTypes.cpp
@@ -104,6 +104,10 @@ LLVM_DUMP_METHOD void TagInfo::dump(llvm::raw_ostream &OS) {
if (EnumExtensibility)
OS << "Enum Extensibility: " << static_cast<long>(*EnumExtensibility)
<< ' ';
+ if (SwiftCopyableSpecified)
+ OS << (SwiftCopyable ? "[SwiftCopyable] " : "[~SwiftCopyable]");
+ if (SwiftEscapableSpecified)
+ OS << (SwiftEscapable ? "[SwiftEscapable] " : "[~SwiftEscapable]");
OS << '\n';
}
diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp
index 3b8b3c80f7c086..480e1190358d48 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -1266,11 +1266,13 @@ class CommonTypeTableInfo
class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
public:
unsigned getUnversionedInfoSize(const TagInfo &TI) {
+ // clang-format off
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
- 2 + getCommonTypeInfoSize(TI);
+ 3 + getCommonTypeInfoSize(TI);
+ // clang-format on
}
void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
@@ -1289,7 +1291,12 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
writer.write<uint8_t>(Flags);
if (auto Copyable = TI.isSwiftCopyable())
- writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
+ writer.write<uint8_t>(*Copyable ? kSwiftConforms : kSwiftDoesNotConform);
+ else
+ writer.write<uint8_t>(0);
+
+ if (auto Escapable = TI.isSwiftEscapable())
+ writer.write<uint8_t>(*Escapable ? kSwiftConforms : kSwiftDoesNotConform);
else
writer.write<uint8_t>(0);
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index e3cb2b3f573886..0668dda910f2a8 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -459,6 +459,7 @@ struct Tag {
std::optional<bool> FlagEnum;
std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
std::optional<bool> SwiftCopyable;
+ std::optional<bool> SwiftEscapable;
FunctionsSeq Methods;
FieldsSeq Fields;
@@ -498,6 +499,7 @@ template <> struct MappingTraits<Tag> {
IO.mapOptional("FlagEnum", T.FlagEnum);
IO.mapOptional("EnumKind", T.EnumConvenienceKind);
IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
+ IO.mapOptional("SwiftEscapable", T.SwiftEscapable);
IO.mapOptional("Methods", T.Methods);
IO.mapOptional("Fields", T.Fields);
IO.mapOptional("Tags", T.Tags);
@@ -983,6 +985,8 @@ class YAMLConverter {
if (T.SwiftCopyable)
TI.setSwiftCopyable(T.SwiftCopyable);
+ if (T.SwiftEscapable)
+ TI.setSwiftEscapable(T.SwiftEscapable);
if (T.EnumConvenienceKind) {
if (T.EnumExtensibility) {
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 5bb58d6c98be95..07d1326bf9a7c2 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -647,6 +647,11 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
}
+ if (auto Escapable = Info.isSwiftEscapable()) {
+ D->addAttr(SwiftAttrAttr::Create(S.Context,
+ *Escapable ? "Escapable" : "~Escapable"));
+ }
+
if (auto Extensibility = Info.EnumExtensibility) {
using api_notes::EnumExtensibilityKind;
bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
index f4f9c7a244e0a3..c5171e2f287d28 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
@@ -13,3 +13,7 @@ Tags:
SwiftConformsTo: MySwiftModule.MySwiftNonCopyableProtocol
- Name: CopyableType
SwiftCopyable: true
+- Name: NonEscapableType
+ SwiftEscapable: false
+- Name: EscapableType
+ SwiftEscapable: true
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
index a8f6d0248eae40..f205cd3c6e7b71 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
@@ -7,3 +7,6 @@ inline void RCRelease(RefCountedType *x) { x->value--; }
struct NonCopyableType { int value; };
struct CopyableType { int value; };
+
+struct NonEscapableType { int value; };
+struct EscapableType { int value; };
diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp
index 6457e1557618de..d0e7e31fc1d726 100644
--- a/clang/test/APINotes/swift-import-as.cpp
+++ b/clang/test/APINotes/swift-import-as.cpp
@@ -4,6 +4,8 @@
// 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 RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %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 NonCopyableType | FileCheck -check-prefix=CHECK-NON-COPYABLE %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 CopyableType | FileCheck -check-prefix=CHECK-COPYABLE %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 NonEscapableType | FileCheck -check-prefix=CHECK-NON-ESCAPABLE %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 EscapableType | FileCheck -check-prefix=CHECK-ESCAPABLE %s
#include <SwiftImportAs.h>
@@ -26,3 +28,11 @@
// CHECK-COPYABLE: Dumping CopyableType:
// CHECK-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct CopyableType
// CHECK-COPYABLE-NOT: SwiftAttrAttr
+
+// CHECK-NON-ESCAPABLE: Dumping NonEscapableType:
+// CHECK-NON-ESCAPABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonEscapableType
+// CHECK-NON-ESCAPABLE: SwiftAttrAttr {{.+}} "~Escapable"
+
+// CHECK-ESCAPABLE: Dumping EscapableType:
+// CHECK-ESCAPABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct EscapableType
+// CHECK-ESCAPABLE: SwiftAttrAttr {{.+}} "Escapable"
More information about the cfe-commits
mailing list