[clang] [APINotes] Avoid repeated hash lookups (NFC) (PR #107959)
https://github.com/egorzhdan approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/107959 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/104088 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
@@ -793,6 +827,16 @@ class YAMLConverter { SwiftVersion); } + template + void convertVariable(const T &Entity, VariableInfo &VI) { egorzhdan wrote: The existing methods that do the same thing for classes, methods, etc. are called `convertX` without the `Info` suffix. I think it's better keep the naming consistent. https://github.com/llvm/llvm-project/pull/104088 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
@@ -858,6 +867,62 @@ void APINotesWriter::Implementation::writeCXXMethodBlock( } } +namespace { +/// Used to serialize the on-disk C field table. +class FieldTableInfo +: public VersionedTableInfo { +public: + unsigned getKeyLength(key_type_ref) { +return sizeof(uint32_t) + sizeof(uint32_t); + } + + void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { +llvm::support::endian::Writer writer(OS, llvm::endianness::little); +writer.write(Key.parentContextID); +writer.write(Key.nameID); + } + + hash_value_type ComputeHash(key_type_ref key) { +return static_cast(key.hashValue()); + } + + unsigned getUnversionedInfoSize(const FieldInfo &FI) { +return getVariableInfoSize(FI); + } + + void emitUnversionedInfo(raw_ostream &OS, const FieldInfo &FI) { +emitVariableInfo(OS, FI); + } +}; +} // namespace + +void APINotesWriter::Implementation::writeFieldBlock( +llvm::BitstreamWriter &Stream) { + llvm::BCBlockRAII Scope(Stream, FIELD_BLOCK_ID, 3); + + if (Fields.empty()) +return; + + { +llvm::SmallString<4096> HashTableBlob; +uint32_t Offset; +{ + llvm::OnDiskChainedHashTableGenerator Generator; + for (auto &MD : Fields) egorzhdan wrote: Fixed https://github.com/llvm/llvm-project/pull/104088 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
@@ -1252,6 +1282,81 @@ bool APINotesReader::Implementation::readCXXMethodBlock( return false; } +bool APINotesReader::Implementation::readFieldBlock( +llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl &Scratch) { + if (Cursor.EnterSubBlock(FIELD_BLOCK_ID)) +return true; + + llvm::Expected MaybeNext = Cursor.advance(); + if (!MaybeNext) { +// FIXME this drops the error on the floor. +consumeError(MaybeNext.takeError()); +return false; + } + llvm::BitstreamEntry Next = MaybeNext.get(); + while (Next.Kind != llvm::BitstreamEntry::EndBlock) { +if (Next.Kind == llvm::BitstreamEntry::Error) + return true; + +if (Next.Kind == llvm::BitstreamEntry::SubBlock) { + // Unknown sub-block, possibly for use by a future version of the + // API notes format. + if (Cursor.SkipBlock()) +return true; + + MaybeNext = Cursor.advance(); + if (!MaybeNext) { +// FIXME this drops the error on the floor. +consumeError(MaybeNext.takeError()); +return false; + } + Next = MaybeNext.get(); + continue; +} + +Scratch.clear(); +llvm::StringRef BlobData; +llvm::Expected MaybeKind = +Cursor.readRecord(Next.ID, Scratch, &BlobData); +if (!MaybeKind) { + // FIXME this drops the error on the floor. + consumeError(MaybeKind.takeError()); + return false; +} +unsigned Kind = MaybeKind.get(); +switch (Kind) { +case field_block::FIELD_DATA: { + // Already saw C++ method table. egorzhdan wrote: Oops, that's a copy-and-paste typo, fixed. https://github.com/llvm/llvm-project/pull/104088 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/104088 >From 1f41cef4dfbf19517c67586945ad9885f48a7150 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 14 Aug 2024 18:37:25 +0100 Subject: [PATCH] [APINotes] Support fields of C/C++ structs This allows annotating fields of C/C++ structs using API Notes. Previously API Notes supported Objective-C properties, but not fields. rdar://131548377 --- clang/include/clang/APINotes/APINotesReader.h | 7 + clang/include/clang/APINotes/APINotesWriter.h | 8 ++ clang/include/clang/APINotes/Types.h | 6 + clang/lib/APINotes/APINotesFormat.h | 20 ++- clang/lib/APINotes/APINotesReader.cpp | 130 ++ clang/lib/APINotes/APINotesWriter.cpp | 73 ++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 64 +++-- clang/lib/Sema/SemaAPINotes.cpp | 20 +++ .../APINotes/Inputs/Headers/Fields.apinotes | 23 clang/test/APINotes/Inputs/Headers/Fields.h | 21 +++ .../APINotes/Inputs/Headers/module.modulemap | 5 + clang/test/APINotes/fields.cpp| 17 +++ 12 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.h create mode 100644 clang/test/APINotes/fields.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 03657352c49a59..baf63340640242 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,13 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given field of a C struct. + /// + /// \param Name The name of the field. + /// + /// \returns information about the field, if known. + VersionedInfo lookupField(ContextID CtxID, llvm::StringRef Name); + /// Look for information regarding the given C++ method in the given C++ tag /// context. /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e0fe5eacef7258..3cc16c3d959faf 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -86,6 +86,14 @@ class APINotesWriter { void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C record field. + /// + /// \param CtxID The context in which this field resides, i.e. a C/C++ tag. + /// \param Name The name of the field. + /// \param Info Information about this field. + void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, +llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index f972d0cf26640d..89889910d1a073 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C/C++ record field. +class FieldInfo : public VariableInfo { +public: + FieldInfo() {} +}; + /// Describes API notes data for a C++ method. class CXXMethodInfo : public FunctionInfo { public: diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index fba5f4e8907dae..d724a9ea471b54 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 = 29; // SwiftConformsTo +const uint16_t VERSION_MINOR = 30; // fields const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -72,6 +72,10 @@ enum BlockID { /// used in other tables. OBJC_SELECTOR_BLOCK_ID, + /// The fields data block, which maps names fields of C records to + /// information about the field. + FIELD_BLOCK_ID, + /// The global variables data block, which maps global variable names to /// information about the global variable. GLOBAL_VARIABLE_BLOCK_ID, @@ -199,6 +203,20 @@ using CXXMethodDataLayout = >; } // namespace cxx_method_block +namespace field_block { +enum { + FIELD_DATA = 1, +}; + +using FieldDataLayout = +llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from C (context id, name) +
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/104088 >From 3e4c23b5cdfba147bf6598822ca4d9174c984a05 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 14 Aug 2024 18:37:25 +0100 Subject: [PATCH] [APINotes] Support fields of C/C++ structs This allows annotating fields of C/C++ structs using API Notes. Previously API Notes supported Objective-C properties, but not fields. rdar://131548377 --- clang/include/clang/APINotes/APINotesReader.h | 7 + clang/include/clang/APINotes/APINotesWriter.h | 8 ++ clang/include/clang/APINotes/Types.h | 6 + clang/lib/APINotes/APINotesFormat.h | 20 ++- clang/lib/APINotes/APINotesReader.cpp | 130 ++ clang/lib/APINotes/APINotesWriter.cpp | 73 ++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 64 +++-- clang/lib/Sema/SemaAPINotes.cpp | 20 +++ .../APINotes/Inputs/Headers/Fields.apinotes | 23 clang/test/APINotes/Inputs/Headers/Fields.h | 21 +++ .../APINotes/Inputs/Headers/module.modulemap | 5 + clang/test/APINotes/fields.cpp| 17 +++ 12 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.h create mode 100644 clang/test/APINotes/fields.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 03657352c49a59..baf63340640242 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,13 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given field of a C struct. + /// + /// \param Name The name of the field. + /// + /// \returns information about the field, if known. + VersionedInfo lookupField(ContextID CtxID, llvm::StringRef Name); + /// Look for information regarding the given C++ method in the given C++ tag /// context. /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e0fe5eacef7258..3cc16c3d959faf 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -86,6 +86,14 @@ class APINotesWriter { void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C record field. + /// + /// \param CtxID The context in which this field resides, i.e. a C/C++ tag. + /// \param Name The name of the field. + /// \param Info Information about this field. + void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, +llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index f972d0cf26640d..89889910d1a073 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C/C++ record field. +class FieldInfo : public VariableInfo { +public: + FieldInfo() {} +}; + /// Describes API notes data for a C++ method. class CXXMethodInfo : public FunctionInfo { public: diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index fba5f4e8907dae..d724a9ea471b54 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 = 29; // SwiftConformsTo +const uint16_t VERSION_MINOR = 30; // fields const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -72,6 +72,10 @@ enum BlockID { /// used in other tables. OBJC_SELECTOR_BLOCK_ID, + /// The fields data block, which maps names fields of C records to + /// information about the field. + FIELD_BLOCK_ID, + /// The global variables data block, which maps global variable names to /// information about the global variable. GLOBAL_VARIABLE_BLOCK_ID, @@ -199,6 +203,20 @@ using CXXMethodDataLayout = >; } // namespace cxx_method_block +namespace field_block { +enum { + FIELD_DATA = 1, +}; + +using FieldDataLayout = +llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from C (context id, name) +
[clang] [APINotes] Support fields of C/C++ structs (PR #104088)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/104088 This allows annotating fields of C/C++ structs using API Notes. Previously API Notes supported Objective-C properties, but not fields. rdar://131548377 >From cefe51c59177d4c69a1d556408e6a69301c07326 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 14 Aug 2024 18:37:25 +0100 Subject: [PATCH] [APINotes] Support fields of C/C++ structs This allows annotating fields of C/C++ structs using API Notes. Previously API Notes supported Objective-C properties, but not fields. rdar://131548377 --- clang/include/clang/APINotes/APINotesReader.h | 7 + clang/include/clang/APINotes/APINotesWriter.h | 8 ++ clang/include/clang/APINotes/Types.h | 6 + clang/lib/APINotes/APINotesFormat.h | 20 ++- clang/lib/APINotes/APINotesReader.cpp | 130 ++ clang/lib/APINotes/APINotesWriter.cpp | 73 ++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 64 +++-- clang/lib/Sema/SemaAPINotes.cpp | 20 +++ .../APINotes/Inputs/Headers/Fields.apinotes | 23 clang/test/APINotes/Inputs/Headers/Fields.h | 21 +++ .../APINotes/Inputs/Headers/module.modulemap | 5 + clang/test/APINotes/fields.cpp| 17 +++ 12 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Fields.h create mode 100644 clang/test/APINotes/fields.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 03657352c49a59..baf63340640242 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,13 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given field of a C struct. + /// + /// \param Name The name of the field. + /// + /// \returns information about the field, if known. + VersionedInfo lookupField(ContextID CtxID, llvm::StringRef Name); + /// Look for information regarding the given C++ method in the given C++ tag /// context. /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e0fe5eacef7258..3cc16c3d959faf 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -86,6 +86,14 @@ class APINotesWriter { void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C record field. + /// + /// \param CtxID The context in which this field resides, i.e. a C/C++ tag. + /// \param Name The name of the field. + /// \param Info Information about this field. + void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, +llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index f972d0cf26640d..89889910d1a073 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C/C++ record field. +class FieldInfo : public VariableInfo { +public: + FieldInfo() {} +}; + /// Describes API notes data for a C++ method. class CXXMethodInfo : public FunctionInfo { public: diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index fba5f4e8907dae..d724a9ea471b54 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 = 29; // SwiftConformsTo +const uint16_t VERSION_MINOR = 30; // fields const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -72,6 +72,10 @@ enum BlockID { /// used in other tables. OBJC_SELECTOR_BLOCK_ID, + /// The fields data block, which maps names fields of C records to + /// information about the field. + FIELD_BLOCK_ID, + /// The global variables data block, which maps global variable names to /// information about the global variable. GLOBAL_VARIABLE_BLOCK_ID, @@ -199,6 +203,20 @@ using CXXMethodDataLayout = >; } // namespace cxx_method_block +namespace field_block { +enum { + FIELD_DATA = 1, +}; + +using FieldDataLayout = +llvm::BCRecordLayout, // table offset within t
[clang] [APINotes] Support C++ tag conformances to Swift protocols (PR #102664)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/102664 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support C++ tag conformances to Swift protocols (PR #102664)
@@ -1230,6 +1231,12 @@ class TagTableInfo : public CommonTypeTableInfo { } else { writer.write(0); } +if (auto ConformsTo = TI.SwiftConformsTo) { + writer.write(ConformsTo->size() + 1); + OS.write(ConformsTo->c_str(), ConformsTo->size()); egorzhdan wrote: Alright, renamed this. https://github.com/llvm/llvm-project/pull/102664 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support C++ tag conformances to Swift protocols (PR #102664)
@@ -572,6 +572,13 @@ class TagTableInfo ReleaseOpLength - 1); Data += ReleaseOpLength - 1; } +unsigned ConformsToLength = +endian::readNext(Data); +if (ConformsToLength > 0) { egorzhdan wrote: Done! Applied this change https://github.com/llvm/llvm-project/pull/102664 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support C++ tag conformances to Swift protocols (PR #102664)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/102664 >From 4735b4c7bad13dee4bbeb819aba8ac555f842322 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 9 Aug 2024 20:08:43 +0100 Subject: [PATCH] [APINotes] Support C++ tag conformances to Swift protocols This allows adding a Clang attribute `swift_attr("conforms_to:ModuleName.ProtocolName")` to C++ structs via API Notes. The Swift compiler respects this attribute when importing C++ types into Swift by automatically declaring the C++ type as a conforming type to the given Swift protocol. rdar://131388824 --- clang/docs/APINotes.rst | 12 clang/include/clang/APINotes/Types.h | 7 +++ clang/lib/APINotes/APINotesFormat.h | 2 +- clang/lib/APINotes/APINotesReader.cpp| 6 ++ clang/lib/APINotes/APINotesWriter.cpp| 7 +++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 4 clang/lib/Sema/SemaAPINotes.cpp | 4 .../APINotes/Inputs/Headers/SwiftImportAs.apinotes | 2 ++ clang/test/APINotes/swift-import-as.cpp | 2 ++ 9 files changed, 45 insertions(+), 1 deletion(-) diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index bc09b16bab5d27..dcefa6810dac67 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -188,6 +188,18 @@ declaration kind), all of which are optional: - Name: tzdb SwiftCopyable: false +:SwiftConformsTo: + + Allows annotating a C++ class as conforming to a Swift protocol. Equivalent + to ``SWIFT_CONFORMS_TO_PROTOCOL``. The value is a module-qualified name of a + Swift protocol. + + :: + +Tags: +- Name: vector + SwiftConformsTo: Cxx.CxxSequence + :Availability, AvailabilityMsg: A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index c8e5e4df25d173..f972d0cf26640d 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -685,6 +685,9 @@ class TagInfo : public CommonTypeInfo { std::optional SwiftRetainOp; std::optional SwiftReleaseOp; + /// The Swift protocol that this type should be automatically conformed to. + std::optional SwiftConformance; + std::optional EnumExtensibility; TagInfo() @@ -720,6 +723,9 @@ class TagInfo : public CommonTypeInfo { if (!SwiftReleaseOp) SwiftReleaseOp = RHS.SwiftReleaseOp; +if (!SwiftConformance) + SwiftConformance = RHS.SwiftConformance; + if (!HasFlagEnum) setFlagEnum(RHS.isFlagEnum()); @@ -742,6 +748,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftImportAs == RHS.SwiftImportAs && LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && + LHS.SwiftConformance == RHS.SwiftConformance && LHS.isFlagEnum() == RHS.isFlagEnum() && LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 9d254dcc1c9eff..fba5f4e8907dae 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 = 28; // nested tags +const uint16_t VERSION_MINOR = 29; // SwiftConformsTo const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 871f782511d5f1..c05fdffe4a071b 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -572,6 +572,12 @@ class TagTableInfo ReleaseOpLength - 1); Data += ReleaseOpLength - 1; } +if (unsigned ConformanceLength = +endian::readNext(Data)) { + Info.SwiftConformance = std::string(reinterpret_cast(Data), + ConformanceLength - 1); + Data += ConformanceLength - 1; +} ReadCommonTypeInfo(Data, Info); return Info; diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 2a71922746ac5d..cf3a0bee393eee 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1189,6 +1189,7 @@ class TagTableInfo : public CommonTypeTableInfo { 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->s
[clang] [APINotes] Support C++ tag conformances to Swift protocols (PR #102664)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/102664 This allows adding a Clang attribute `swift_attr("conforms_to:ModuleName.ProtocolName")` to C++ structs via API Notes. The Swift compiler respects this attribute when importing C++ types into Swift by automatically declaring the C++ type as a conforming type to the given Swift protocol. rdar://131388824 >From 32d62daa94c30b1ddf95fc78e48866c8d4633bbb Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 9 Aug 2024 20:08:43 +0100 Subject: [PATCH] [APINotes] Support C++ tag conformances to Swift protocols This allows adding a Clang attribute `swift_attr("conforms_to:ModuleName.ProtocolName")` to C++ structs via API Notes. The Swift compiler respects this attribute when importing C++ types into Swift by automatically declaring the C++ type as a conforming type to the given Swift protocol. rdar://131388824 --- clang/docs/APINotes.rst | 12 clang/include/clang/APINotes/Types.h | 6 ++ clang/lib/APINotes/APINotesFormat.h | 2 +- clang/lib/APINotes/APINotesReader.cpp| 7 +++ clang/lib/APINotes/APINotesWriter.cpp| 7 +++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 4 clang/lib/Sema/SemaAPINotes.cpp | 4 .../APINotes/Inputs/Headers/SwiftImportAs.apinotes | 2 ++ clang/test/APINotes/swift-import-as.cpp | 2 ++ 9 files changed, 45 insertions(+), 1 deletion(-) diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index bc09b16bab5d27..dcefa6810dac67 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -188,6 +188,18 @@ declaration kind), all of which are optional: - Name: tzdb SwiftCopyable: false +:SwiftConformsTo: + + Allows annotating a C++ class as conforming to a Swift protocol. Equivalent + to ``SWIFT_CONFORMS_TO_PROTOCOL``. The value is a module-qualified name of a + Swift protocol. + + :: + +Tags: +- Name: vector + SwiftConformsTo: Cxx.CxxSequence + :Availability, AvailabilityMsg: A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index c8e5e4df25d173..dc725fbe867b90 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -685,6 +685,8 @@ class TagInfo : public CommonTypeInfo { std::optional SwiftRetainOp; std::optional SwiftReleaseOp; + std::optional SwiftConformsTo; + std::optional EnumExtensibility; TagInfo() @@ -720,6 +722,9 @@ class TagInfo : public CommonTypeInfo { if (!SwiftReleaseOp) SwiftReleaseOp = RHS.SwiftReleaseOp; +if (!SwiftConformsTo) + SwiftConformsTo = RHS.SwiftConformsTo; + if (!HasFlagEnum) setFlagEnum(RHS.isFlagEnum()); @@ -742,6 +747,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftImportAs == RHS.SwiftImportAs && LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && + LHS.SwiftConformsTo == RHS.SwiftConformsTo && LHS.isFlagEnum() == RHS.isFlagEnum() && LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 9d254dcc1c9eff..fba5f4e8907dae 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 = 28; // nested tags +const uint16_t VERSION_MINOR = 29; // SwiftConformsTo const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 871f782511d5f1..0a0c249b860c71 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -572,6 +572,13 @@ class TagTableInfo ReleaseOpLength - 1); Data += ReleaseOpLength - 1; } +unsigned ConformsToLength = +endian::readNext(Data); +if (ConformsToLength > 0) { + Info.SwiftConformsTo = std::string(reinterpret_cast(Data), + ConformsToLength - 1); + Data += ConformsToLength - 1; +} ReadCommonTypeInfo(Data, Info); return Info; diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 2a71922746ac5d..d81bfd9f61759c 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1189,6 +1189,7 @@ class TagTableInfo : public CommonTypeTableInfo { return 2 + (TI.Sw
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/101001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
@@ -1044,11 +1044,13 @@ void Sema::ProcessAPINotes(Decl *D) { if (auto TagContext = dyn_cast(D->getDeclContext())) { if (auto CXXMethod = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { -if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); - ProcessVersionedAPINotes(*this, CXXMethod, Info); + if (CXXMethod->getIdentifier()) { egorzhdan wrote: Alright, I replaced this with an explicit check for operators, constructors and destructors. https://github.com/llvm/llvm-project/pull/101001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/101001 >From 63e76d8e6576f651b7a2aa6358444e82e8a1b662 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 29 Jul 2024 13:01:18 +0100 Subject: [PATCH] [APINotes] Do not crash for C++ operators This fixes a crash during `CXXMethod->getName()` in `Sema::ProcessAPINotes`: we were trying to get the name of a C++ method as a string, which fails with an assertion if the name is not a simple identifier. --- clang/lib/Sema/SemaAPINotes.cpp | 15 ++- clang/test/APINotes/Inputs/Headers/Methods.h | 6 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index be5b7b92dfe6f..2c49c1f64b2da 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -1044,11 +1044,16 @@ void Sema::ProcessAPINotes(Decl *D) { if (auto TagContext = dyn_cast(D->getDeclContext())) { if (auto CXXMethod = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { -if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); - ProcessVersionedAPINotes(*this, CXXMethod, Info); + if (!isa(CXXMethod) && + !isa(CXXMethod) && + !isa(CXXMethod) && + !CXXMethod->isOverloadedOperator()) { +for (auto Reader : APINotes.findAPINotes(D->getLocation())) { + if (auto Context = UnwindTagContext(TagContext, APINotes)) { +auto Info = +Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); +ProcessVersionedAPINotes(*this, CXXMethod, Info); + } } } } diff --git a/clang/test/APINotes/Inputs/Headers/Methods.h b/clang/test/APINotes/Inputs/Headers/Methods.h index 6a96b12762871..cbb57ccd0afbd 100644 --- a/clang/test/APINotes/Inputs/Headers/Methods.h +++ b/clang/test/APINotes/Inputs/Headers/Methods.h @@ -2,6 +2,8 @@ struct IntWrapper { int value; IntWrapper getIncremented() const { return {value + 1}; } + + IntWrapper operator+(const IntWrapper& RHS) const { return {value + RHS.value}; } }; struct Outer { @@ -9,5 +11,9 @@ struct Outer { int value; Inner getDecremented() const { return {value - 1}; } + +bool operator==(const Inner& RHS) const { + return value == RHS.value; +} }; }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
@@ -1044,11 +1044,13 @@ void Sema::ProcessAPINotes(Decl *D) { if (auto TagContext = dyn_cast(D->getDeclContext())) { if (auto CXXMethod = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { -if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); - ProcessVersionedAPINotes(*this, CXXMethod, Info); + if (CXXMethod->getIdentifier()) { egorzhdan wrote: Operators are one of the cases where `->getName()` would fail with an assertion. Other cases are destructors, constructors. https://github.com/llvm/llvm-project/pull/101001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
@@ -1044,11 +1044,13 @@ void Sema::ProcessAPINotes(Decl *D) { if (auto TagContext = dyn_cast(D->getDeclContext())) { if (auto CXXMethod = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { -if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); - ProcessVersionedAPINotes(*this, CXXMethod, Info); + if (CXXMethod->getIdentifier()) { egorzhdan wrote: `clang::CXXMethodDecl`s are always NamedDecls, right? But not all of them actually have a name that is convertible to a string. https://github.com/llvm/llvm-project/pull/101001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Do not crash for C++ operators (PR #101001)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/101001 This fixes a crash during `CXXMethod->getName()` in `Sema::ProcessAPINotes`: we were trying to get the name of a C++ method as a string, which fails with an assertion if the name is not a simple identifier. >From 0993d9e4b1161b3ec38309f2b1f00d61da034006 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 29 Jul 2024 13:01:18 +0100 Subject: [PATCH] [APINotes] Do not crash for C++ operators This fixes a crash during `CXXMethod->getName()` in `Sema::ProcessAPINotes`: we were trying to get the name of a C++ method as a string, which fails with an assertion if the name is not a simple identifier. --- clang/lib/Sema/SemaAPINotes.cpp | 12 +++- clang/test/APINotes/Inputs/Headers/Methods.h | 6 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index be5b7b92dfe6f..2350cbc0f420f 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -1044,11 +1044,13 @@ void Sema::ProcessAPINotes(Decl *D) { if (auto TagContext = dyn_cast(D->getDeclContext())) { if (auto CXXMethod = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { -if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); - ProcessVersionedAPINotes(*this, CXXMethod, Info); + if (CXXMethod->getIdentifier()) { +for (auto Reader : APINotes.findAPINotes(D->getLocation())) { + if (auto Context = UnwindTagContext(TagContext, APINotes)) { +auto Info = +Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); +ProcessVersionedAPINotes(*this, CXXMethod, Info); + } } } } diff --git a/clang/test/APINotes/Inputs/Headers/Methods.h b/clang/test/APINotes/Inputs/Headers/Methods.h index 6a96b12762871..cbb57ccd0afbd 100644 --- a/clang/test/APINotes/Inputs/Headers/Methods.h +++ b/clang/test/APINotes/Inputs/Headers/Methods.h @@ -2,6 +2,8 @@ struct IntWrapper { int value; IntWrapper getIncremented() const { return {value + 1}; } + + IntWrapper operator+(const IntWrapper& RHS) const { return {value + RHS.value}; } }; struct Outer { @@ -9,5 +11,9 @@ struct Outer { int value; Inner getDecremented() const { return {value - 1}; } + +bool operator==(const Inner& RHS) const { + return value == RHS.value; +} }; }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -783,51 +783,76 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto CurrentTag = DC; CurrentTag; + CurrentTag = dyn_cast(CurrentTag->getParent())) +TagStack.push(CurrentTag); +} +assert(!TagStack.empty()); egorzhdan wrote: Yeah, that makes sense. I added another assertion that ensures `DC` is not null. I would prefer to keep this assertion in place, since I think C++ container access without bounds check tends to make people nervous in non-hardened environments. > You can also remove the assertion by taking a reference to the DC. I thought the implicit convention of the codebase is that `clang::ABCDecl` are passed by pointer, not by reference. I could be wrong. But I think it's better to be consistent with the surrounding code. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -456,6 +458,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); egorzhdan wrote: Yeap, I added a comment to clarify that. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/99655 >From f1e3a236ca5dbc64913b0d44bdf92a30d38b8277 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 19 Jul 2024 15:24:10 +0100 Subject: [PATCH] [APINotes] Support nested tags This allows annotating C/C++ structs declared within other structs using API Notes. rdar://132083354 --- clang/lib/APINotes/APINotesFormat.h | 2 +- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 15 ++- clang/lib/Sema/SemaAPINotes.cpp | 119 +++--- .../APINotes/Inputs/Headers/Methods.apinotes | 24 clang/test/APINotes/Inputs/Headers/Methods.h | 1 - .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 3 + clang/test/APINotes/methods.cpp | 8 ++ clang/test/APINotes/namespaces.cpp| 5 + 9 files changed, 131 insertions(+), 49 deletions(-) diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index cd6456dbe37b2..9d254dcc1c9ef 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 = 27; // SingleDeclTableKey +const uint16_t VERSION_MINOR = 28; // nested tags const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 060e1fdaf2fd9..1194a15f0 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -406,6 +406,9 @@ template <> struct ScalarEnumerationTraits { } // namespace llvm namespace { +struct Tag; +typedef std::vector TagsSeq; + struct Tag { StringRef Name; AvailabilityItem Availability; @@ -421,9 +424,11 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; -}; -typedef std::vector TagsSeq; + /// Tags that are declared within the current tag. Only the tags that have + /// corresponding API Notes will be listed. + TagsSeq Tags; +}; } // namespace LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) @@ -456,6 +461,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); } }; } // namespace yaml @@ -958,12 +964,17 @@ class YAMLConverter { ContextInfo CI; auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, CI, SwiftVersion); +Context TagCtx(TagCtxID, ContextKind::Tag); for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); } + +// Convert nested tags. +for (const auto &Tag : T.Tags) + convertTagContext(TagCtx, Tag, SwiftVersion); } void convertTopLevelItems(std::optional Ctx, diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 055e66a0c3486..be5b7b92dfe6f 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -783,51 +783,77 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + assert(DC && "tag context must not be null"); + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto Current
[clang] [APINotes] Support nested tags (PR #99655)
@@ -783,51 +783,76 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto CurrentTag = DC; CurrentTag; + CurrentTag = dyn_cast(CurrentTag->getParent())) +TagStack.push(CurrentTag); +} +assert(!TagStack.empty()); egorzhdan wrote: Hmm, the reason I added the assertion here is because we're calling `TagStack.top()->...` on the following line, and I wanted to make it clear to the reader that this is access is never going to be out of bounds. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -456,6 +458,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); egorzhdan wrote: It's just the tags that have associated attributes. It's similar to how Obj-C methods and properties are stored in `struct Class` above. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -783,51 +783,76 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto CurrentTag = DC; CurrentTag; + CurrentTag = dyn_cast(CurrentTag->getParent())) +TagStack.push(CurrentTag); +} +assert(!TagStack.empty()); egorzhdan wrote: Not sure I follow: a tag might be a top-level entity, if its context is the translation unit. It isn't necessarily nested in a C++ namespace. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -421,9 +424,8 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; + TagsSeq Tags; egorzhdan wrote: These are, in fact, child tags – I can add a comment here describing the meaning of this field. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -958,12 +961,18 @@ class YAMLConverter { ContextInfo CI; auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, CI, SwiftVersion); +Context TagCtx(TagCtxID, ContextKind::Tag); for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); } + +// Convert nested tags. +for (const auto &Tag : T.Tags) { + convertTagContext(TagCtx, Tag, SwiftVersion); +} egorzhdan wrote: Fixed https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
@@ -899,6 +924,10 @@ void Sema::ProcessAPINotes(Decl *D) { } for (auto Reader : APINotes.findAPINotes(D->getLocation())) { +if (Tag->getName() == "inner_char_box") + llvm::errs(); egorzhdan wrote: My bad! Removed this. https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/99655 >From 824de086ec1e3208fce111a3cfacc971dc032b60 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 19 Jul 2024 15:24:10 +0100 Subject: [PATCH] [APINotes] Support nested tags This allows annotating C/C++ structs declared within other structs using API Notes. rdar://132083354 --- clang/lib/APINotes/APINotesFormat.h | 2 +- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 12 +- clang/lib/Sema/SemaAPINotes.cpp | 118 +++--- .../APINotes/Inputs/Headers/Methods.apinotes | 24 clang/test/APINotes/Inputs/Headers/Methods.h | 1 - .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 3 + clang/test/APINotes/methods.cpp | 8 ++ clang/test/APINotes/namespaces.cpp| 5 + 9 files changed, 127 insertions(+), 49 deletions(-) diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index cd6456dbe37b2..9d254dcc1c9ef 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 = 27; // SingleDeclTableKey +const uint16_t VERSION_MINOR = 28; // nested tags const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 060e1fdaf2fd9..2d34ec8febcfa 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -406,6 +406,9 @@ template <> struct ScalarEnumerationTraits { } // namespace llvm namespace { +struct Tag; +typedef std::vector TagsSeq; + struct Tag { StringRef Name; AvailabilityItem Availability; @@ -421,9 +424,8 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; + TagsSeq Tags; }; - -typedef std::vector TagsSeq; } // namespace LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) @@ -456,6 +458,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); } }; } // namespace yaml @@ -958,12 +961,17 @@ class YAMLConverter { ContextInfo CI; auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, CI, SwiftVersion); +Context TagCtx(TagCtxID, ContextKind::Tag); for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); } + +// Convert nested tags. +for (const auto &Tag : T.Tags) + convertTagContext(TagCtx, Tag, SwiftVersion); } void convertTopLevelItems(std::optional Ctx, diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 055e66a0c3486..f3452d86e63bb 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -783,51 +783,76 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto CurrentTag = DC; CurrentTag; + CurrentTag = dyn_cast(CurrentTag->getParent())) +TagStack.push(CurrentTag); +} +assert(!TagStack.empty()); +std::optional Ctx
[clang] [APINotes] Support nested tags (PR #99655)
@@ -456,6 +458,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); egorzhdan wrote: There are actually child tags, in the sense of tags declared within other tags, e.g. ```cpp struct Outer { struct Inner { }; }; ``` https://github.com/llvm/llvm-project/pull/99655 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support nested tags (PR #99655)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/99655 This allows annotating C/C++ structs declared within other structs using API Notes. rdar://132083354 >From 8ee14d729d996a9414438a64ecc789082c421bd0 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 19 Jul 2024 15:24:10 +0100 Subject: [PATCH] [APINotes] Support nested tags This allows annotating C/C++ structs declared within other structs using API Notes. rdar://132083354 --- clang/lib/APINotes/APINotesFormat.h | 2 +- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 13 +- clang/lib/Sema/SemaAPINotes.cpp | 120 +++--- .../APINotes/Inputs/Headers/Methods.apinotes | 24 clang/test/APINotes/Inputs/Headers/Methods.h | 1 - .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 3 + clang/test/APINotes/methods.cpp | 8 ++ clang/test/APINotes/namespaces.cpp| 5 + 9 files changed, 130 insertions(+), 49 deletions(-) diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index cd6456dbe37b2..9d254dcc1c9ef 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 = 27; // SingleDeclTableKey +const uint16_t VERSION_MINOR = 28; // nested tags const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 060e1fdaf2fd9..a87e49be83cef 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -406,6 +406,9 @@ template <> struct ScalarEnumerationTraits { } // namespace llvm namespace { +struct Tag; +typedef std::vector TagsSeq; + struct Tag { StringRef Name; AvailabilityItem Availability; @@ -421,9 +424,8 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; + TagsSeq Tags; }; - -typedef std::vector TagsSeq; } // namespace LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) @@ -456,6 +458,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); +IO.mapOptional("Tags", T.Tags); } }; } // namespace yaml @@ -958,12 +961,18 @@ class YAMLConverter { ContextInfo CI; auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, CI, SwiftVersion); +Context TagCtx(TagCtxID, ContextKind::Tag); for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); } + +// Convert nested tags. +for (const auto &Tag : T.Tags) { + convertTagContext(TagCtx, Tag, SwiftVersion); +} } void convertTopLevelItems(std::optional Ctx, diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 055e66a0c3486..92ccbde9b4d35 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -783,51 +783,76 @@ static void ProcessVersionedAPINotes( } } +static std::optional +UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { + if (auto NamespaceContext = dyn_cast(DC)) { +for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { +for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) +NamespaceStack.push(CurrentNamespace); +} + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { +auto CurrentNamespace = NamespaceStack.top(); +NamespaceStack.pop(); +NamespaceID = +Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); +if (!NamespaceID) + return std::nullopt; + } + if (NamespaceID) +return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); +} + } + return std::nullopt; +} + +static std::optional +UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { + for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { +// Retrieve the context ID for the parent tag of the decl. +std::stack TagStack; +{ + for (auto CurrentTag = DC; CurrentTag; + CurrentTag = dyn_cast(CurrentTag-
[clang] [APINotes] Support annotating C++ methods (PR #99512)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/99512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support annotating C++ methods (PR #99512)
@@ -794,6 +831,33 @@ void APINotesWriter::Implementation::writeObjCMethodBlock( } } +void APINotesWriter::Implementation::writeCXXMethodBlock( +llvm::BitstreamWriter &Stream) { + llvm::BCBlockRAII Scope(Stream, CXX_METHOD_BLOCK_ID, 3); + + if (CXXMethods.empty()) +return; + + { +llvm::SmallString<4096> HashTableBlob; +uint32_t Offset; +{ + llvm::OnDiskChainedHashTableGenerator Generator; + for (auto &OM : CXXMethods) egorzhdan wrote: Ah that makes sense, thanks 🙂 Fixed https://github.com/llvm/llvm-project/pull/99512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Support annotating C++ methods (PR #99512)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/99512 >From 117596b16e143e44c2b6c17184840490490e16a7 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 18 Jul 2024 15:49:24 +0100 Subject: [PATCH] [APINotes] Support annotating C++ methods This adds support for adding Clang attributes to C++ methods declared within C++ records by using API Notes. For instance: ``` Tags: - Name: IntWrapper Methods: - Name: getIncremented Availability: none ``` This is the first instance of something within a C++ record being annotated with API Notes, so it adds the necessary infra to make a C++ record an "API Notes context". Notably this does not add support for nested C++ tags. That will be added in a follow-up patch. rdar://131387880 --- clang/include/clang/APINotes/APINotesReader.h | 21 +++ clang/include/clang/APINotes/APINotesWriter.h | 8 + clang/include/clang/APINotes/Types.h | 7 + clang/lib/APINotes/APINotesFormat.h | 29 clang/lib/APINotes/APINotesReader.cpp | 149 clang/lib/APINotes/APINotesWriter.cpp | 72 clang/lib/APINotes/APINotesYAMLCompiler.cpp | 164 ++ clang/lib/Sema/SemaAPINotes.cpp | 50 +- .../APINotes/Inputs/Headers/Methods.apinotes | 8 + clang/test/APINotes/Inputs/Headers/Methods.h | 14 ++ .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 1 + .../APINotes/Inputs/Headers/module.modulemap | 4 + clang/test/APINotes/methods.cpp | 9 + clang/test/APINotes/namespaces.cpp| 5 + 15 files changed, 465 insertions(+), 79 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.h create mode 100644 clang/test/APINotes/methods.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 37a4ff7a69712..03657352c49a5 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,16 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given C++ method in the given C++ tag + /// context. + /// + /// \param CtxID The ID that references the parent context, i.e. a C++ tag. + /// \param Name The name of the C++ method we're looking for. + /// + /// \returns Information about the method, if known. + VersionedInfo lookupCXXMethod(ContextID CtxID, + llvm::StringRef Name); + /// Look for information regarding the given global variable. /// /// \param Name The name of the global variable. @@ -166,6 +176,17 @@ class APINotesReader { /// \returns information about the enumerator, if known. VersionedInfo lookupEnumConstant(llvm::StringRef Name); + /// Look for the context ID of the given C++ tag. + /// + /// \param Name The name of the tag we're looking for. + /// \param ParentCtx The context in which this tag is declared, e.g. a C++ + /// namespace. + /// + /// \returns The ID, if known. + std::optional + lookupTagID(llvm::StringRef Name, + std::optional ParentCtx = std::nullopt); + /// Look for information regarding the given tag /// (struct/union/enum/C++ class). /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e82dbc7c9540e..e0fe5eacef725 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -78,6 +78,14 @@ class APINotesWriter { bool IsInstanceMethod, const ObjCMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C++ method. + /// + /// \param CtxID The context in which this method resides, i.e. a C++ tag. + /// \param Name The name of the method. + /// \param Info Information about this method. + void addCXXMethod(ContextID CtxID, llvm::StringRef Name, +const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index b389aa8d56f16..c8e5e4df25d17 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C++ method. +class CXXMethodInfo : public FunctionInfo { +public: + CXXMethodInfo() {} +}; + /// Describes API notes data for an enumerator. class EnumConstantInfo : public CommonEntityInfo
[clang] [APINotes] Support annotating C++ methods (PR #99512)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/99512 >From 0a0dbf24c096c4fc0be973fb03bb48688afa447b Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 18 Jul 2024 15:49:24 +0100 Subject: [PATCH] [APINotes] Support annotating C++ methods This adds support for adding Clang attributes to C++ methods declared within C++ records by using API Notes. For instance: ``` Tags: - Name: IntWrapper Methods: - Name: getIncremented Availability: none ``` This is the first instance of something within a C++ record being annotated with API Notes, so it adds the necessary infra to make a C++ record an "API Notes context". Notably this does not add support for nested C++ tags. That will be added in a follow-up patch. rdar://131387880 --- clang/include/clang/APINotes/APINotesReader.h | 21 +++ clang/include/clang/APINotes/APINotesWriter.h | 8 + clang/include/clang/APINotes/Types.h | 7 + clang/lib/APINotes/APINotesFormat.h | 29 clang/lib/APINotes/APINotesReader.cpp | 149 clang/lib/APINotes/APINotesWriter.cpp | 72 clang/lib/APINotes/APINotesYAMLCompiler.cpp | 164 ++ clang/lib/Sema/SemaAPINotes.cpp | 50 +- .../APINotes/Inputs/Headers/Methods.apinotes | 8 + clang/test/APINotes/Inputs/Headers/Methods.h | 14 ++ .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 1 + .../APINotes/Inputs/Headers/module.modulemap | 4 + clang/test/APINotes/methods.cpp | 9 + clang/test/APINotes/namespaces.cpp| 5 + 15 files changed, 465 insertions(+), 79 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.h create mode 100644 clang/test/APINotes/methods.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 37a4ff7a69712..03657352c49a5 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,16 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given C++ method in the given C++ tag + /// context. + /// + /// \param CtxID The ID that references the parent context, i.e. a C++ tag. + /// \param Name The name of the C++ method we're looking for. + /// + /// \returns Information about the method, if known. + VersionedInfo lookupCXXMethod(ContextID CtxID, + llvm::StringRef Name); + /// Look for information regarding the given global variable. /// /// \param Name The name of the global variable. @@ -166,6 +176,17 @@ class APINotesReader { /// \returns information about the enumerator, if known. VersionedInfo lookupEnumConstant(llvm::StringRef Name); + /// Look for the context ID of the given C++ tag. + /// + /// \param Name The name of the tag we're looking for. + /// \param ParentCtx The context in which this tag is declared, e.g. a C++ + /// namespace. + /// + /// \returns The ID, if known. + std::optional + lookupTagID(llvm::StringRef Name, + std::optional ParentCtx = std::nullopt); + /// Look for information regarding the given tag /// (struct/union/enum/C++ class). /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e82dbc7c9540e..e0fe5eacef725 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -78,6 +78,14 @@ class APINotesWriter { bool IsInstanceMethod, const ObjCMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C++ method. + /// + /// \param CtxID The context in which this method resides, i.e. a C++ tag. + /// \param Name The name of the method. + /// \param Info Information about this method. + void addCXXMethod(ContextID CtxID, llvm::StringRef Name, +const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index b389aa8d56f16..c8e5e4df25d17 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C++ method. +class CXXMethodInfo : public FunctionInfo { +public: + CXXMethodInfo() {} +}; + /// Describes API notes data for an enumerator. class EnumConstantInfo : public CommonEntityInfo
[clang] [APINotes] Support annotating C++ methods (PR #99512)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/99512 This adds support for adding Clang attributes to C++ methods declared within C++ records by using API Notes. For instance: ``` Tags: - Name: IntWrapper Methods: - Name: getIncremented Availability: none ``` This is the first instance of something within a C++ record being annotated with API Notes, so it adds the necessary infra to make a C++ record an "API Notes context". Notably this does not add support for nested C++ tags. That will be added in a follow-up patch. rdar://131387880 >From 33ac9376e3c38c4cf4b1b7a0beec93b03e3ce806 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 18 Jul 2024 15:49:24 +0100 Subject: [PATCH] [APINotes] Support annotating C++ methods This adds support for adding Clang attributes to C++ methods declared within C++ records by using API Notes. For instance: ``` Tags: - Name: IntWrapper Methods: - Name: getIncremented Availability: none ``` This is the first instance of something within a C++ record being annotated with API Notes, so it adds the necessary infra to make a C++ record an "API Notes context". Notably this does not add support for nested C++ tags. That will be added in a follow-up patch. rdar://131387880 --- clang/include/clang/APINotes/APINotesReader.h | 21 +++ clang/include/clang/APINotes/APINotesWriter.h | 8 + clang/include/clang/APINotes/Types.h | 7 + clang/lib/APINotes/APINotesFormat.h | 29 clang/lib/APINotes/APINotesReader.cpp | 149 clang/lib/APINotes/APINotesWriter.cpp | 72 clang/lib/APINotes/APINotesYAMLCompiler.cpp | 164 ++ clang/lib/Sema/SemaAPINotes.cpp | 50 +- .../APINotes/Inputs/Headers/Methods.apinotes | 8 + clang/test/APINotes/Inputs/Headers/Methods.h | 14 ++ .../Inputs/Headers/Namespaces.apinotes| 3 + .../test/APINotes/Inputs/Headers/Namespaces.h | 1 + .../APINotes/Inputs/Headers/module.modulemap | 4 + clang/test/APINotes/methods.cpp | 9 + clang/test/APINotes/namespaces.cpp| 5 + 15 files changed, 465 insertions(+), 79 deletions(-) create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Methods.h create mode 100644 clang/test/APINotes/methods.cpp diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 37a4ff7a69712..03657352c49a5 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,16 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given C++ method in the given C++ tag + /// context. + /// + /// \param CtxID The ID that references the parent context, i.e. a C++ tag. + /// \param Name The name of the C++ method we're looking for. + /// + /// \returns Information about the method, if known. + VersionedInfo lookupCXXMethod(ContextID CtxID, + llvm::StringRef Name); + /// Look for information regarding the given global variable. /// /// \param Name The name of the global variable. @@ -166,6 +176,17 @@ class APINotesReader { /// \returns information about the enumerator, if known. VersionedInfo lookupEnumConstant(llvm::StringRef Name); + /// Look for the context ID of the given C++ tag. + /// + /// \param Name The name of the tag we're looking for. + /// \param ParentCtx The context in which this tag is declared, e.g. a C++ + /// namespace. + /// + /// \returns The ID, if known. + std::optional + lookupTagID(llvm::StringRef Name, + std::optional ParentCtx = std::nullopt); + /// Look for information regarding the given tag /// (struct/union/enum/C++ class). /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e82dbc7c9540e..e0fe5eacef725 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -78,6 +78,14 @@ class APINotesWriter { bool IsInstanceMethod, const ObjCMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C++ method. + /// + /// \param CtxID The context in which this method resides, i.e. a C++ tag. + /// \param Name The name of the method. + /// \param Info Information about this method. + void addCXXMethod(ContextID CtxID, llvm::StringRef Name, +const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Typ
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/99358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
@@ -286,6 +280,31 @@ inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) { lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID; } +/// A stored Objective-C or C++ declaration, represented by the ID of its parent +/// context, and the name of the declaration. +struct SingleDeclTableKey { + uint32_t parentContextID; + uint32_t nameID; + + SingleDeclTableKey() : parentContextID(-1), nameID(-1) {} + + SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID) + : parentContextID(ParentContextID), nameID(NameID) {} + + SingleDeclTableKey(std::optional ParentCtx, IdentifierID NameID) + : parentContextID(ParentCtx ? ParentCtx->id.Value : (uint32_t)-1), egorzhdan wrote: Done! https://github.com/llvm/llvm-project/pull/99358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
egorzhdan wrote: Yeap, exactly, we weren't actually using the context kind, so this patch basically just removes it. https://github.com/llvm/llvm-project/pull/99358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/99358 >From 8fcad7fee075e59dcf38716f19de738f51d85d82 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Jul 2024 18:13:34 +0100 Subject: [PATCH] [APINotes] Reduce memory footprint for Obj-C/C++ contexts We were storing extraneous data for certain Objective-C/C++ entities. Specifically, for declarations that can be nested in another context (such as functions) we were storing the kind of the parent context in addition to its ID. The ID is always sufficient. This removes the logically incorrect usages of `ContextTableKey` that don't actually describe a context, but rather describe a single declaration. This introduces `SingleDeclTableKey` to store that kind of entities in a more compact and reasonable way. --- clang/lib/APINotes/APINotesFormat.h | 57 +++ clang/lib/APINotes/APINotesReader.cpp | 32 ++- clang/lib/APINotes/APINotesWriter.cpp | 46 +++-- 3 files changed, 84 insertions(+), 51 deletions(-) diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index e3aa76df8316c..42dfe7a773a97 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 = 26; // SwiftCopyable +const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -269,12 +269,6 @@ struct ContextTableKey { : parentContextID(parentContextID), contextKind(contextKind), contextID(contextID) {} - ContextTableKey(std::optional context, IdentifierID nameID) - : parentContextID(context ? context->id.Value : (uint32_t)-1), -contextKind(context ? static_cast(context->kind) -: static_cast(-1)), -contextID(nameID) {} - llvm::hash_code hashValue() const { return llvm::hash_value( std::tuple{parentContextID, contextKind, contextID}); @@ -286,6 +280,32 @@ inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) { lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID; } +/// A stored Objective-C or C++ declaration, represented by the ID of its parent +/// context, and the name of the declaration. +struct SingleDeclTableKey { + uint32_t parentContextID; + uint32_t nameID; + + SingleDeclTableKey() : parentContextID(-1), nameID(-1) {} + + SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID) + : parentContextID(ParentContextID), nameID(NameID) {} + + SingleDeclTableKey(std::optional ParentCtx, IdentifierID NameID) + : parentContextID(ParentCtx ? ParentCtx->id.Value + : static_cast(-1)), +nameID(NameID) {} + + llvm::hash_code hashValue() const { +return llvm::hash_value(std::make_pair(parentContextID, nameID)); + } +}; + +inline bool operator==(const SingleDeclTableKey &lhs, + const SingleDeclTableKey &rhs) { + return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID; +} + } // namespace api_notes } // namespace clang @@ -341,6 +361,29 @@ template <> struct DenseMapInfo { return lhs == rhs; } }; + +template <> struct DenseMapInfo { + static inline clang::api_notes::SingleDeclTableKey getEmptyKey() { +return clang::api_notes::SingleDeclTableKey(); + } + + static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() { +return clang::api_notes::SingleDeclTableKey{ +DenseMapInfo::getTombstoneKey(), +DenseMapInfo::getTombstoneKey()}; + } + + static unsigned + getHashValue(const clang::api_notes::SingleDeclTableKey &value) { +return value.hashValue(); + } + + static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs, + const clang::api_notes::SingleDeclTableKey &rhs) { +return lhs == rhs; + } +}; + } // namespace llvm #endif diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 8454e092b55ac..7600738374840 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -429,15 +429,13 @@ class ObjCSelectorTableInfo { /// Used to deserialize the on-disk global variable table. class GlobalVariableTableInfo -: public VersionedTableInfo { public: static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { auto CtxID = endian::readNext(Data); -auto ContextKind = -endian::readNext(Data); auto NameID = endian::readNext(Data); -return {CtxID, ContextKind, NameID}; +return {CtxID, NameID}; } hash_value_type ComputeHash(internal_key_type Key) { @@ -454,15 +452,13 @@ class GlobalVariableTableInfo /// Used
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
@@ -269,12 +269,6 @@ struct ContextTableKey { : parentContextID(parentContextID), contextKind(contextKind), contextID(contextID) {} - ContextTableKey(std::optional context, IdentifierID nameID) - : parentContextID(context ? context->id.Value : (uint32_t)-1), -contextKind(context ? static_cast(context->kind) -: static_cast(-1)), -contextID(nameID) {} egorzhdan wrote: This constructor was doing something that didn't make any sense: instead of storing the contextKind of the current decl, it stored the contextKind of its parent. https://github.com/llvm/llvm-project/pull/99358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Reduce memory footprint for Obj-C/C++ contexts (PR #99358)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/99358 We were storing extraneous data for certain Objective-C/C++ entities. Specifically, for declarations that can be nested in another context (such as functions) we were storing the kind of the parent context in addition to its ID. The ID is always sufficient. This removes the logically incorrect usages of `ContextTableKey` that don't actually describe a context, but rather describe a single declaration. This introduces `SingleDeclTableKey` to store that kind of entities in a more compact and reasonable way. >From cec486ee4a00677c143ee70f4f4b5ef6e6c4f3ca Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Jul 2024 18:13:34 +0100 Subject: [PATCH] [APINotes] Reduce memory footprint for Obj-C/C++ contexts We were storing extraneous data for certain Objective-C/C++ entities. Specifically, for declarations that can be nested in another context (such as functions) we were storing the kind of the parent context in addition to its ID. The ID is always sufficient. This removes the logically incorrect usages of `ContextTableKey` that don't actually describe a context, but rather describe a single declaration. This introduces `SingleDeclTableKey` to store that kind of entities in a more compact and reasonable way. --- clang/lib/APINotes/APINotesFormat.h | 56 +++ clang/lib/APINotes/APINotesReader.cpp | 32 ++- clang/lib/APINotes/APINotesWriter.cpp | 46 +++--- 3 files changed, 83 insertions(+), 51 deletions(-) diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index e3aa76df8316c..da52a5670c0b3 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 = 26; // SwiftCopyable +const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -269,12 +269,6 @@ struct ContextTableKey { : parentContextID(parentContextID), contextKind(contextKind), contextID(contextID) {} - ContextTableKey(std::optional context, IdentifierID nameID) - : parentContextID(context ? context->id.Value : (uint32_t)-1), -contextKind(context ? static_cast(context->kind) -: static_cast(-1)), -contextID(nameID) {} - llvm::hash_code hashValue() const { return llvm::hash_value( std::tuple{parentContextID, contextKind, contextID}); @@ -286,6 +280,31 @@ inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) { lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID; } +/// A stored Objective-C or C++ declaration, represented by the ID of its parent +/// context, and the name of the declaration. +struct SingleDeclTableKey { + uint32_t parentContextID; + uint32_t nameID; + + SingleDeclTableKey() : parentContextID(-1), nameID(-1) {} + + SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID) + : parentContextID(ParentContextID), nameID(NameID) {} + + SingleDeclTableKey(std::optional ParentCtx, IdentifierID NameID) + : parentContextID(ParentCtx ? ParentCtx->id.Value : (uint32_t)-1), +nameID(NameID) {} + + llvm::hash_code hashValue() const { +return llvm::hash_value(std::make_pair(parentContextID, nameID)); + } +}; + +inline bool operator==(const SingleDeclTableKey &lhs, + const SingleDeclTableKey &rhs) { + return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID; +} + } // namespace api_notes } // namespace clang @@ -341,6 +360,29 @@ template <> struct DenseMapInfo { return lhs == rhs; } }; + +template <> struct DenseMapInfo { + static inline clang::api_notes::SingleDeclTableKey getEmptyKey() { +return clang::api_notes::SingleDeclTableKey(); + } + + static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() { +return clang::api_notes::SingleDeclTableKey{ +DenseMapInfo::getTombstoneKey(), +DenseMapInfo::getTombstoneKey()}; + } + + static unsigned + getHashValue(const clang::api_notes::SingleDeclTableKey &value) { +return value.hashValue(); + } + + static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs, + const clang::api_notes::SingleDeclTableKey &rhs) { +return lhs == rhs; + } +}; + } // namespace llvm #endif diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 8454e092b55ac..7600738374840 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -429,15 +429,13 @@ class ObjCSelectorTableInfo { /// Used to deserialize the on-disk global variable table. class Gl
[clang] [APINotes] Remove unused API (PR #98943)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/98943 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Remove unused API (PR #98943)
egorzhdan wrote: Yeah, I can't see any usages of this in the past few years. It was probably used a long while ago. https://github.com/llvm/llvm-project/pull/98943 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Remove unused API (PR #98943)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/98943 This method is not actually used anywhere. >From 4010859ca13a79d55a7b47f9363ee32870b7f1ef Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 15 Jul 2024 19:37:13 +0100 Subject: [PATCH] [APINotes] Remove unused API This method is not actually used anywhere. --- clang/include/clang/APINotes/Types.h | 7 --- 1 file changed, 7 deletions(-) diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index daf2f1897f46b..b389aa8d56f16 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -263,13 +263,6 @@ class ContextInfo : public CommonTypeInfo { SwiftObjCMembers = Value.value_or(false); } - /// Strip off any information within the class information structure that is - /// module-local, such as 'audited' flags. - void stripModuleLocalInfo() { -HasDefaultNullability = false; -DefaultNullability = 0; - } - friend bool operator==(const ContextInfo &, const ContextInfo &); ContextInfo &operator|=(const ContextInfo &RHS) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Refactor: remove references to `ObjCContext...` (PR #98201)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/98201 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Refactor: remove references to `ObjCContext...` (PR #98201)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/98201 >From d90ff1e2ff914a6086fe06578594de7cfc11b2af Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 9 Jul 2024 19:53:08 +0100 Subject: [PATCH] [APINotes] Refactor: remove references to `ObjCContext...` API Notes now support in C++. In preparation for supporting C++ methods in API Notes, this change renames the remaining usages of `ObjCContextABC` into `ContextABC` to make it clear that those contexts might actually be C++, not Objective-C. This is NFC-ish. --- clang/include/clang/APINotes/APINotesReader.h | 4 +- clang/include/clang/APINotes/APINotesWriter.h | 8 +- clang/include/clang/APINotes/Types.h | 19 ++-- clang/lib/APINotes/APINotesFormat.h | 20 ++-- clang/lib/APINotes/APINotesReader.cpp | 93 +-- clang/lib/APINotes/APINotesTypes.cpp | 2 +- clang/lib/APINotes/APINotesWriter.cpp | 71 +++--- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 10 +- clang/lib/Sema/SemaAPINotes.cpp | 4 +- 9 files changed, 115 insertions(+), 116 deletions(-) diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 1c5aab0959550..37a4ff7a69712 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -101,7 +101,7 @@ class APINotesReader { /// \param Name The name of the class we're looking for. /// /// \returns The information about the class, if known. - VersionedInfo lookupObjCClassInfo(llvm::StringRef Name); + VersionedInfo lookupObjCClassInfo(llvm::StringRef Name); /// Look for the context ID of the given Objective-C protocol. /// @@ -115,7 +115,7 @@ class APINotesReader { /// \param Name The name of the protocol we're looking for. /// /// \returns The information about the protocol, if known. - VersionedInfo lookupObjCProtocolInfo(llvm::StringRef Name); + VersionedInfo lookupObjCProtocolInfo(llvm::StringRef Name); /// Look for information regarding the given Objective-C property in /// the given context. diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index c5ca3e4617796..e82dbc7c9540e 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -53,10 +53,10 @@ class APINotesWriter { /// /// \returns the ID of the class, protocol, or namespace, which can be used to /// add properties and methods to the class/protocol/namespace. - ContextID addObjCContext(std::optional ParentCtxID, - llvm::StringRef Name, ContextKind Kind, - const ObjCContextInfo &Info, - llvm::VersionTuple SwiftVersion); + ContextID addContext(std::optional ParentCtxID, + llvm::StringRef Name, ContextKind Kind, + const ContextInfo &Info, + llvm::VersionTuple SwiftVersion); /// Add information about a specific Objective-C property. /// diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 026a4a431e734..daf2f1897f46b 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -192,8 +192,9 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { return !(LHS == RHS); } -/// Describes API notes data for an Objective-C class or protocol. -class ObjCContextInfo : public CommonTypeInfo { +/// Describes API notes data for an Objective-C class or protocol or a C++ +/// namespace. +class ContextInfo : public CommonTypeInfo { /// Whether this class has a default nullability. LLVM_PREFERRED_TYPE(bool) unsigned HasDefaultNullability : 1; @@ -217,7 +218,7 @@ class ObjCContextInfo : public CommonTypeInfo { unsigned SwiftObjCMembers : 1; public: - ObjCContextInfo() + ContextInfo() : HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0), SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false), SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {} @@ -269,9 +270,9 @@ class ObjCContextInfo : public CommonTypeInfo { DefaultNullability = 0; } - friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &); + friend bool operator==(const ContextInfo &, const ContextInfo &); - ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) { + ContextInfo &operator|=(const ContextInfo &RHS) { // Merge inherited info. static_cast(*this) |= RHS; @@ -294,7 +295,7 @@ class ObjCContextInfo : public CommonTypeInfo { LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); }; -inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) { +inline bool operator==(const ContextInfo &LHS, const ContextInfo &RHS) { return static_cast(LHS)
[clang] [APINotes] Refactor: remove references to `ObjCContext...` (PR #98201)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/98201 API Notes now support in C++. In preparation for supporting C++ methods in API Notes, this change renames the remaining usages of `ObjCContextABC` into `ContextABC` to make it clear that those contexts might actually be C++, not Objective-C. This is NFC-ish. >From 1553f723572322e4cab6c776ab1f0c7175adc495 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 9 Jul 2024 19:53:08 +0100 Subject: [PATCH] [APINotes] Refactor: remove references to `ObjCContext...` API Notes now support in C++. In preparation for supporting C++ methods in API Notes, this change renames the remaining usages of `ObjCContextABC` into `ContextABC` to make it clear that those contexts might actually be C++, not Objective-C. This is NFC-ish. --- clang/include/clang/APINotes/APINotesReader.h | 4 +- clang/include/clang/APINotes/APINotesWriter.h | 8 +- clang/include/clang/APINotes/Types.h | 19 ++-- clang/lib/APINotes/APINotesFormat.h | 16 ++-- clang/lib/APINotes/APINotesReader.cpp | 93 +-- clang/lib/APINotes/APINotesTypes.cpp | 2 +- clang/lib/APINotes/APINotesWriter.cpp | 72 +++--- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 10 +- clang/lib/Sema/SemaAPINotes.cpp | 4 +- 9 files changed, 114 insertions(+), 114 deletions(-) diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 1c5aab0959550..37a4ff7a69712 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -101,7 +101,7 @@ class APINotesReader { /// \param Name The name of the class we're looking for. /// /// \returns The information about the class, if known. - VersionedInfo lookupObjCClassInfo(llvm::StringRef Name); + VersionedInfo lookupObjCClassInfo(llvm::StringRef Name); /// Look for the context ID of the given Objective-C protocol. /// @@ -115,7 +115,7 @@ class APINotesReader { /// \param Name The name of the protocol we're looking for. /// /// \returns The information about the protocol, if known. - VersionedInfo lookupObjCProtocolInfo(llvm::StringRef Name); + VersionedInfo lookupObjCProtocolInfo(llvm::StringRef Name); /// Look for information regarding the given Objective-C property in /// the given context. diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index c5ca3e4617796..e82dbc7c9540e 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -53,10 +53,10 @@ class APINotesWriter { /// /// \returns the ID of the class, protocol, or namespace, which can be used to /// add properties and methods to the class/protocol/namespace. - ContextID addObjCContext(std::optional ParentCtxID, - llvm::StringRef Name, ContextKind Kind, - const ObjCContextInfo &Info, - llvm::VersionTuple SwiftVersion); + ContextID addContext(std::optional ParentCtxID, + llvm::StringRef Name, ContextKind Kind, + const ContextInfo &Info, + llvm::VersionTuple SwiftVersion); /// Add information about a specific Objective-C property. /// diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 026a4a431e734..daf2f1897f46b 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -192,8 +192,9 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { return !(LHS == RHS); } -/// Describes API notes data for an Objective-C class or protocol. -class ObjCContextInfo : public CommonTypeInfo { +/// Describes API notes data for an Objective-C class or protocol or a C++ +/// namespace. +class ContextInfo : public CommonTypeInfo { /// Whether this class has a default nullability. LLVM_PREFERRED_TYPE(bool) unsigned HasDefaultNullability : 1; @@ -217,7 +218,7 @@ class ObjCContextInfo : public CommonTypeInfo { unsigned SwiftObjCMembers : 1; public: - ObjCContextInfo() + ContextInfo() : HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0), SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false), SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {} @@ -269,9 +270,9 @@ class ObjCContextInfo : public CommonTypeInfo { DefaultNullability = 0; } - friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &); + friend bool operator==(const ContextInfo &, const ContextInfo &); - ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) { + ContextInfo &operator|=(const ContextInfo &RHS) { // Merge inherited info. static_cast(*this) |= RHS; @@ -294,7 +295,7 @@ class ObjCContextInfo : pub
[clang] [APINotes] Update the documentation with new features (PR #95162)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/95162 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Update the documentation with new features (PR #95162)
egorzhdan wrote: The test failures are unrelated to this change. https://github.com/llvm/llvm-project/pull/95162 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Update the documentation with new features (PR #95162)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/95162 >From c9d9d115118471f0ca6a311e44b366ef9fe4fb2b Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 11 Jun 2024 19:58:53 +0100 Subject: [PATCH 1/2] [APINotes] Update the documentation with new features This adds the documentation for a few recently added Clang API Notes features: C++ namespaces, `SwiftImportAs` and `SwiftCopyable`. --- clang/docs/APINotes.rst | 37 ++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index a6e200e8bffde..2a688e3dca24d 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -80,11 +80,12 @@ entries: Name: MyFramework -:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions: +:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions, Namespaces: Arrays of top-level declarations. Each entry in the array must have a - 'Name' key with its Objective-C name. "Tags" refers to structs, enums, and - unions; "Enumerators" refers to enum cases. + 'Name' key with its Objective-C or C++ name. "Tags" refers to structs, + C++ classes, enums, and unions; "Classes" refers to Objective-C classes; + "Enumerators" refers to enum cases. :: @@ -157,6 +158,36 @@ declaration kind), all of which are optional: - Class: NSBundle SwiftName: Bundle +:SwiftImportAs: + + For a class, possible values are ``owned`` (equivalent to + ``SWIFT_SELF_CONTAINED``), ``reference`` (equivalent to + ``SWIFT_SHARED_REFERENCE``, also requires specifying ``SwiftReleaseOp`` and + ``SwiftRetainOp``). + + For a method, possible values are ``unsafe`` (equivalent + to ``SWIFT_RETURNS_INDEPENDENT_VALUE``), ``computed_property`` (equivalent to + ``SWIFT_COMPUTED_PROPERTY``). + + :: + +Tags: +- Name: RefCountedStorage + SwiftImportAs: reference + SwiftReleaseOp: RCRelease + SwiftRetainOp: RCRetain + +:SwiftCopyable: + + Allows annotating a C++ class as non-copyable in Swift. Equivalent to + ``SWIFT_NONCOPYABLE``, or to an explicit conformance ``: ~Copyable``. + + :: + +Tags: +- Name: tzdb + SwiftCopyable: false + :Availability, AvailabilityMsg: A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of >From 201db9ad4ab7e9aaac84b18c6b1e139b202065f9 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 11 Jun 2024 22:08:26 +0100 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Saleem Abdulrasool --- clang/docs/APINotes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index 2a688e3dca24d..bc09b16bab5d2 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -161,12 +161,12 @@ declaration kind), all of which are optional: :SwiftImportAs: For a class, possible values are ``owned`` (equivalent to - ``SWIFT_SELF_CONTAINED``), ``reference`` (equivalent to + ``SWIFT_SELF_CONTAINED``) or ``reference`` (equivalent to ``SWIFT_SHARED_REFERENCE``, also requires specifying ``SwiftReleaseOp`` and ``SwiftRetainOp``). For a method, possible values are ``unsafe`` (equivalent - to ``SWIFT_RETURNS_INDEPENDENT_VALUE``), ``computed_property`` (equivalent to + to ``SWIFT_RETURNS_INDEPENDENT_VALUE``) or ``computed_property`` (equivalent to ``SWIFT_COMPUTED_PROPERTY``). :: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Update the documentation with new features (PR #95162)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/95162 This adds the documentation for a few recently added Clang API Notes features: C++ namespaces, `SwiftImportAs` and `SwiftCopyable`. >From c9d9d115118471f0ca6a311e44b366ef9fe4fb2b Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 11 Jun 2024 19:58:53 +0100 Subject: [PATCH] [APINotes] Update the documentation with new features This adds the documentation for a few recently added Clang API Notes features: C++ namespaces, `SwiftImportAs` and `SwiftCopyable`. --- clang/docs/APINotes.rst | 37 ++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index a6e200e8bffde..2a688e3dca24d 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -80,11 +80,12 @@ entries: Name: MyFramework -:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions: +:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions, Namespaces: Arrays of top-level declarations. Each entry in the array must have a - 'Name' key with its Objective-C name. "Tags" refers to structs, enums, and - unions; "Enumerators" refers to enum cases. + 'Name' key with its Objective-C or C++ name. "Tags" refers to structs, + C++ classes, enums, and unions; "Classes" refers to Objective-C classes; + "Enumerators" refers to enum cases. :: @@ -157,6 +158,36 @@ declaration kind), all of which are optional: - Class: NSBundle SwiftName: Bundle +:SwiftImportAs: + + For a class, possible values are ``owned`` (equivalent to + ``SWIFT_SELF_CONTAINED``), ``reference`` (equivalent to + ``SWIFT_SHARED_REFERENCE``, also requires specifying ``SwiftReleaseOp`` and + ``SwiftRetainOp``). + + For a method, possible values are ``unsafe`` (equivalent + to ``SWIFT_RETURNS_INDEPENDENT_VALUE``), ``computed_property`` (equivalent to + ``SWIFT_COMPUTED_PROPERTY``). + + :: + +Tags: +- Name: RefCountedStorage + SwiftImportAs: reference + SwiftReleaseOp: RCRelease + SwiftRetainOp: RCRetain + +:SwiftCopyable: + + Allows annotating a C++ class as non-copyable in Swift. Equivalent to + ``SWIFT_NONCOPYABLE``, or to an explicit conformance ``: ~Copyable``. + + :: + +Tags: +- Name: tzdb + SwiftCopyable: false + :Availability, AvailabilityMsg: A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [NFC] Add missing spaces in BoolOption for apinotes (PR #92027)
https://github.com/egorzhdan approved this pull request. Thank you, LGTM! https://github.com/llvm/llvm-project/pull/92027 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Add diagnostic about "%P" specifier with Objective-C pointers (PR #89977)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/89977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Add diagnostic about "%P" specifier with Objective-C pointers (PR #89977)
https://github.com/egorzhdan edited https://github.com/llvm/llvm-project/pull/89977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Add diagnostic about "%P" specifier with Objective-C pointers (#89968) (PR #89977)
https://github.com/egorzhdan edited https://github.com/llvm/llvm-project/pull/89977 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
egorzhdan wrote: The test failure on Windows is not related to this PR. https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/90064 >From 60191f2bc6cb191b5b256d220a8b1d07093bddd1 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 25 Apr 2024 15:19:09 +0100 Subject: [PATCH] [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 --- clang/include/clang/APINotes/Types.h | 22 ++- clang/lib/APINotes/APINotesFormat.h | 5 - clang/lib/APINotes/APINotesReader.cpp | 7 ++ clang/lib/APINotes/APINotesWriter.cpp | 7 +- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 5 + 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 + 9 files changed, 65 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 93bb045d6a6670..026a4a431e7349 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -675,6 +675,11 @@ class TagInfo : public CommonTypeInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsFlagEnum : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyableSpecified : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyable : 1; + public: std::optional SwiftImportAs; std::optional SwiftRetainOp; @@ -682,7 +687,9 @@ class TagInfo : public CommonTypeInfo { std::optional EnumExtensibility; - TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {} + TagInfo() + : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false), +SwiftCopyable(false) {} std::optional isFlagEnum() const { if (HasFlagEnum) @@ -694,6 +701,15 @@ class TagInfo : public CommonTypeInfo { IsFlagEnum = Value.value_or(false); } + std::optional isSwiftCopyable() const { +return SwiftCopyableSpecified ? std::optional(SwiftCopyable) + : std::nullopt; + } + void setSwiftCopyable(std::optional Value) { +SwiftCopyableSpecified = Value.has_value(); +SwiftCopyable = Value.value_or(false); + } + TagInfo &operator|=(const TagInfo &RHS) { static_cast(*this) |= RHS; @@ -710,6 +726,9 @@ class TagInfo : public CommonTypeInfo { if (!EnumExtensibility) EnumExtensibility = RHS.EnumExtensibility; +if (!SwiftCopyableSpecified) + setSwiftCopyable(RHS.isSwiftCopyable()); + return *this; } @@ -724,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && LHS.isFlagEnum() == RHS.isFlagEnum() && + LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; } diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 615314c46f09ca..97e630e97fdcc2 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; using IdentifierIDField = llvm::BCVBR<16>; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index dfc3beb6fa13ee..b60ca685f62c98 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -527,6 +527,13 @@ class TagTableInfo Info.EnumExtensibility = static_cast((Payload & 0x3) - 1); +uint8_t Copyable = +endian::readNext(Data); +if (Copyable == kSwiftNonCopyable) + Info.setSwiftCopyable(std::optional(false)); +else if (Copyable == kSwiftCopyable) + Info.setSwiftCopyable(std::optional(true)); + unsigned ImportAsLength = endian::readNext(Data); if (ImportAsLength > 0) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index e3f5d102fcd07f..3e615976315090 100644 --- a/clang/lib/APINotes/APINotesWr
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan ready_for_review https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
@@ -1146,6 +1146,12 @@ class TagTableInfo : public CommonTypeTableInfo { writer.write(Flags); +if (auto Copyable = TI.isSwiftCopyable()) { egorzhdan wrote: Fixed https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
@@ -527,6 +527,13 @@ class TagTableInfo Info.EnumExtensibility = static_cast((Payload & 0x3) - 1); +uint8_t Copyable = +endian::readNext(Data); +if (Copyable == 1) + Info.setSwiftCopyable(std::optional(false)); +else if (Copyable == 2) + Info.setSwiftCopyable(std::optional(true)); egorzhdan wrote: Good point! Added the constants. https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/90064 >From f0394cfaf4df3881809fdce7882bda3006951805 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 25 Apr 2024 15:19:09 +0100 Subject: [PATCH] [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 --- clang/include/clang/APINotes/Types.h | 22 ++- clang/lib/APINotes/APINotesFormat.h | 5 - clang/lib/APINotes/APINotesReader.cpp | 7 ++ clang/lib/APINotes/APINotesWriter.cpp | 13 +++ clang/lib/APINotes/APINotesYAMLCompiler.cpp | 5 + 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 + 9 files changed, 68 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 93bb045d6a6670..026a4a431e7349 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -675,6 +675,11 @@ class TagInfo : public CommonTypeInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsFlagEnum : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyableSpecified : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyable : 1; + public: std::optional SwiftImportAs; std::optional SwiftRetainOp; @@ -682,7 +687,9 @@ class TagInfo : public CommonTypeInfo { std::optional EnumExtensibility; - TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {} + TagInfo() + : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false), +SwiftCopyable(false) {} std::optional isFlagEnum() const { if (HasFlagEnum) @@ -694,6 +701,15 @@ class TagInfo : public CommonTypeInfo { IsFlagEnum = Value.value_or(false); } + std::optional isSwiftCopyable() const { +return SwiftCopyableSpecified ? std::optional(SwiftCopyable) + : std::nullopt; + } + void setSwiftCopyable(std::optional Value) { +SwiftCopyableSpecified = Value.has_value(); +SwiftCopyable = Value.value_or(false); + } + TagInfo &operator|=(const TagInfo &RHS) { static_cast(*this) |= RHS; @@ -710,6 +726,9 @@ class TagInfo : public CommonTypeInfo { if (!EnumExtensibility) EnumExtensibility = RHS.EnumExtensibility; +if (!SwiftCopyableSpecified) + setSwiftCopyable(RHS.isSwiftCopyable()); + return *this; } @@ -724,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && LHS.isFlagEnum() == RHS.isFlagEnum() && + LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; } diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 615314c46f09ca..97e630e97fdcc2 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; using IdentifierIDField = llvm::BCVBR<16>; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index dfc3beb6fa13ee..b60ca685f62c98 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -527,6 +527,13 @@ class TagTableInfo Info.EnumExtensibility = static_cast((Payload & 0x3) - 1); +uint8_t Copyable = +endian::readNext(Data); +if (Copyable == kSwiftNonCopyable) + Info.setSwiftCopyable(std::optional(false)); +else if (Copyable == kSwiftCopyable) + Info.setSwiftCopyable(std::optional(true)); + unsigned ImportAsLength = endian::readNext(Data); if (ImportAsLength > 0) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index e3f5d102fcd07f..6bd96c0b813cf7 100644 --- a/clang/lib/APINotes/APINo
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
@@ -1125,10 +1125,10 @@ class CommonTypeTableInfo class TagTableInfo : public CommonTypeTableInfo { public: unsigned getUnversionedInfoSize(const TagInfo &TI) { -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); +return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 + + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 2 + + getCommonTypeInfoSize(TI); egorzhdan wrote: Yeah, it's unfortunate that clang-format is overly strict about this. I can revert this and try to merge despite clang-format complaining, if you think that's better. https://github.com/llvm/llvm-project/pull/90064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/90064 >From 9eac3a34aa9c48e1ddc715ca04c4380f1d78a876 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 25 Apr 2024 15:19:09 +0100 Subject: [PATCH] [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 --- clang/include/clang/APINotes/Types.h | 22 ++- clang/lib/APINotes/APINotesReader.cpp | 7 ++ clang/lib/APINotes/APINotesWriter.cpp | 14 clang/lib/APINotes/APINotesYAMLCompiler.cpp | 5 + 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 + 8 files changed, 65 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 93bb045d6a6670..026a4a431e7349 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -675,6 +675,11 @@ class TagInfo : public CommonTypeInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsFlagEnum : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyableSpecified : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyable : 1; + public: std::optional SwiftImportAs; std::optional SwiftRetainOp; @@ -682,7 +687,9 @@ class TagInfo : public CommonTypeInfo { std::optional EnumExtensibility; - TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {} + TagInfo() + : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false), +SwiftCopyable(false) {} std::optional isFlagEnum() const { if (HasFlagEnum) @@ -694,6 +701,15 @@ class TagInfo : public CommonTypeInfo { IsFlagEnum = Value.value_or(false); } + std::optional isSwiftCopyable() const { +return SwiftCopyableSpecified ? std::optional(SwiftCopyable) + : std::nullopt; + } + void setSwiftCopyable(std::optional Value) { +SwiftCopyableSpecified = Value.has_value(); +SwiftCopyable = Value.value_or(false); + } + TagInfo &operator|=(const TagInfo &RHS) { static_cast(*this) |= RHS; @@ -710,6 +726,9 @@ class TagInfo : public CommonTypeInfo { if (!EnumExtensibility) EnumExtensibility = RHS.EnumExtensibility; +if (!SwiftCopyableSpecified) + setSwiftCopyable(RHS.isSwiftCopyable()); + return *this; } @@ -724,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && LHS.isFlagEnum() == RHS.isFlagEnum() && + LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; } diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index dfc3beb6fa13ee..7eaab36a85d00b 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -527,6 +527,13 @@ class TagTableInfo Info.EnumExtensibility = static_cast((Payload & 0x3) - 1); +uint8_t Copyable = +endian::readNext(Data); +if (Copyable == 1) + Info.setSwiftCopyable(std::optional(false)); +else if (Copyable == 2) + Info.setSwiftCopyable(std::optional(true)); + unsigned ImportAsLength = endian::readNext(Data); if (ImportAsLength > 0) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index e3f5d102fcd07f..e18108a7573eae 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1125,10 +1125,10 @@ class CommonTypeTableInfo class TagTableInfo : public CommonTypeTableInfo { public: unsigned getUnversionedInfoSize(const TagInfo &TI) { -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); +return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 + + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 2 + + getCommonTypeInfoSize(TI); } void emitUnversionedI
[clang] [APINotes] Allow annotating a C++ type as non-copyable in Swift (PR #90064)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/90064 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 >From a3ea8c954f3446330314f4b5d1ea42d87761b1c4 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 25 Apr 2024 15:19:09 +0100 Subject: [PATCH] [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 --- clang/include/clang/APINotes/Types.h | 22 ++- clang/lib/APINotes/APINotesReader.cpp | 7 ++ clang/lib/APINotes/APINotesWriter.cpp | 8 ++- clang/lib/APINotes/APINotesYAMLCompiler.cpp | 5 + 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 + 8 files changed, 62 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 93bb045d6a6670..026a4a431e7349 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -675,6 +675,11 @@ class TagInfo : public CommonTypeInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsFlagEnum : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyableSpecified : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftCopyable : 1; + public: std::optional SwiftImportAs; std::optional SwiftRetainOp; @@ -682,7 +687,9 @@ class TagInfo : public CommonTypeInfo { std::optional EnumExtensibility; - TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {} + TagInfo() + : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false), +SwiftCopyable(false) {} std::optional isFlagEnum() const { if (HasFlagEnum) @@ -694,6 +701,15 @@ class TagInfo : public CommonTypeInfo { IsFlagEnum = Value.value_or(false); } + std::optional isSwiftCopyable() const { +return SwiftCopyableSpecified ? std::optional(SwiftCopyable) + : std::nullopt; + } + void setSwiftCopyable(std::optional Value) { +SwiftCopyableSpecified = Value.has_value(); +SwiftCopyable = Value.value_or(false); + } + TagInfo &operator|=(const TagInfo &RHS) { static_cast(*this) |= RHS; @@ -710,6 +726,9 @@ class TagInfo : public CommonTypeInfo { if (!EnumExtensibility) EnumExtensibility = RHS.EnumExtensibility; +if (!SwiftCopyableSpecified) + setSwiftCopyable(RHS.isSwiftCopyable()); + return *this; } @@ -724,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && LHS.isFlagEnum() == RHS.isFlagEnum() && + LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && LHS.EnumExtensibility == RHS.EnumExtensibility; } diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index dfc3beb6fa13ee..7eaab36a85d00b 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -527,6 +527,13 @@ class TagTableInfo Info.EnumExtensibility = static_cast((Payload & 0x3) - 1); +uint8_t Copyable = +endian::readNext(Data); +if (Copyable == 1) + Info.setSwiftCopyable(std::optional(false)); +else if (Copyable == 2) + Info.setSwiftCopyable(std::optional(true)); + unsigned ImportAsLength = endian::readNext(Data); if (ImportAsLength > 0) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index e3f5d102fcd07f..c9584ff8345d2f 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1128,7 +1128,7 @@ class TagTableInfo : public CommonTypeTableInfo { return 2 + (TI.SwiftImpo
[clang] [APINotes] Add test for C++ class templates (PR #87006)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/87006 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Add test for C++ class templates (PR #87006)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/87006 This upstreams https://github.com/apple/llvm-project/pull/7930. This adds a test to verify that we can apply attributes to C++ class templates using API Notes. Doing the same for function templates is not currently possible and requires more work. >From f7713493fcde4ce149aa91e3782040f709f9b10f Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 28 Mar 2024 20:41:29 + Subject: [PATCH] [APINotes] Add test for C++ class templates This upstreams https://github.com/apple/llvm-project/pull/7930. This adds a test to verify that we can apply attributes to C++ class templates using API Notes. Doing the same for function templates is not currently possible and requires more work. --- clang/test/APINotes/Inputs/Headers/Templates.apinotes | 5 + clang/test/APINotes/Inputs/Headers/Templates.h| 9 + clang/test/APINotes/Inputs/Headers/module.modulemap | 4 clang/test/APINotes/templates.cpp | 9 + 4 files changed, 27 insertions(+) create mode 100644 clang/test/APINotes/Inputs/Headers/Templates.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Templates.h create mode 100644 clang/test/APINotes/templates.cpp diff --git a/clang/test/APINotes/Inputs/Headers/Templates.apinotes b/clang/test/APINotes/Inputs/Headers/Templates.apinotes new file mode 100644 index 00..b7336484da0c79 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Templates.apinotes @@ -0,0 +1,5 @@ +--- +Name: Templates +Tags: +- Name: Box + SwiftImportAs: owned diff --git a/clang/test/APINotes/Inputs/Headers/Templates.h b/clang/test/APINotes/Inputs/Headers/Templates.h new file mode 100644 index 00..862035fee363f7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Templates.h @@ -0,0 +1,9 @@ +template +struct Box { + T value; + + const T& get_value() const { return value; } + const T* get_ptr() const { return &value; } +}; + +using IntBox = Box; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 99fb1aec86481a..d515169184f4f0 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -36,6 +36,10 @@ module Namespaces { header "Namespaces.h" } +module Templates { + header "Templates.h" +} + module SwiftImportAs { header "SwiftImportAs.h" } diff --git a/clang/test/APINotes/templates.cpp b/clang/test/APINotes/templates.cpp new file mode 100644 index 00..d4dce291615e18 --- /dev/null +++ b/clang/test/APINotes/templates.cpp @@ -0,0 +1,9 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Tmpl -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Tmpl -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Box -x c++ | FileCheck -check-prefix=CHECK-BOX %s + +#include "Templates.h" + +// CHECK-BOX: Dumping Box: +// CHECK-BOX-NEXT: ClassTemplateDecl {{.+}} imported in Templates Box +// CHECK-BOX: SwiftAttrAttr {{.+}} <> "import_owned" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] For a re-exported module, look for APINotes in the re-exporting module's apinotes file (PR #86820)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/86820 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] For a re-exported module, look for APINotes in the re-exporting module's apinotes file (PR #86820)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/86820 This upstreams https://github.com/apple/llvm-project/pull/8063. If module FooCore is re-exported through module Foo (by using `export_as` in the modulemap), look for attributes of FooCore symbols in Foo.apinotes file. Swift bundles `std.apinotes` file that adds Swift-specific attributes to the C++ stdlib symbols. In recent versions of libc++, module std got split into multiple top-level modules, each of them is re-exported through std. This change allows us to keep using a single modulemap file for all supported C++ stdlibs. rdar://121680760 >From 05cbe254a30b09bed99e9cf20af07c3996d36340 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 27 Mar 2024 15:44:06 + Subject: [PATCH] [APINotes] For a re-exported module, look for APINotes in the re-exporting module's apinotes file This upstreams https://github.com/apple/llvm-project/pull/8063. If module FooCore is re-exported through module Foo (by using `export_as` in the modulemap), look for attributes of FooCore symbols in Foo.apinotes file. Swift bundles `std.apinotes` file that adds Swift-specific attributes to the C++ stdlib symbols. In recent versions of libc++, module std got split into multiple top-level modules, each of them is re-exported through std. This change allows us to keep using a single modulemap file for all supported C++ stdlibs. rdar://121680760 --- clang/lib/APINotes/APINotesManager.cpp | 5 + clang/test/APINotes/Inputs/Headers/ExportAs.apinotes | 5 + clang/test/APINotes/Inputs/Headers/ExportAs.h| 1 + clang/test/APINotes/Inputs/Headers/ExportAsCore.h| 1 + clang/test/APINotes/Inputs/Headers/module.modulemap | 10 ++ clang/test/APINotes/export-as.c | 8 6 files changed, 30 insertions(+) create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAs.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAs.h create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAsCore.h create mode 100644 clang/test/APINotes/export-as.c diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp index f60f09e2b3c231..789bb97d81de00 100644 --- a/clang/lib/APINotes/APINotesManager.cpp +++ b/clang/lib/APINotes/APINotesManager.cpp @@ -221,6 +221,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, ArrayRef SearchPaths) { FileManager &FM = SM.getFileManager(); auto ModuleName = M->getTopLevelModuleName(); + auto ExportedModuleName = M->getTopLevelModule()->ExportAsModule; llvm::SmallVector APINotes; // First, look relative to the module itself. @@ -233,6 +234,10 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, APINotes.push_back(*File); } + // If module FooCore is re-exported through module Foo, try Foo.apinotes. + if (!ExportedModuleName.empty()) +if (auto File = findAPINotesFile(Dir, ExportedModuleName, WantPublic)) + APINotes.push_back(*File); }; if (M->IsFramework) { diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes new file mode 100644 index 00..14c77afd8c30a1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes @@ -0,0 +1,5 @@ +Name: ExportAs +Globals: + - Name: globalInt +Availability: none +AvailabilityMsg: "oh no" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.h b/clang/test/APINotes/Inputs/Headers/ExportAs.h new file mode 100644 index 00..ff490e09641760 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.h @@ -0,0 +1 @@ +#include "ExportAsCore.h" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAsCore.h b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h new file mode 100644 index 00..f7674c19935d64 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h @@ -0,0 +1 @@ +static int globalInt = 123; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 98b4ee3e96cfe7..99fb1aec86481a 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -2,6 +2,16 @@ module ExternCtx { header "ExternCtx.h" } +module ExportAsCore { + header "ExportAsCore.h" + export_as ExportAs +} + +module ExportAs { + header "ExportAs.h" + export * +} + module HeaderLib { header "HeaderLib.h" } diff --git a/clang/test/APINotes/export-as.c b/clang/test/APINotes/export-as.c new file mode 100644 index 00..7a8a652ab75575 --- /dev/null +++ b/clang/test/APINotes/export-as.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapi
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
egorzhdan wrote: I'm going to land this patch now to unblock other work on APINotes, but I'm happy to address more review feedback post-merge. https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
egorzhdan wrote: @compnerd I think I addressed all of your comments, let me know if this is good to go! https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
@@ -52,49 +52,54 @@ static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, if (!Metadata.IsActive) return; - auto IsModified = [&](Decl *D, QualType QT, -NullabilityKind Nullability) -> bool { + auto GetModified = + [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> std::optional { QualType Original = QT; S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), isa(D), /*OverrideExisting=*/true); -return QT.getTypePtr() != Original.getTypePtr(); +return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT) + : std::nullopt; }; if (auto Function = dyn_cast(D)) { -if (IsModified(D, Function->getReturnType(), Nullability)) { - QualType FnType = Function->getType(); - Function->setType(FnType); +if (auto Modified = +GetModified(D, Function->getReturnType(), Nullability)) { + const FunctionType *FnType = Function->getType()->castAs(); + if (const FunctionProtoType *proto = dyn_cast(FnType)) +Function->setType(S.Context.getFunctionType( +*Modified, proto->getParamTypes(), proto->getExtProtoInfo())); + else +Function->setType( +S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo())); } } else if (auto Method = dyn_cast(D)) { -QualType Type = Method->getReturnType(); -if (IsModified(D, Type, Nullability)) { - Method->setReturnType(Type); +if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) { + Method->setReturnType(*Modified); // Make it a context-sensitive keyword if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } else if (auto Value = dyn_cast(D)) { -QualType Type = Value->getType(); -if (IsModified(D, Type, Nullability)) { - Value->setType(Type); +if (auto Modified = GetModified(D, Value->getType(), Nullability)) { + Value->setType(*Modified); // Make it a context-sensitive keyword if we can. if (auto Parm = dyn_cast(D)) { -if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) +if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified)) Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } } else if (auto Property = dyn_cast(D)) { -QualType Type = Property->getType(); -if (IsModified(D, Type, Nullability)) { - Property->setType(Type, Property->getTypeSourceInfo()); +if (auto Modified = GetModified(D, Property->getType(), Nullability)) { + Property->setType(*Modified, Property->getTypeSourceInfo()); // Make it a property attribute if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Property->setPropertyAttributes( ObjCPropertyAttribute::kind_null_resettable); } egorzhdan wrote: Good point, we don't have a test for this, let me add one https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
@@ -0,0 +1,44 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +// Test with Swift version 3.0. This should only affect the few APIs that have an entry in the 3.0 tables. egorzhdan wrote: Yes, in a sense that API Notes that apply attributes specific to Swift version 3.0 still exist in the SDK, and can be read by the compiler. https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
@@ -0,0 +1,4 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers +Nu llabilityOfRet: O egorzhdan wrote: Alright, I added a comment https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
@@ -638,15 +638,15 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(S, PDecl, FD.D); - // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. PDecl->setGetterName(GetterSel, GetterNameLoc); PDecl->setSetterName(SetterSel, SetterNameLoc); PDecl->setPropertyAttributesAsWritten( makePropertyAttributesAsWritten(AttributesAsWritten)); + ProcessDeclAttributes(S, PDecl, FD.D); + if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); egorzhdan wrote: We have a test for this in this PR, `properties.m` – that's how I discovered this :) https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST] Print attributes of Obj-C interfaces (PR #84772)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/84772 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream the remaining API Notes fixes and tests (PR #84773)
egorzhdan wrote: This depends on https://github.com/llvm/llvm-project/pull/84772. https://github.com/llvm/llvm-project/pull/84773 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST] Print attributes of Obj-C interfaces (PR #84772)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/84772 When pretty printing an Objective-C interface declaration, Clang previously didn't print any attributes that are applied to the declaration. >From 71ce3d88b229ff604dff64172d1fd9bcc18d32ea Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 11 Mar 2024 15:19:56 + Subject: [PATCH] [Clang][AST] Print attributes of Obj-C interfaces When pretty printing an Objective-C interface declaration, Clang previously didn't print any attributes that are applied to the declaration. --- clang/lib/AST/DeclPrinter.cpp | 5 + clang/test/AST/ast-print-objectivec.m | 8 2 files changed, 13 insertions(+) diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 43d221968ea3fb..b701581b2474a9 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1517,6 +1517,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { return; } bool eolnOut = false; + if (OID->hasAttrs()) { +prettyPrintAttributes(OID); +Out << "\n"; + } + Out << "@interface " << I; if (auto TypeParams = OID->getTypeParamListAsWritten()) { diff --git a/clang/test/AST/ast-print-objectivec.m b/clang/test/AST/ast-print-objectivec.m index 05a0a5d4aa74c4..a0652f38e713fa 100644 --- a/clang/test/AST/ast-print-objectivec.m +++ b/clang/test/AST/ast-print-objectivec.m @@ -21,6 +21,10 @@ - (void)MethI __attribute__((availability(macosx,introduced=10.1.0,deprecated=10 - (void)methodWithArg:(int)x andAnotherOne:(int)y { } @end +__attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2))) +@interface InterfaceWithAttribute +@end + // CHECK: @protocol P // CHECK: - (void)MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); // CHECK: @end @@ -45,6 +49,10 @@ - (void)methodWithArg:(int)x andAnotherOne:(int)y { } // CHECK: @end +// CHECK: __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) +// CHECK: @interface InterfaceWithAttribute +// CHECK: @end + @class C1; struct __attribute__((objc_bridge_related(C1,,))) S1; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Fix failing tests after a PCM logic change (PR #84556)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/84556 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Fix failing tests after a PCM logic change (PR #84556)
egorzhdan wrote: The clang-format CI failure is unrelated to this patch. https://github.com/llvm/llvm-project/pull/84556 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
egorzhdan wrote: Apologies for the delay! I looked into this performance hit, and it seems largely expected to me: the compiler spends extra time checking if there is an apinotes file for a given clang module with the notes for the declarations that are being processed. We can consider adding a Clang driver option to disable API Notes, if this performance regression is significant enough. https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Fix failing tests after a PCM logic change (PR #84556)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/84556 This fixes tests that are going to be upstreamed in the near future. Currently they are failing downstream in the Apple open source fork. Failing tests Clang :: APINotes/retain-count-convention.m Clang :: APINotes/types.m Clang :: APINotes/versioned-multi.c Clang :: APINotes/versioned.m Since 2e5af56 got merged, Clang now enables `LangOpts.APINotesModules` when reading a precompiled module that was built with API Notes enabled. This is correct. The logic in APINotesManager needs to be adjusted to handle this. rdar://123526142 >From e939da2aa1435027163efa4446e78b90c3d9243a Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 8 Mar 2024 20:09:50 + Subject: [PATCH] [APINotes] Fix failing tests after a PCM logic change This fixes tests that are going to be upstreamed in the near future. Currently they are failing downstream in the Apple open source fork. Failing tests Clang :: APINotes/retain-count-convention.m Clang :: APINotes/types.m Clang :: APINotes/versioned-multi.c Clang :: APINotes/versioned.m Since 2e5af56 got merged, Clang now enables `LangOpts.APINotesModules` when reading a precompiled module that was built with API Notes enabled. This is correct. The logic in APINotesManager needs to be adjusted to handle this. rdar://123526142 --- clang/lib/APINotes/APINotesManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp index d3aef09dac9105..f60f09e2b3c231 100644 --- a/clang/lib/APINotes/APINotesManager.cpp +++ b/clang/lib/APINotes/APINotesManager.cpp @@ -224,7 +224,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, llvm::SmallVector APINotes; // First, look relative to the module itself. - if (LookInModule) { + if (LookInModule && M->Directory) { // Local function to try loading an API notes file in the given directory. auto tryAPINotes = [&](DirectoryEntryRef Dir, bool WantPublic) { if (auto File = findAPINotesFile(Dir, ModuleName, WantPublic)) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Fix a few accidental refactoring artifacts (PR #83057)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/83057 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Fix a few accidental refactoring artifacts (PR #83057)
https://github.com/egorzhdan created https://github.com/llvm/llvm-project/pull/83057 This fixes a few breakages introduced during upstreaming – please see each commit for details. >From dae96657bee753a96bc41e8cde3ca81e082d82cb Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 26 Feb 2024 20:46:39 + Subject: [PATCH 1/4] [APINotes] Fix accidental refactoring artifact The assertion needs to happen after the read operation. --- clang/lib/APINotes/APINotesReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index ff9b95d9bf75e3..36f5c2931b7d9f 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -81,9 +81,9 @@ class VersionedTableInfo { auto version = ReadVersionTuple(Data); const auto *DataBefore = Data; (void)DataBefore; + auto UnversionedData = Derived::readUnversioned(Key, Data); assert(Data != DataBefore && "Unversioned data reader didn't move pointer"); - auto UnversionedData = Derived::readUnversioned(Key, Data); Result.push_back({version, UnversionedData}); } return Result; >From c08b72c3534310b3ddaefddccfc5a64f0829ee6e Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 26 Feb 2024 20:47:43 + Subject: [PATCH 2/4] [APINotes] Fix hashing of a string `llvm::hash_value` of a `StringRef` hashes the pointer, not the string. --- clang/lib/APINotes/APINotesReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 36f5c2931b7d9f..1364dc5acd3706 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -148,7 +148,7 @@ class IdentifierTableInfo { external_key_type GetExternalKey(internal_key_type Key) { return Key; } hash_value_type ComputeHash(internal_key_type Key) { -return llvm::hash_value(Key); +return llvm::djbHash(Key); } static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { >From e8ee95ab96e437f73a1557dcface7760d5a697e5 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 26 Feb 2024 20:48:57 + Subject: [PATCH 3/4] [APINotes] Do not use a moved-from value `Results` was being moved and then used. --- clang/lib/APINotes/APINotesReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 1364dc5acd3706..55ea4bae81e6e8 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -1797,8 +1797,8 @@ APINotesReader::Create(std::unique_ptr InputBuffer, template APINotesReader::VersionedInfo::VersionedInfo( llvm::VersionTuple Version, -llvm::SmallVector, 1> Results) -: Results(std::move(Results)) { +llvm::SmallVector, 1> R) +: Results(std::move(R)) { assert(!Results.empty()); assert(std::is_sorted( >From 76098becdbda1c1903592c160dbb0fc505ed31e3 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 26 Feb 2024 20:50:01 + Subject: [PATCH 4/4] [APINotes] Populate `StoredObjCSelector` properly --- clang/lib/APINotes/APINotesWriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 62a2ab1799913a..76fd24ccfae984 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -128,6 +128,7 @@ class APINotesWriter::Implementation { SelectorID getSelector(ObjCSelectorRef SelectorRef) { // Translate the selector reference into a stored selector. StoredObjCSelector Selector; +Selector.NumArgs = SelectorRef.NumArgs; Selector.Identifiers.reserve(SelectorRef.Identifiers.size()); for (auto piece : SelectorRef.Identifiers) Selector.Identifiers.push_back(getIdentifier(piece)); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
egorzhdan wrote: Oh, thanks @nikic for that data point. Let me try to avoid the overhead, I'll put up a patch tomorrow morning. https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
https://github.com/egorzhdan closed https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (!IsUnmodified(D, Function->getReturnType(), Nullability)) { + QualType FnType = Function->getType(); + Function->setType(FnType); +} + } else if (auto Method = dyn_cast(D)) { +QualType Type = Method->getReturnType(); +if (!IsUnmodified(D, Type, Nullability)) { + Method->setReturnType(Type); + + // Make it a context-sensitive keyword if we can. + if (!isIndirectPointerType(Type)) +Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( +Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); +} + } else if (auto Value = dyn_cast(D)) { +QualType Type = Value->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Value->setType(Type); + + // Make it a context-sensitive keyword if we can. + if (auto Parm = dyn_cast(D)) { +if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( + Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); + } +} + } else if (auto Property = dyn_cast(D)) { +QualType Type = Property->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Property->setType(Type, Property->getTypeSourceInfo()); + + // Make it a property attribute if we can. + if (!isIndirectPointerType(Type)) +Property->setPropertyAttributes( +ObjCPropertyAttribute::kind_null_resettable); +} + } +} + +/// Copy a string into ASTContext-allocated memory. +static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) { + void *mem = Ctx.Allocate(String.size(), alignof(char *)); + memcpy(mem, String.data(), String.size()); + return StringRef(static_cast(mem), String.size()); +} + +static AttributeCommonInfo getPlaceholderAttrInfo() { + return AttributeCommonInfo(SourceRange(), + AttributeCommonInfo::UnknownAttribute, + {AttributeCommonInfo::AS_GNU, + /*Spelling*/ 0, /*IsAlignas*/ false, + /*IsRegularKeywordAttribute*/ false}); +} + +namespace { +template struct AttrKindFor {}; + +#define ATTR(X) \ + template <> struct AttrKindFor { \ +static const attr::Kind value = attr::X; \ + }; +#include "clang/Basic/AttrList.inc" + +/// Handle an attribute introduced by API notes. +/// +/// \param IsAddition Whether we shoul
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (!IsUnmodified(D, Function->getReturnType(), Nullability)) { + QualType FnType = Function->getType(); + Function->setType(FnType); +} + } else if (auto Method = dyn_cast(D)) { +QualType Type = Method->getReturnType(); +if (!IsUnmodified(D, Type, Nullability)) { + Method->setReturnType(Type); + + // Make it a context-sensitive keyword if we can. + if (!isIndirectPointerType(Type)) +Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( +Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); +} + } else if (auto Value = dyn_cast(D)) { +QualType Type = Value->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Value->setType(Type); + + // Make it a context-sensitive keyword if we can. + if (auto Parm = dyn_cast(D)) { +if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( + Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); + } +} + } else if (auto Property = dyn_cast(D)) { +QualType Type = Property->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Property->setType(Type, Property->getTypeSourceInfo()); + + // Make it a property attribute if we can. + if (!isIndirectPointerType(Type)) +Property->setPropertyAttributes( +ObjCPropertyAttribute::kind_null_resettable); +} + } +} + +/// Copy a string into ASTContext-allocated memory. +static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) { + void *mem = Ctx.Allocate(String.size(), alignof(char *)); + memcpy(mem, String.data(), String.size()); + return StringRef(static_cast(mem), String.size()); +} + +static AttributeCommonInfo getPlaceholderAttrInfo() { + return AttributeCommonInfo(SourceRange(), + AttributeCommonInfo::UnknownAttribute, + {AttributeCommonInfo::AS_GNU, + /*Spelling*/ 0, /*IsAlignas*/ false, + /*IsRegularKeywordAttribute*/ false}); +} + +namespace { +template struct AttrKindFor {}; + +#define ATTR(X) \ + template <> struct AttrKindFor { \ +static const attr::Kind value = attr::X; \ + }; +#include "clang/Basic/AttrList.inc" + +/// Handle an attribute introduced by API notes. +/// +/// \param IsAddition Whether we shoul
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (!IsUnmodified(D, Function->getReturnType(), Nullability)) { + QualType FnType = Function->getType(); + Function->setType(FnType); +} + } else if (auto Method = dyn_cast(D)) { +QualType Type = Method->getReturnType(); +if (!IsUnmodified(D, Type, Nullability)) { + Method->setReturnType(Type); + + // Make it a context-sensitive keyword if we can. + if (!isIndirectPointerType(Type)) +Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( +Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); +} + } else if (auto Value = dyn_cast(D)) { +QualType Type = Value->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Value->setType(Type); + + // Make it a context-sensitive keyword if we can. + if (auto Parm = dyn_cast(D)) { +if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( + Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); + } +} + } else if (auto Property = dyn_cast(D)) { +QualType Type = Property->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Property->setType(Type, Property->getTypeSourceInfo()); + + // Make it a property attribute if we can. + if (!isIndirectPointerType(Type)) +Property->setPropertyAttributes( +ObjCPropertyAttribute::kind_null_resettable); +} + } +} + +/// Copy a string into ASTContext-allocated memory. +static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) { + void *mem = Ctx.Allocate(String.size(), alignof(char *)); + memcpy(mem, String.data(), String.size()); + return StringRef(static_cast(mem), String.size()); +} + +static AttributeCommonInfo getPlaceholderAttrInfo() { + return AttributeCommonInfo(SourceRange(), + AttributeCommonInfo::UnknownAttribute, + {AttributeCommonInfo::AS_GNU, + /*Spelling*/ 0, /*IsAlignas*/ false, + /*IsRegularKeywordAttribute*/ false}); +} + +namespace { +template struct AttrKindFor {}; + +#define ATTR(X) \ + template <> struct AttrKindFor { \ +static const attr::Kind value = attr::X; \ + }; +#include "clang/Basic/AttrList.inc" + +/// Handle an attribute introduced by API notes. +/// +/// \param IsAddition Whether we shoul
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (!IsUnmodified(D, Function->getReturnType(), Nullability)) { + QualType FnType = Function->getType(); + Function->setType(FnType); +} + } else if (auto Method = dyn_cast(D)) { +QualType Type = Method->getReturnType(); +if (!IsUnmodified(D, Type, Nullability)) { + Method->setReturnType(Type); + + // Make it a context-sensitive keyword if we can. + if (!isIndirectPointerType(Type)) +Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( +Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); +} + } else if (auto Value = dyn_cast(D)) { +QualType Type = Value->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Value->setType(Type); + + // Make it a context-sensitive keyword if we can. + if (auto Parm = dyn_cast(D)) { +if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( + Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); + } +} + } else if (auto Property = dyn_cast(D)) { +QualType Type = Property->getType(); +if (!IsUnmodified(D, Type, Nullability)) { + Property->setType(Type, Property->getTypeSourceInfo()); + + // Make it a property attribute if we can. + if (!isIndirectPointerType(Type)) +Property->setPropertyAttributes( +ObjCPropertyAttribute::kind_null_resettable); +} + } +} + +/// Copy a string into ASTContext-allocated memory. +static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) { + void *mem = Ctx.Allocate(String.size(), alignof(char *)); + memcpy(mem, String.data(), String.size()); + return StringRef(static_cast(mem), String.size()); +} + +static AttributeCommonInfo getPlaceholderAttrInfo() { + return AttributeCommonInfo(SourceRange(), + AttributeCommonInfo::UnknownAttribute, + {AttributeCommonInfo::AS_GNU, + /*Spelling*/ 0, /*IsAlignas*/ false, + /*IsRegularKeywordAttribute*/ false}); +} + +namespace { +template struct AttrKindFor {}; + +#define ATTR(X) \ + template <> struct AttrKindFor { \ +static const attr::Kind value = attr::X; \ + }; +#include "clang/Basic/AttrList.inc" + +/// Handle an attribute introduced by API notes. +/// +/// \param IsAddition Whether we shoul
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (!IsUnmodified(D, Function->getReturnType(), Nullability)) { egorzhdan wrote: Agreed, done. https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; egorzhdan wrote: `State` seems a bit too generic of a name to me, and these are still `bool`s so they won't get more cases. I renamed `IsReplacement_t` to `IsSubstitution_t`, but I would prefer to leave `IsActive_t` as is. https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,1014 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum IsActive_t : bool { IsNotActive, IsActive }; +enum IsReplacement_t : bool { IsNotReplacement, IsReplacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::IsActive), +IsReplacement(Replacement == IsReplacement_t::IsReplacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isMultiLevelPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + QualType Type; + + // Nullability for a function/method appertains to the retain type. + if (auto Function = dyn_cast(D)) +Type = Function->getReturnType(); + else if (auto Method = dyn_cast(D)) +Type = Method->getReturnType(); + else if (auto Value = dyn_cast(D)) +Type = Value->getType(); + else if (auto Property = dyn_cast(D)) +Type = Property->getType(); + else +return; + + // Check the nullability specifier on this type. + QualType OrigType = Type; + S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(), + isa(D), + /*overrideExisting=*/true); + if (Type.getTypePtr() == OrigType.getTypePtr()) +return; + + if (auto Function = dyn_cast(D)) { +const FunctionType *FnType = Function->getType()->castAs(); +if (const FunctionProtoType *Proto = dyn_cast(FnType)) + Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(), + Proto->getExtProtoInfo())); +else + Function->setType( + S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo())); + } else if (auto Method = dyn_cast(D)) { +Method->setReturnType(Type); + +// Make it a context-sensitive keyword if we can. +if (!isMultiLevelPointerType(Type)) + Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( + Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); + + } else if (auto Value = dyn_cast(D)) { +Value->setType(Type); + +// Make it a context-sensitive keyword if we can. +if (auto Parm = dyn_cast(D)) { + if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type)) +Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( +Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); +} + } else if (auto Property = dyn_cast(D)) { +Property->setType(Type, Property->getTypeSourceInfo()); + +// Make it a property attribute if we can. +if (!isMultiLevelPointerType(Type)) + Property->setPropertyAttributes( + ObjCPropertyAttribute::kind_null_resettable); + + } else +llvm_unreachable("cannot handle nullability here"); +} + +/// Copy a string into ASTContext-allocated memory. +static StringRef CopyString(ASTContext &Ctx, StringRef String) { + void *mem = Ctx.Allocate(String.size(), alignof(char)); + memcpy(mem, String.data(), String.size()); + return StringRef(static_cast(mem), String.size()); +} + +static AttributeCommonInfo getDummyAttrInfo() { + return AttributeCommonInfo(SourceRange(), + AttributeCommonInfo::UnknownAttribute, + {AttributeCommonInfo::AS_GNU, + /*Spelling*/ 0, /*IsAlignas*/ false, + /*IsRegularKeywordAttribute*/ false}); +} + +namespace { +template struct AttrKindFor {}; + +#define ATTR(X)
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/78445 >From 806fe5abaeec7ad7d75d0be026bb42808d15bc41 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Jan 2024 13:41:25 + Subject: [PATCH] [APINotes] Upstream Sema logic to apply API Notes to decls This upstreams more of the Clang API Notes functionality that is currently implemented in the Apple fork: https://github.com/apple/llvm-project/tree/next/clang/lib/APINotes --- .../clang/Basic/DiagnosticSemaKinds.td| 7 + clang/include/clang/Sema/Sema.h | 6 + clang/lib/Sema/CMakeLists.txt | 1 + clang/lib/Sema/SemaAPINotes.cpp | 988 ++ clang/lib/Sema/SemaDecl.cpp | 4 + clang/lib/Sema/SemaDeclAttr.cpp | 3 + clang/lib/Sema/SemaDeclCXX.cpp| 6 +- clang/lib/Sema/SemaDeclObjC.cpp | 4 + clang/lib/Sema/SemaObjCProperty.cpp | 5 + clang/lib/Sema/SemaTemplate.cpp | 7 + 10 files changed, 1030 insertions(+), 1 deletion(-) create mode 100644 clang/lib/Sema/SemaAPINotes.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ebda201361fb07..887d6120f48d2c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10760,6 +10760,13 @@ def warn_imp_cast_drops_unaligned : Warning< } // end of sema category +let CategoryName = "API Notes Issue" in { + +def err_incompatible_replacement_type : Error< + "API notes replacement type %0 has a different size from original type %1">; + +} // end of API Notes category + let CategoryName = "OpenMP Issue" in { // OpenMP support. def err_omp_expected_var_arg : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fcccac10f4733a..77749372b7fb65 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4883,6 +4883,12 @@ class Sema final { bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, bool SkipArgCountCheck = false); + /// Map any API notes provided for this declaration to attributes on the + /// declaration. + /// + /// Triggered by declaration-attribute processing. + void ProcessAPINotes(Decl *D); + /// Determine if type T is a valid subject for a nonnull and similar /// attributes. By default, we look through references (the behavior used by /// nonnull), but if the second parameter is true, then we treat a reference diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 862f9d4ffb825d..e8bff07ced0cfa 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -27,6 +27,7 @@ add_clang_library(clangSema Sema.cpp SemaAccess.cpp SemaAttr.cpp + SemaAPINotes.cpp SemaAvailability.cpp SemaCXXScopeSpec.cpp SemaCast.cpp diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp new file mode 100644 index 00..836c633e9d2042 --- /dev/null +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -0,0 +1,988 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsSubstitution_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsSubstitution_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsSubstitution_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNull
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + auto IsUnmodified = [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> bool { +QualType Original = QT; +S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), +isa(D), +/*OverrideExisting=*/true); +return QT.getTypePtr() == Original.getTypePtr(); + }; + + if (auto Function = dyn_cast(D)) { +if (IsUnmodified(D, Function->getReturnType(), Nullability)) { egorzhdan wrote: Oops, my bad, fixed. https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/78445 >From 2e4aa8640d208767a3f560516f1b3fd8c31dee3f Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Jan 2024 13:41:25 + Subject: [PATCH] [APINotes] Upstream Sema logic to apply API Notes to decls This upstreams more of the Clang API Notes functionality that is currently implemented in the Apple fork: https://github.com/apple/llvm-project/tree/next/clang/lib/APINotes --- .../clang/Basic/DiagnosticSemaKinds.td| 7 + clang/include/clang/Sema/Sema.h | 6 + clang/lib/Sema/CMakeLists.txt | 1 + clang/lib/Sema/SemaAPINotes.cpp | 989 ++ clang/lib/Sema/SemaDecl.cpp | 4 + clang/lib/Sema/SemaDeclAttr.cpp | 3 + clang/lib/Sema/SemaDeclCXX.cpp| 6 +- clang/lib/Sema/SemaDeclObjC.cpp | 4 + clang/lib/Sema/SemaObjCProperty.cpp | 5 + clang/lib/Sema/SemaTemplate.cpp | 7 + 10 files changed, 1031 insertions(+), 1 deletion(-) create mode 100644 clang/lib/Sema/SemaAPINotes.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ebda201361fb07..887d6120f48d2c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10760,6 +10760,13 @@ def warn_imp_cast_drops_unaligned : Warning< } // end of sema category +let CategoryName = "API Notes Issue" in { + +def err_incompatible_replacement_type : Error< + "API notes replacement type %0 has a different size from original type %1">; + +} // end of API Notes category + let CategoryName = "OpenMP Issue" in { // OpenMP support. def err_omp_expected_var_arg : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fcccac10f4733a..77749372b7fb65 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4883,6 +4883,12 @@ class Sema final { bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, bool SkipArgCountCheck = false); + /// Map any API notes provided for this declaration to attributes on the + /// declaration. + /// + /// Triggered by declaration-attribute processing. + void ProcessAPINotes(Decl *D); + /// Determine if type T is a valid subject for a nonnull and similar /// attributes. By default, we look through references (the behavior used by /// nonnull), but if the second parameter is true, then we treat a reference diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 862f9d4ffb825d..e8bff07ced0cfa 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -27,6 +27,7 @@ add_clang_library(clangSema Sema.cpp SemaAccess.cpp SemaAttr.cpp + SemaAPINotes.cpp SemaAvailability.cpp SemaCXXScopeSpec.cpp SemaCast.cpp diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp new file mode 100644 index 00..e75df0653c1f9b --- /dev/null +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullabi
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
@@ -0,0 +1,1014 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum IsActive_t : bool { IsNotActive, IsActive }; +enum IsReplacement_t : bool { IsNotReplacement, IsReplacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::IsActive), +IsReplacement(Replacement == IsReplacement_t::IsReplacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isMultiLevelPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, + VersionedInfoMetadata Metadata) { + if (!Metadata.IsActive) +return; + + QualType Type; + + // Nullability for a function/method appertains to the retain type. + if (auto Function = dyn_cast(D)) +Type = Function->getReturnType(); + else if (auto Method = dyn_cast(D)) +Type = Method->getReturnType(); + else if (auto Value = dyn_cast(D)) +Type = Value->getType(); + else if (auto Property = dyn_cast(D)) +Type = Property->getType(); + else +return; + + // Check the nullability specifier on this type. + QualType OrigType = Type; + S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(), + isa(D), + /*overrideExisting=*/true); + if (Type.getTypePtr() == OrigType.getTypePtr()) +return; egorzhdan wrote: Ah, I see, thanks for explaining! Done https://github.com/llvm/llvm-project/pull/78445 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)
https://github.com/egorzhdan updated https://github.com/llvm/llvm-project/pull/78445 >From 40a6247d20e121d9dea0ff83a61f5e7abba7bba6 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Jan 2024 13:41:25 + Subject: [PATCH] [APINotes] Upstream Sema logic to apply API Notes to decls This upstreams more of the Clang API Notes functionality that is currently implemented in the Apple fork: https://github.com/apple/llvm-project/tree/next/clang/lib/APINotes --- .../clang/Basic/DiagnosticSemaKinds.td| 7 + clang/include/clang/Sema/Sema.h | 6 + clang/lib/Sema/CMakeLists.txt | 1 + clang/lib/Sema/SemaAPINotes.cpp | 989 ++ clang/lib/Sema/SemaDecl.cpp | 4 + clang/lib/Sema/SemaDeclAttr.cpp | 3 + clang/lib/Sema/SemaDeclCXX.cpp| 6 +- clang/lib/Sema/SemaDeclObjC.cpp | 4 + clang/lib/Sema/SemaObjCProperty.cpp | 5 + clang/lib/Sema/SemaTemplate.cpp | 7 + 10 files changed, 1031 insertions(+), 1 deletion(-) create mode 100644 clang/lib/Sema/SemaAPINotes.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ebda201361fb07..887d6120f48d2c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10760,6 +10760,13 @@ def warn_imp_cast_drops_unaligned : Warning< } // end of sema category +let CategoryName = "API Notes Issue" in { + +def err_incompatible_replacement_type : Error< + "API notes replacement type %0 has a different size from original type %1">; + +} // end of API Notes category + let CategoryName = "OpenMP Issue" in { // OpenMP support. def err_omp_expected_var_arg : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fcccac10f4733a..77749372b7fb65 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4883,6 +4883,12 @@ class Sema final { bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, bool SkipArgCountCheck = false); + /// Map any API notes provided for this declaration to attributes on the + /// declaration. + /// + /// Triggered by declaration-attribute processing. + void ProcessAPINotes(Decl *D); + /// Determine if type T is a valid subject for a nonnull and similar /// attributes. By default, we look through references (the behavior used by /// nonnull), but if the second parameter is true, then we treat a reference diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 862f9d4ffb825d..e8bff07ced0cfa 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -27,6 +27,7 @@ add_clang_library(clangSema Sema.cpp SemaAccess.cpp SemaAttr.cpp + SemaAPINotes.cpp SemaAvailability.cpp SemaCXXScopeSpec.cpp SemaCast.cpp diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp new file mode 100644 index 00..594d73753a80e0 --- /dev/null +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -0,0 +1,989 @@ +//===--- SemaAPINotes.cpp - API Notes Handling ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file implements the mapping from API notes to declaration attributes. +// +//===--===// + +#include "clang/APINotes/APINotesReader.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/SemaInternal.h" + +using namespace clang; + +namespace { +enum class IsActive_t : bool { Inactive, Active }; +enum class IsReplacement_t : bool { Original, Replacement }; + +struct VersionedInfoMetadata { + /// An empty version refers to unversioned metadata. + VersionTuple Version; + unsigned IsActive : 1; + unsigned IsReplacement : 1; + + VersionedInfoMetadata(VersionTuple Version, IsActive_t Active, +IsReplacement_t Replacement) + : Version(Version), IsActive(Active == IsActive_t::Active), +IsReplacement(Replacement == IsReplacement_t::Replacement) {} +}; +} // end anonymous namespace + +/// Determine whether this is a multi-level pointer type. +static bool isIndirectPointerType(QualType Type) { + QualType Pointee = Type->getPointeeType(); + if (Pointee.isNull()) +return false; + + return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() || + Pointee->isMemberPointerType(); +} + +/// Apply nullability to the given declaration. +static void applyNullabi