[clang] [APINotes] Avoid repeated hash lookups (NFC) (PR #107959)

2024-09-10 Thread Egor Zhdan via cfe-commits

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)

2024-08-16 Thread Egor Zhdan via cfe-commits

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)

2024-08-14 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-08-14 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-08-14 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-08-14 Thread Egor Zhdan via cfe-commits

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)

2024-08-14 Thread Egor Zhdan via cfe-commits

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)

2024-08-14 Thread Egor Zhdan via cfe-commits

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)

2024-08-13 Thread Egor Zhdan via cfe-commits

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)

2024-08-12 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-08-12 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-08-12 Thread Egor Zhdan via cfe-commits

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)

2024-08-09 Thread Egor Zhdan via cfe-commits

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)

2024-07-29 Thread Egor Zhdan via cfe-commits

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)

2024-07-29 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-29 Thread Egor Zhdan via cfe-commits

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)

2024-07-29 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-29 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-29 Thread Egor Zhdan via cfe-commits

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)

2024-07-22 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-22 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-22 Thread Egor Zhdan via cfe-commits

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)

2024-07-22 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-22 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits

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)

2024-07-19 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-19 Thread Egor Zhdan via cfe-commits

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)

2024-07-19 Thread Egor Zhdan via cfe-commits

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)

2024-07-18 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-18 Thread Egor Zhdan via cfe-commits

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)

2024-07-18 Thread Egor Zhdan via cfe-commits

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)

2024-07-18 Thread Egor Zhdan via cfe-commits

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)

2024-07-18 Thread Egor Zhdan via cfe-commits

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)

2024-07-17 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-17 Thread Egor Zhdan via cfe-commits

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)

2024-07-17 Thread Egor Zhdan via cfe-commits

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)

2024-07-17 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-07-17 Thread Egor Zhdan via cfe-commits

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)

2024-07-16 Thread Egor Zhdan via cfe-commits

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)

2024-07-16 Thread Egor Zhdan via cfe-commits

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)

2024-07-15 Thread Egor Zhdan via cfe-commits

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)

2024-07-10 Thread Egor Zhdan via cfe-commits

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)

2024-07-09 Thread Egor Zhdan via cfe-commits

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)

2024-07-09 Thread Egor Zhdan via cfe-commits

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)

2024-06-12 Thread Egor Zhdan via cfe-commits

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)

2024-06-12 Thread Egor Zhdan via cfe-commits

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)

2024-06-11 Thread Egor Zhdan via cfe-commits

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)

2024-06-11 Thread Egor Zhdan via cfe-commits

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)

2024-05-13 Thread Egor Zhdan via cfe-commits

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)

2024-04-29 Thread Egor Zhdan via cfe-commits

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)

2024-04-29 Thread Egor Zhdan via cfe-commits

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)

2024-04-29 Thread Egor Zhdan via cfe-commits

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)

2024-04-26 Thread Egor Zhdan via cfe-commits

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)

2024-04-26 Thread Egor Zhdan via cfe-commits

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)

2024-04-25 Thread Egor Zhdan via cfe-commits

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)

2024-04-25 Thread Egor Zhdan via cfe-commits

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)

2024-04-25 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-04-25 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-04-25 Thread Egor Zhdan via cfe-commits

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)

2024-04-25 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-04-25 Thread Egor Zhdan via cfe-commits

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)

2024-04-25 Thread Egor Zhdan via cfe-commits

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)

2024-03-29 Thread Egor Zhdan via cfe-commits

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)

2024-03-28 Thread Egor Zhdan via cfe-commits

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)

2024-03-28 Thread Egor Zhdan via cfe-commits

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)

2024-03-27 Thread Egor Zhdan via cfe-commits

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)

2024-03-27 Thread Egor Zhdan via cfe-commits

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)

2024-03-27 Thread Egor Zhdan via cfe-commits

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)

2024-03-25 Thread Egor Zhdan via cfe-commits

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)

2024-03-20 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-03-20 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-03-20 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-03-20 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-03-11 Thread Egor Zhdan via cfe-commits

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)

2024-03-11 Thread Egor Zhdan via cfe-commits

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)

2024-03-11 Thread Egor Zhdan via cfe-commits

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)

2024-03-11 Thread Egor Zhdan via cfe-commits

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)

2024-03-11 Thread Egor Zhdan via cfe-commits

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)

2024-03-08 Thread Egor Zhdan via cfe-commits

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)

2024-03-08 Thread Egor Zhdan via cfe-commits

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)

2024-02-26 Thread Egor Zhdan via cfe-commits

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)

2024-02-26 Thread Egor Zhdan via cfe-commits

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)

2024-02-26 Thread Egor Zhdan via cfe-commits

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)

2024-02-26 Thread Egor Zhdan via cfe-commits

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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-26 Thread Egor Zhdan via cfe-commits

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)

2024-02-23 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-23 Thread Egor Zhdan via cfe-commits

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)

2024-02-23 Thread Egor Zhdan via cfe-commits


@@ -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)

2024-02-23 Thread Egor Zhdan via cfe-commits

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

  1   2   3   >