diff options
author | Egor Zhdan <e_zhdan@apple.com> | 2024-04-26 19:30:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-26 19:30:08 +0100 |
commit | b2098db2485331e01503e1452a7a60cd8c031a3f (patch) | |
tree | 696e57c487684031f900918bd79e949c72445002 /clang/lib/APINotes | |
parent | b27f86b40b20942c0e809128214b43d6edde365a (diff) | |
download | llvm-b2098db2485331e01503e1452a7a60cd8c031a3f.zip llvm-b2098db2485331e01503e1452a7a60cd8c031a3f.tar.gz llvm-b2098db2485331e01503e1452a7a60cd8c031a3f.tar.bz2 |
[APINotes] Allow annotating a C++ type as non-copyable in Swift
Certain C++ types, such as `std::chrono::tzdb` in libstdc++, are
non-copyable, but don't explicitly delete their copy constructor.
Instead, they trigger template instantiation errors when trying to call
their implicit copy constructor. The Swift compiler inserts implicit
copies of value types in some cases, which trigger compiler errors for
such types.
This adds a Clang API Notes attribute that allows annotating C++ types
as non-copyable in Swift. This lets the Swift compiler know that it
should not try to instantiate the implicit copy constructor for a C++
struct.
rdar://127049438
Diffstat (limited to 'clang/lib/APINotes')
-rw-r--r-- | clang/lib/APINotes/APINotesFormat.h | 5 | ||||
-rw-r--r-- | clang/lib/APINotes/APINotesReader.cpp | 7 | ||||
-rw-r--r-- | clang/lib/APINotes/APINotesWriter.cpp | 7 | ||||
-rw-r--r-- | clang/lib/APINotes/APINotesYAMLCompiler.cpp | 5 |
4 files changed, 22 insertions, 2 deletions
diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 615314c..97e630e 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,7 +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 = 25; // SwiftImportAs +const uint16_t VERSION_MINOR = 26; // SwiftCopyable + +const uint8_t kSwiftCopyable = 1; +const uint8_t kSwiftNonCopyable = 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 dfc3beb6..b60ca68 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -527,6 +527,13 @@ public: Info.EnumExtensibility = static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1); + 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)); + unsigned ImportAsLength = endian::readNext<uint16_t, llvm::endianness::little>(Data); if (ImportAsLength > 0) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index e3f5d10..3e61597 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1128,7 +1128,7 @@ public: return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + - 1 + getCommonTypeInfoSize(TI); + 2 + getCommonTypeInfoSize(TI); } void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) { @@ -1146,6 +1146,11 @@ public: writer.write<uint8_t>(Flags); + if (auto Copyable = TI.isSwiftCopyable()) + writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable); + else + writer.write<uint8_t>(0); + if (auto ImportAs = TI.SwiftImportAs) { writer.write<uint16_t>(ImportAs->size() + 1); OS.write(ImportAs->c_str(), ImportAs->size()); diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 57d6da7..2295d76 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -419,6 +419,7 @@ struct Tag { std::optional<EnumExtensibilityKind> EnumExtensibility; std::optional<bool> FlagEnum; std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; + std::optional<bool> SwiftCopyable; }; typedef std::vector<Tag> TagsSeq; @@ -452,6 +453,7 @@ template <> struct MappingTraits<Tag> { IO.mapOptional("EnumExtensibility", T.EnumExtensibility); IO.mapOptional("FlagEnum", T.FlagEnum); IO.mapOptional("EnumKind", T.EnumConvenienceKind); + IO.mapOptional("SwiftCopyable", T.SwiftCopyable); } }; } // namespace yaml @@ -1009,6 +1011,9 @@ public: if (Tag.SwiftReleaseOp) TI.SwiftReleaseOp = Tag.SwiftReleaseOp; + if (Tag.SwiftCopyable) + TI.setSwiftCopyable(Tag.SwiftCopyable); + if (Tag.EnumConvenienceKind) { if (Tag.EnumExtensibility) { emitError( |