[clang] 8c09352 - [libclang] Fix conversion from `StringRef` to `CXString`

2022-08-31 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-08-31T17:39:45+01:00
New Revision: 8c0935238527622ba0a7e78e8a1ee2d36026961c

URL: 
https://github.com/llvm/llvm-project/commit/8c0935238527622ba0a7e78e8a1ee2d36026961c
DIFF: 
https://github.com/llvm/llvm-project/commit/8c0935238527622ba0a7e78e8a1ee2d36026961c.diff

LOG: [libclang] Fix conversion from `StringRef` to `CXString`

`CXString createRef(StringRef String)` used to return an invalid string when 
invoked with some empty strings:

If a `StringRef` holds a non-nullptr pointer, for instance, pointing into 
contents of a larger string, and has a zero length, `createRef` previously 
returned the entire larger string, ignoring the fact that the actual string 
passed to it as a param is empty.

This was discovered when invoking `c-index-test` to dump the contents of 
documentation comments, in case the comment contains an empty HTML attribute, 
such as `src=""`.

Differential Revision: https://reviews.llvm.org/D133009

Added: 


Modified: 
clang/test/Index/comment-lots-of-unknown-commands.c
clang/test/Index/comment-to-html-xml-conversion.cpp
clang/tools/libclang/CXString.cpp

Removed: 




diff  --git a/clang/test/Index/comment-lots-of-unknown-commands.c 
b/clang/test/Index/comment-lots-of-unknown-commands.c
index 119a34566094c..41a03d394488c 100644
--- a/clang/test/Index/comment-lots-of-unknown-commands.c
+++ b/clang/test/Index/comment-lots-of-unknown-commands.c
@@ -1,5 +1,7 @@
 // RUN: c-index-test -test-load-source-reparse 1 local %s | FileCheck %s
 
+// XFAIL: *
+
 // See PR 21254. We had too few bits to encode command IDs so if you created
 // enough of them the ID codes would wrap around. This test creates commands up
 // to an ID of 258. Ideally we should check for large numbers, but that would

diff  --git a/clang/test/Index/comment-to-html-xml-conversion.cpp 
b/clang/test/Index/comment-to-html-xml-conversion.cpp
index bba5cf8f0bf42..1fedd382365cf 100644
--- a/clang/test/Index/comment-to-html-xml-conversion.cpp
+++ b/clang/test/Index/comment-to-html-xml-conversion.cpp
@@ -744,6 +744,15 @@ void comment_to_html_conversion_37();
 // CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
 // CHECK-NEXT: (CXComment_InlineCommand CommandName=[anchor] 
RenderAnchor Arg[0]=A)))]
 
+/// Aaa ccc
+void comment_to_html_conversion_40();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_40:{{.*}} FullCommentAsHTML=[ Aaa ccc] FullCommentAsXML=[comment_to_html_conversion_40c:@F@comment_to_html_conversion_40#void
 comment_to_html_conversion_40() Aaa 
ccc]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// CHECK-NEXT:   (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa ccc])
+// CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] Attrs: src=)
 
 /// Aaa.
 class comment_to_xml_conversion_01 {

diff  --git a/clang/tools/libclang/CXString.cpp 
b/clang/tools/libclang/CXString.cpp
index 2754795f4a647..5e427957a1092 100644
--- a/clang/tools/libclang/CXString.cpp
+++ b/clang/tools/libclang/CXString.cpp
@@ -78,13 +78,22 @@ CXString createDup(const char *String) {
 }
 
 CXString createRef(StringRef String) {
+  if (!String.data())
+return createNull();
+
+  // If the string is empty, it might point to a position in another string
+  // while having zero length. Make sure we don't create a reference to the
+  // larger string.
+  if (String.empty())
+return createEmpty();
+
   // If the string is not nul-terminated, we have to make a copy.
 
   // FIXME: This is doing a one past end read, and should be removed! For 
memory
   // we don't manage, the API string can become unterminated at any time 
outside
   // our control.
 
-  if (!String.empty() && String.data()[String.size()] != 0)
+  if (String.data()[String.size()] != 0)
 return createDup(String);
 
   CXString Result;



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 0cb0809 - [Clang][Comments] Parse `` in doc comments correctly

2022-09-01 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-09-01T13:17:42+01:00
New Revision: 0cb08093365478224f2a58cece42527fb8e1199e

URL: 
https://github.com/llvm/llvm-project/commit/0cb08093365478224f2a58cece42527fb8e1199e
DIFF: 
https://github.com/llvm/llvm-project/commit/0cb08093365478224f2a58cece42527fb8e1199e.diff

LOG: [Clang][Comments] Parse `` in doc comments correctly

This is a valid HTML5 tag. Previously it triggered a Clang error (`HTML start 
tag prematurely ended, expected attribute name or '>'`) since Clang was 
treating `/>` as a text token. This was happening because after lexing the 
closing quote (`"`) the lexer state was reset to "Normal" while the tag was not 
actually closed yet: `>` was not yet parsed at that point.

rdar://91464292

Differential Revision: https://reviews.llvm.org/D132932

Added: 


Modified: 
clang/lib/AST/CommentLexer.cpp
clang/test/Index/comment-to-html-xml-conversion.cpp
clang/test/Sema/warn-documentation.cpp

Removed: 




diff  --git a/clang/lib/AST/CommentLexer.cpp b/clang/lib/AST/CommentLexer.cpp
index 61ce8979f13f5..f0250fc9fd55e 100644
--- a/clang/lib/AST/CommentLexer.cpp
+++ b/clang/lib/AST/CommentLexer.cpp
@@ -701,7 +701,7 @@ void Lexer::lexHTMLStartTag(Token &T) {
 
   C = *BufferPtr;
   if (!isHTMLIdentifierStartingCharacter(C) &&
-  C != '=' && C != '\"' && C != '\'' && C != '>') {
+  C != '=' && C != '\"' && C != '\'' && C != '>' && C != '/') {
 State = LS_Normal;
 return;
   }

diff  --git a/clang/test/Index/comment-to-html-xml-conversion.cpp 
b/clang/test/Index/comment-to-html-xml-conversion.cpp
index 1fedd382365cf..ec49e5af31da1 100644
--- a/clang/test/Index/comment-to-html-xml-conversion.cpp
+++ b/clang/test/Index/comment-to-html-xml-conversion.cpp
@@ -744,6 +744,26 @@ void comment_to_html_conversion_37();
 // CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
 // CHECK-NEXT: (CXComment_InlineCommand CommandName=[anchor] 
RenderAnchor Arg[0]=A)))]
 
+/// Aaa bbb
+void comment_to_html_conversion_38();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_38:{{.*}} FullCommentAsHTML=[ Aaa bbb] FullCommentAsXML=[comment_to_html_conversion_38c:@F@comment_to_html_conversion_38#void
 comment_to_html_conversion_38() Aaa 
bbb]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// CHECK-NEXT:   (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa bbb])
+// CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] SelfClosing)
+
+/// Aaa ccc
+void comment_to_html_conversion_39();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_39:{{.*}} FullCommentAsHTML=[ Aaa ccc] FullCommentAsXML=[comment_to_html_conversion_39c:@F@comment_to_html_conversion_39#void
 comment_to_html_conversion_39() Aaa 
ccc]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// CHECK-NEXT:   (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa ccc])
+// CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] SelfClosing)
+
 /// Aaa ccc
 void comment_to_html_conversion_40();
 
@@ -754,6 +774,36 @@ void comment_to_html_conversion_40();
 // CHECK-NEXT: (CXComment_Text Text=[ Aaa ccc])
 // CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] Attrs: src=)
 
+/// Aaa ccc
+void comment_to_html_conversion_41();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_41:{{.*}} FullCommentAsHTML=[ Aaa ccc] FullCommentAsXML=[comment_to_html_conversion_41c:@F@comment_to_html_conversion_41#void
 comment_to_html_conversion_41() Aaa 
ccc]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// CHECK-NEXT:   (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa ccc])
+// CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] Attrs: src=path)
+
+/// Aaa ccc
+void comment_to_html_conversion_42();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_42:{{.*}} FullCommentAsHTML=[ Aaa ccc] FullCommentAsXML=[comment_to_html_conversion_42c:@F@comment_to_html_conversion_42#void
 comment_to_html_conversion_42() Aaa 
ccc]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// CHECK-NEXT:   (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa ccc])
+// CHECK-NEXT: (CXComment_HTMLStartTag Name=[img] Attrs: src=path 
SelfClosing)
+
+/// Aaa ddd
+void comment_to_html_conversion_43();
+
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: 
FunctionDecl=comment_to_html_conversion_43:{{.*}} FullCommentAsHTML=[ Aaa ddd] FullCommentAsXML=[comment_to_html_conversion_43c:@F@comment_to_html_conversion_43#void
 comment_to_html_conversion_43() Aaa 
ddd]
+// CHECK-NEXT:  CommentAST=[
+// CHECK-NEXT:(CXComment_FullComment
+// 

[clang] 7c232b0 - [Clang][Comments] Fix `Index/comment-lots-of-unknown-commands.c`

2022-09-02 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-09-02T12:34:38+01:00
New Revision: 7c232b0867209a8f487bbcabca9289e9ef313bef

URL: 
https://github.com/llvm/llvm-project/commit/7c232b0867209a8f487bbcabca9289e9ef313bef
DIFF: 
https://github.com/llvm/llvm-project/commit/7c232b0867209a8f487bbcabca9289e9ef313bef.diff

LOG: [Clang][Comments] Fix `Index/comment-lots-of-unknown-commands.c`

This re-enables a test after it was disabled in 
https://reviews.llvm.org/D133009.

Fixes #57484.

Differential Revision: https://reviews.llvm.org/D133105

Added: 


Modified: 
clang/test/Index/comment-lots-of-unknown-commands.c

Removed: 




diff  --git a/clang/test/Index/comment-lots-of-unknown-commands.c 
b/clang/test/Index/comment-lots-of-unknown-commands.c
index 41a03d394488c..1de96762dc4ae 100644
--- a/clang/test/Index/comment-lots-of-unknown-commands.c
+++ b/clang/test/Index/comment-lots-of-unknown-commands.c
@@ -1,7 +1,5 @@
 // RUN: c-index-test -test-load-source-reparse 1 local %s | FileCheck %s
 
-// XFAIL: *
-
 // See PR 21254. We had too few bits to encode command IDs so if you created
 // enough of them the ID codes would wrap around. This test creates commands up
 // to an ID of 258. Ideally we should check for large numbers, but that would
@@ -37,7 +35,7 @@
 @ei
 @oun
 @ou
-@nl
+@nlnl
 @ien
 @fr
 @en
@@ -58,7 +56,7 @@
 @fro
 @ast
 @ae
-@nN
+@nNnN
 @pc
 @tae
 @ws
@@ -122,10 +120,10 @@
 @an
 @de
 @tel
-@nd
-@dic
+@ndnd
+@dict
 @Lo
-@il
+@ilil
 @tle
 @axt
 @ba
@@ -137,7 +135,7 @@
 @ru
 @m
 @tG
-@it
+@itit
 @rh
 @G
 @rpc
@@ -183,7 +181,7 @@ void f();
 // CHECK: (CXComment_InlineCommand CommandName=[ei] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[oun] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ou] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[nl] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[nlnl] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ien] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[fr] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[en] RenderNormal 
HasTrailingNewline)
@@ -204,7 +202,7 @@ void f();
 // CHECK: (CXComment_InlineCommand CommandName=[fro] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ast] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ae] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[nN] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[nNnN] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[pc] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[tae] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ws] RenderNormal 
HasTrailingNewline)
@@ -268,10 +266,10 @@ void f();
 // CHECK: (CXComment_InlineCommand CommandName=[an] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[de] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[tel] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[nd] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[dic] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[ndnd] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[dict] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[Lo] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[il] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[ilil] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[tle] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[axt] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[ba] RenderNormal 
HasTrailingNewline)
@@ -283,7 +281,7 @@ void f();
 // CHECK: (CXComment_InlineCommand CommandName=[ru] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[m] RenderNormal 
HasTrailingNewline)
 // CHECK: (CXComment_InlineCommand CommandName=[tG] RenderNormal 
HasTrailingNewline)
-// CHECK: (CXComment_InlineCommand CommandName=[it] RenderNormal 
HasTrailingNewline)
+// CHECK: (CXComment_InlineCommand CommandName=[itit] RenderNormal 
HasTrailingNewline)
 // CHECK:  

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

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

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/71413

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

>From f80d68edf0787821531c0f88d845b253703ef13e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:41:19 +
Subject: [PATCH 1/2] [APINotes] NFC: rename `StoredObjCSelector::NumPieces`

This value actually represents a number of arguments the selector takes, not 
the number of identifiers. These will be different if the selector takes no 
arguments.
---
 clang/lib/APINotes/APINotesFormat.h   | 6 +++---
 clang/lib/APINotes/APINotesReader.cpp | 2 +-
 clang/lib/APINotes/APINotesWriter.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 5897b45d3796d0e..615314c46f09cac 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -247,7 +247,7 @@ using EnumConstantDataLayout =
 
 /// A stored Objective-C selector.
 struct StoredObjCSelector {
-  unsigned NumPieces;
+  unsigned NumArgs;
   llvm::SmallVector Identifiers;
 };
 
@@ -302,7 +302,7 @@ template <> struct 
DenseMapInfo {
 
   static unsigned
   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
-auto hash = llvm::hash_value(Selector.NumPieces);
+auto hash = llvm::hash_value(Selector.NumArgs);
 hash = hash_combine(hash, Selector.Identifiers.size());
 for (auto piece : Selector.Identifiers)
   hash = hash_combine(hash, static_cast(piece));
@@ -313,7 +313,7 @@ template <> struct 
DenseMapInfo {
 
   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
   const clang::api_notes::StoredObjCSelector &RHS) {
-return LHS.NumPieces == RHS.NumPieces && LHS.Identifiers == 
RHS.Identifiers;
+return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
   }
 };
 
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 2cbf5fd3bf50301..01177b9b1d04dde 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -421,7 +421,7 @@ class ObjCSelectorTableInfo {
 
   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
 internal_key_type Key;
-Key.NumPieces =
+Key.NumArgs =
 endian::readNext(Data);
 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
 for (unsigned i = 0; i != NumIdents; ++i) {
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 770d78e22050c01..62a2ab1799913a1 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -823,7 +823,7 @@ class ObjCSelectorTableInfo {
 
   void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
-writer.write(Key.NumPieces);
+writer.write(Key.NumArgs);
 for (auto Identifier : Key.Identifiers)
   writer.write(Identifier);
   }

>From 903b4f72f914c64698a468adbba8a7af992bc9aa Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:45:11 +
Subject: [PATCH 2/2] [APINotes] Upstream APINotes YAML compiler

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/APINotes/APINotesYAMLCompiler.h |  11 +
 clang/include/clang/APINotes/Types.h  |   1 +
 clang/lib/APINotes/APINotesReader.cpp |   1 +
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 498 +-
 4 files changed, 510 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/APINotes/APINotesYAMLCompiler.h 
b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
index 6098d0ee36fc477..9c24ed85b6a124a 100644
--- a/clang/include/clang/APINotes/APINotesYAMLCompiler.h
+++ b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
@@ -10,14 +10,25 @@
 #define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang {
+class FileEntry;
+} // namespace clang
+
 namespace clang {
 namespace api_notes {
 /// Parses the APINotes YAML content and writes the representation back to the
 /// specified stream.  This provides a means of testing the YAML processing of
 /// the APINotes format.
 bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
+
+/// Converts API notes from YAML format to binary format.
+bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
+ llvm::raw_ostream &OS,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
 } // namesp

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/71413

>From f80d68edf0787821531c0f88d845b253703ef13e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:41:19 +
Subject: [PATCH 1/2] [APINotes] NFC: rename `StoredObjCSelector::NumPieces`

This value actually represents a number of arguments the selector takes, not 
the number of identifiers. These will be different if the selector takes no 
arguments.
---
 clang/lib/APINotes/APINotesFormat.h   | 6 +++---
 clang/lib/APINotes/APINotesReader.cpp | 2 +-
 clang/lib/APINotes/APINotesWriter.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 5897b45d3796d0e..615314c46f09cac 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -247,7 +247,7 @@ using EnumConstantDataLayout =
 
 /// A stored Objective-C selector.
 struct StoredObjCSelector {
-  unsigned NumPieces;
+  unsigned NumArgs;
   llvm::SmallVector Identifiers;
 };
 
@@ -302,7 +302,7 @@ template <> struct 
DenseMapInfo {
 
   static unsigned
   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
-auto hash = llvm::hash_value(Selector.NumPieces);
+auto hash = llvm::hash_value(Selector.NumArgs);
 hash = hash_combine(hash, Selector.Identifiers.size());
 for (auto piece : Selector.Identifiers)
   hash = hash_combine(hash, static_cast(piece));
@@ -313,7 +313,7 @@ template <> struct 
DenseMapInfo {
 
   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
   const clang::api_notes::StoredObjCSelector &RHS) {
-return LHS.NumPieces == RHS.NumPieces && LHS.Identifiers == 
RHS.Identifiers;
+return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
   }
 };
 
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 2cbf5fd3bf50301..01177b9b1d04dde 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -421,7 +421,7 @@ class ObjCSelectorTableInfo {
 
   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
 internal_key_type Key;
-Key.NumPieces =
+Key.NumArgs =
 endian::readNext(Data);
 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
 for (unsigned i = 0; i != NumIdents; ++i) {
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 770d78e22050c01..62a2ab1799913a1 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -823,7 +823,7 @@ class ObjCSelectorTableInfo {
 
   void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
-writer.write(Key.NumPieces);
+writer.write(Key.NumArgs);
 for (auto Identifier : Key.Identifiers)
   writer.write(Identifier);
   }

>From 912092a4a8a815b4b6b449842cb028f564f829f6 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:45:11 +
Subject: [PATCH 2/2] [APINotes] Upstream APINotes YAML compiler

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/APINotes/APINotesYAMLCompiler.h |  11 +
 clang/include/clang/APINotes/Types.h  |   1 +
 clang/lib/APINotes/APINotesReader.cpp |   1 +
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 479 +-
 4 files changed, 491 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/APINotes/APINotesYAMLCompiler.h 
b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
index 6098d0ee36fc477..9c24ed85b6a124a 100644
--- a/clang/include/clang/APINotes/APINotesYAMLCompiler.h
+++ b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
@@ -10,14 +10,25 @@
 #define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang {
+class FileEntry;
+} // namespace clang
+
 namespace clang {
 namespace api_notes {
 /// Parses the APINotes YAML content and writes the representation back to the
 /// specified stream.  This provides a means of testing the YAML processing of
 /// the APINotes format.
 bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
+
+/// Converts API notes from YAML format to binary format.
+bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
+ llvm::raw_ostream &OS,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
 } // namespace api_notes
 } // namespace clang
 
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index b74244bc8f1cbd3..79595abcf7d02d9 100644
--

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{

egorzhdan wrote:

Alright, done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;

egorzhdan wrote:

Don't think there is a good reason, removed the return type

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }

egorzhdan wrote:

This underflows `offset`, but I simplified this bit of code another way by 
using `resize`

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,

egorzhdan wrote:

Makes sense, renamed it

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");

egorzhdan wrote:

This has two usages below

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}

egorzhdan wrote:

Looks better indeed, thanks!

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;

egorzhdan wrote:

I renamed this to follow the upper-case conventions, would you prefer a 
different name? What does `seller` stand for?

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/71413

>From f80d68edf0787821531c0f88d845b253703ef13e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:41:19 +
Subject: [PATCH 1/2] [APINotes] NFC: rename `StoredObjCSelector::NumPieces`

This value actually represents a number of arguments the selector takes, not 
the number of identifiers. These will be different if the selector takes no 
arguments.
---
 clang/lib/APINotes/APINotesFormat.h   | 6 +++---
 clang/lib/APINotes/APINotesReader.cpp | 2 +-
 clang/lib/APINotes/APINotesWriter.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 5897b45d3796d0e..615314c46f09cac 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -247,7 +247,7 @@ using EnumConstantDataLayout =
 
 /// A stored Objective-C selector.
 struct StoredObjCSelector {
-  unsigned NumPieces;
+  unsigned NumArgs;
   llvm::SmallVector Identifiers;
 };
 
@@ -302,7 +302,7 @@ template <> struct 
DenseMapInfo {
 
   static unsigned
   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
-auto hash = llvm::hash_value(Selector.NumPieces);
+auto hash = llvm::hash_value(Selector.NumArgs);
 hash = hash_combine(hash, Selector.Identifiers.size());
 for (auto piece : Selector.Identifiers)
   hash = hash_combine(hash, static_cast(piece));
@@ -313,7 +313,7 @@ template <> struct 
DenseMapInfo {
 
   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
   const clang::api_notes::StoredObjCSelector &RHS) {
-return LHS.NumPieces == RHS.NumPieces && LHS.Identifiers == 
RHS.Identifiers;
+return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
   }
 };
 
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 2cbf5fd3bf50301..01177b9b1d04dde 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -421,7 +421,7 @@ class ObjCSelectorTableInfo {
 
   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
 internal_key_type Key;
-Key.NumPieces =
+Key.NumArgs =
 endian::readNext(Data);
 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
 for (unsigned i = 0; i != NumIdents; ++i) {
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 770d78e22050c01..62a2ab1799913a1 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -823,7 +823,7 @@ class ObjCSelectorTableInfo {
 
   void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
-writer.write(Key.NumPieces);
+writer.write(Key.NumArgs);
 for (auto Identifier : Key.Identifiers)
   writer.write(Identifier);
   }

>From a95d72d013f31511350fb263c27afbc41ff7744b Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:45:11 +
Subject: [PATCH 2/2] [APINotes] Upstream APINotes YAML compiler

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/APINotes/APINotesYAMLCompiler.h |  11 +
 clang/include/clang/APINotes/Types.h  |   1 +
 clang/lib/APINotes/APINotesReader.cpp |   1 +
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 474 +-
 4 files changed, 486 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/APINotes/APINotesYAMLCompiler.h 
b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
index 6098d0ee36fc477..9c24ed85b6a124a 100644
--- a/clang/include/clang/APINotes/APINotesYAMLCompiler.h
+++ b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
@@ -10,14 +10,25 @@
 #define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang {
+class FileEntry;
+} // namespace clang
+
 namespace clang {
 namespace api_notes {
 /// Parses the APINotes YAML content and writes the representation back to the
 /// specified stream.  This provides a means of testing the YAML processing of
 /// the APINotes format.
 bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
+
+/// Converts API notes from YAML format to binary format.
+bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
+ llvm::raw_ostream &OS,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
 } // namespace api_notes
 } // namespace clang
 
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index b74244bc8f1cbd3..79595abcf7d02d9 100644
--

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/71413

>From f80d68edf0787821531c0f88d845b253703ef13e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:41:19 +
Subject: [PATCH 1/2] [APINotes] NFC: rename `StoredObjCSelector::NumPieces`

This value actually represents a number of arguments the selector takes, not 
the number of identifiers. These will be different if the selector takes no 
arguments.
---
 clang/lib/APINotes/APINotesFormat.h   | 6 +++---
 clang/lib/APINotes/APINotesReader.cpp | 2 +-
 clang/lib/APINotes/APINotesWriter.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 5897b45d3796d0e..615314c46f09cac 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -247,7 +247,7 @@ using EnumConstantDataLayout =
 
 /// A stored Objective-C selector.
 struct StoredObjCSelector {
-  unsigned NumPieces;
+  unsigned NumArgs;
   llvm::SmallVector Identifiers;
 };
 
@@ -302,7 +302,7 @@ template <> struct 
DenseMapInfo {
 
   static unsigned
   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
-auto hash = llvm::hash_value(Selector.NumPieces);
+auto hash = llvm::hash_value(Selector.NumArgs);
 hash = hash_combine(hash, Selector.Identifiers.size());
 for (auto piece : Selector.Identifiers)
   hash = hash_combine(hash, static_cast(piece));
@@ -313,7 +313,7 @@ template <> struct 
DenseMapInfo {
 
   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
   const clang::api_notes::StoredObjCSelector &RHS) {
-return LHS.NumPieces == RHS.NumPieces && LHS.Identifiers == 
RHS.Identifiers;
+return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
   }
 };
 
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 2cbf5fd3bf50301..01177b9b1d04dde 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -421,7 +421,7 @@ class ObjCSelectorTableInfo {
 
   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
 internal_key_type Key;
-Key.NumPieces =
+Key.NumArgs =
 endian::readNext(Data);
 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
 for (unsigned i = 0; i != NumIdents; ++i) {
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 770d78e22050c01..62a2ab1799913a1 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -823,7 +823,7 @@ class ObjCSelectorTableInfo {
 
   void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
-writer.write(Key.NumPieces);
+writer.write(Key.NumArgs);
 for (auto Identifier : Key.Identifiers)
   writer.write(Identifier);
   }

>From 59c1842e8c3ba87138186f089faf7218f8568455 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:45:11 +
Subject: [PATCH 2/2] [APINotes] Upstream APINotes YAML compiler

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/APINotes/APINotesYAMLCompiler.h |  11 +
 clang/include/clang/APINotes/Types.h  |   1 +
 clang/lib/APINotes/APINotesReader.cpp |   1 +
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 480 +-
 4 files changed, 492 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/APINotes/APINotesYAMLCompiler.h 
b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
index 6098d0ee36fc477..9c24ed85b6a124a 100644
--- a/clang/include/clang/APINotes/APINotesYAMLCompiler.h
+++ b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
@@ -10,14 +10,25 @@
 #define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang {
+class FileEntry;
+} // namespace clang
+
 namespace clang {
 namespace api_notes {
 /// Parses the APINotes YAML content and writes the representation back to the
 /// specified stream.  This provides a means of testing the YAML processing of
 /// the APINotes format.
 bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
+
+/// Converts API notes from YAML format to binary format.
+bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
+ llvm::raw_ostream &OS,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
 } // namespace api_notes
 } // namespace clang
 
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index b74244bc8f1cbd3..79595abcf7d02d9 100644
--

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-10 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/71413

>From f80d68edf0787821531c0f88d845b253703ef13e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:41:19 +
Subject: [PATCH 1/2] [APINotes] NFC: rename `StoredObjCSelector::NumPieces`

This value actually represents a number of arguments the selector takes, not 
the number of identifiers. These will be different if the selector takes no 
arguments.
---
 clang/lib/APINotes/APINotesFormat.h   | 6 +++---
 clang/lib/APINotes/APINotesReader.cpp | 2 +-
 clang/lib/APINotes/APINotesWriter.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 5897b45d3796d0e..615314c46f09cac 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -247,7 +247,7 @@ using EnumConstantDataLayout =
 
 /// A stored Objective-C selector.
 struct StoredObjCSelector {
-  unsigned NumPieces;
+  unsigned NumArgs;
   llvm::SmallVector Identifiers;
 };
 
@@ -302,7 +302,7 @@ template <> struct 
DenseMapInfo {
 
   static unsigned
   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
-auto hash = llvm::hash_value(Selector.NumPieces);
+auto hash = llvm::hash_value(Selector.NumArgs);
 hash = hash_combine(hash, Selector.Identifiers.size());
 for (auto piece : Selector.Identifiers)
   hash = hash_combine(hash, static_cast(piece));
@@ -313,7 +313,7 @@ template <> struct 
DenseMapInfo {
 
   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
   const clang::api_notes::StoredObjCSelector &RHS) {
-return LHS.NumPieces == RHS.NumPieces && LHS.Identifiers == 
RHS.Identifiers;
+return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
   }
 };
 
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 2cbf5fd3bf50301..01177b9b1d04dde 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -421,7 +421,7 @@ class ObjCSelectorTableInfo {
 
   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
 internal_key_type Key;
-Key.NumPieces =
+Key.NumArgs =
 endian::readNext(Data);
 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
 for (unsigned i = 0; i != NumIdents; ++i) {
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 770d78e22050c01..62a2ab1799913a1 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -823,7 +823,7 @@ class ObjCSelectorTableInfo {
 
   void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
-writer.write(Key.NumPieces);
+writer.write(Key.NumArgs);
 for (auto Identifier : Key.Identifiers)
   writer.write(Identifier);
   }

>From 251611692dba90fc95df29c981821dd954de1e1d Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 6 Nov 2023 15:45:11 +
Subject: [PATCH 2/2] [APINotes] Upstream APINotes YAML compiler

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/APINotes/APINotesYAMLCompiler.h |  11 +
 clang/include/clang/APINotes/Types.h  |   1 +
 clang/lib/APINotes/APINotesReader.cpp |   1 +
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 478 +-
 4 files changed, 490 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/APINotes/APINotesYAMLCompiler.h 
b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
index 6098d0ee36fc477..9c24ed85b6a124a 100644
--- a/clang/include/clang/APINotes/APINotesYAMLCompiler.h
+++ b/clang/include/clang/APINotes/APINotesYAMLCompiler.h
@@ -10,14 +10,25 @@
 #define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang {
+class FileEntry;
+} // namespace clang
+
 namespace clang {
 namespace api_notes {
 /// Parses the APINotes YAML content and writes the representation back to the
 /// specified stream.  This provides a means of testing the YAML processing of
 /// the APINotes format.
 bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
+
+/// Converts API notes from YAML format to binary format.
+bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
+ llvm::raw_ostream &OS,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
 } // namespace api_notes
 } // namespace clang
 
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index b74244bc8f1cbd3..79595abcf7d02d9 100644
--

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,496 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &TheModule;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : TheModule(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  bool convertAvailability(const AvailabilityItem &In,
+   CommonEntityInfo &OutInfo, llvm::StringRef APIName) 
{
+// Populate the unavailability information.
+OutInfo.Unavailable = (In.Mode == APIAvailability::None);
+OutInfo.UnavailableInSwift = (In.Mode == APIAvailability::NonSwift);
+if (OutInfo.Unavailable || OutInfo.UnavailableInSwift) {
+  OutInfo.UnavailableMsg = std::string(In.Msg);
+} else {
+  if (!In.Msg.empty()) {
+emitError("availability message for available API '" + APIName +
+  "' will not be used");
+  }
+}
+return false;
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  while (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.push_back(ParamInfo());
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional NullabilityOfRet,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError("nullability info for " + APIName + " does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (auto i = Nullability.begin(), e = Nullability.end(); i != e;
+ ++i, ++idx) {
+  OutInfo.addTypeInfo(idx, *i);
+  audited = true;
+}
+if (NullabilityOfRet) {
+  OutInfo.addTypeInfo(0, *NullabilityOfRet);
+  audited = true;
+} else if (audited) {
+  OutInfo.addTypeInfo(0, NullabilityKind::NonNull);
+}
+if (audited) {
+  OutInfo.NullabilityAudited = audited;
+  OutInfo.NumAdjustedNullable = idx;
+}
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  bool convertCommon(const T &Common, CommonEntityInfo &Info,
+ StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+return false;
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  bool convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+if (convertCommon(Common, Info, APIName))
+  return true;
+
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+return false;
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &TheMethod, ContextID ClassID,
+ StringRef ClassName, VersionTuple SwiftVersion) {
+ObjCMethodInfo MInfo;
+
+if (convertCommon(TheMethod, MInfo, TheMethod.Selector))
+  return;
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = TheMethod.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector a;
+TheMethod.Selector.split(a, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && a.size() > 1) {
+  emitError("selector " + TheMethod.Selector +
+"is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef selectorRef;
+selectorRef.NumArgs = !takesArguments ? 0 : a.size();
+selectorRef.Identifiers = a;
+
+// Translate the initializer info.
+MInfo.DesignatedInit = TheMethod.DesignatedInit;
+MInfo.RequiredInit = TheMethod.Required;
+if (TheMethod.FactoryAsInit != FactoryAsInitKind::Infer) {
+  emitError("'Fact

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,478 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &M;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  void convertAvailability(const AvailabilityItem &Availability,
+   CommonEntityInfo &CEI, llvm::StringRef APIName) {
+// Populate the unavailability information.
+CEI.Unavailable = (Availability.Mode == APIAvailability::None);
+CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
+if (CEI.Unavailable || CEI.UnavailableInSwift) {
+  CEI.UnavailableMsg = std::string(Availability.Msg);
+} else {
+  if (!Availability.Msg.empty()) {
+emitError(llvm::Twine("availability message for available API '") +
+  APIName + "' will not be used");
+  }
+}
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  if (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.resize(P.Position + 1);
+  }

egorzhdan wrote:

Fixed

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,478 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &M;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  void convertAvailability(const AvailabilityItem &Availability,
+   CommonEntityInfo &CEI, llvm::StringRef APIName) {
+// Populate the unavailability information.
+CEI.Unavailable = (Availability.Mode == APIAvailability::None);
+CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
+if (CEI.Unavailable || CEI.UnavailableInSwift) {
+  CEI.UnavailableMsg = std::string(Availability.Msg);
+} else {
+  if (!Availability.Msg.empty()) {
+emitError(llvm::Twine("availability message for available API '") +
+  APIName + "' will not be used");
+  }
+}
+  }
+
+  void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {
+for (const auto &P : Params) {
+  ParamInfo PI;
+  if (P.Nullability)
+PI.setNullabilityAudited(*P.Nullability);
+  PI.setNoEscape(P.NoEscape);
+  PI.setType(std::string(P.Type));
+  PI.setRetainCountConvention(P.RetainCountConvention);
+  if (OutInfo.Params.size() <= P.Position) {
+OutInfo.Params.resize(P.Position + 1);
+  }
+  OutInfo.Params[P.Position] |= PI;
+}
+  }
+
+  void convertNullability(const NullabilitySeq &Nullability,
+  std::optional ReturnNullability,
+  FunctionInfo &OutInfo, llvm::StringRef APIName) {
+if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
+  emitError(llvm::Twine("nullability info for '") + APIName +
+"' does not fit");
+  return;
+}
+
+bool audited = false;
+unsigned int idx = 1;
+for (const auto &N : Nullability)
+  OutInfo.addTypeInfo(idx++, N);
+audited = Nullability.size() > 0 || ReturnNullability;
+if (audited)
+  OutInfo.addTypeInfo(0, ReturnNullability ? *ReturnNullability
+   : NullabilityKind::NonNull);
+if (!audited)
+  return;
+OutInfo.NullabilityAudited = audited;
+OutInfo.NumAdjustedNullable = idx;
+  }
+
+  /// Convert the common parts of an entity from YAML.
+  template 
+  void convertCommonEntity(const T &Common, CommonEntityInfo &Info,
+   StringRef APIName) {
+convertAvailability(Common.Availability, Info, APIName);
+Info.setSwiftPrivate(Common.SwiftPrivate);
+Info.SwiftName = std::string(Common.SwiftName);
+  }
+
+  /// Convert the common parts of a type entity from YAML.
+  template 
+  void convertCommonType(const T &Common, CommonTypeInfo &Info,
+ StringRef APIName) {
+convertCommonEntity(Common, Info, APIName);
+if (Common.SwiftBridge)
+  Info.setSwiftBridge(std::string(*Common.SwiftBridge));
+Info.setNSErrorDomain(Common.NSErrorDomain);
+  }
+
+  // Translate from Method into ObjCMethodInfo and write it out.
+  void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,
+ VersionTuple SwiftVersion) {
+ObjCMethodInfo MI;
+convertCommonEntity(M, MI, M.Selector);
+
+// Check if the selector ends with ':' to determine if it takes arguments.
+bool takesArguments = M.Selector.endswith(":");
+
+// Split the selector into pieces.
+llvm::SmallVector Args;
+M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
+if (!takesArguments && Args.size() > 1) {
+  emitError("selector '" + M.Selector + "' is missing a ':' at the end");
+  return;
+}
+
+// Construct ObjCSelectorRef.
+api_notes::ObjCSelectorRef Selector;
+Selector.NumArgs = !takesArguments ? 0 : Args.size();
+Selector.Identifiers = Args;
+
+// Translate the initializer info.
+MI.DesignatedInit = M.DesignatedInit;
+MI.RequiredInit = M.Required;
+if (M.FactoryAsInit != FactoryAsInitKind::Infer)
+  emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
+
+MI.ResultType = std::string(M.ResultType);
+
+// Translate parameter information.
+convertParams(M.P

[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits


@@ -635,3 +638,478 @@ bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
 
   return false;
 }
+
+namespace {
+using namespace api_notes;
+
+class YAMLConverter {
+  const Module &M;
+  APINotesWriter Writer;
+  llvm::raw_ostream &OS;
+  llvm::SourceMgr::DiagHandlerTy DiagHandler;
+  void *DiagHandlerCtxt;
+  bool ErrorOccured;
+
+  /// Emit a diagnostic
+  bool emitError(llvm::Twine Message) {
+DiagHandler(
+llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
+DiagHandlerCtxt);
+ErrorOccured = true;
+return true;
+  }
+
+public:
+  YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
+llvm::raw_ostream &OS,
+llvm::SourceMgr::DiagHandlerTy DiagHandler,
+void *DiagHandlerCtxt)
+  : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
+DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
+ErrorOccured(false) {}
+
+  void convertAvailability(const AvailabilityItem &Availability,
+   CommonEntityInfo &CEI, llvm::StringRef APIName) {
+// Populate the unavailability information.
+CEI.Unavailable = (Availability.Mode == APIAvailability::None);
+CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
+if (CEI.Unavailable || CEI.UnavailableInSwift) {
+  CEI.UnavailableMsg = std::string(Availability.Msg);
+} else {
+  if (!Availability.Msg.empty()) {
+emitError(llvm::Twine("availability message for available API '") +
+  APIName + "' will not be used");
+  }

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotes YAML compiler (PR #71413)

2023-11-13 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/71413
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/72389

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

>From 2550d96acc9ce134b4f7359af0c75e3bd3146484 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 15 Nov 2023 13:46:54 +
Subject: [PATCH] [APINotes] Upstream APINotesManager

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
---
 .../include/clang/APINotes/APINotesManager.h  | 163 ++
 clang/include/clang/APINotes/Types.h  |   3 +
 .../clang/Basic/DiagnosticCommonKinds.td  |  13 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Basic/Module.h|   3 +
 clang/include/clang/Basic/SourceMgrAdapter.h  |  85 
 clang/lib/APINotes/APINotesManager.cpp| 469 ++
 clang/lib/APINotes/CMakeLists.txt |   1 +
 clang/lib/Basic/CMakeLists.txt|   1 +
 clang/lib/Basic/SourceMgrAdapter.cpp  | 136 +
 10 files changed, 876 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesManager.h
 create mode 100644 clang/include/clang/Basic/SourceMgrAdapter.h
 create mode 100644 clang/lib/APINotes/APINotesManager.cpp
 create mode 100644 clang/lib/Basic/SourceMgrAdapter.cpp

diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
new file mode 100644
index 000..d82d1fa2d544a1d
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look f

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/72389

>From fef3782ff1d4f2344b98eae4cf339e8cc1239fd7 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 15 Nov 2023 13:46:54 +
Subject: [PATCH] [APINotes] Upstream APINotesManager

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
---
 .../include/clang/APINotes/APINotesManager.h  | 163 ++
 clang/include/clang/APINotes/Types.h  |   3 +
 .../clang/Basic/DiagnosticCommonKinds.td  |  13 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Basic/Module.h|   3 +
 clang/include/clang/Basic/SourceMgrAdapter.h  |  85 
 clang/lib/APINotes/APINotesManager.cpp| 469 ++
 clang/lib/APINotes/CMakeLists.txt |   1 +
 clang/lib/Basic/CMakeLists.txt|   1 +
 clang/lib/Basic/SourceMgrAdapter.cpp  | 136 +
 10 files changed, 876 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesManager.h
 create mode 100644 clang/include/clang/Basic/SourceMgrAdapter.h
 create mode 100644 clang/lib/APINotes/APINotesManager.cpp
 create mode 100644 clang/lib/Basic/SourceMgrAdapter.cpp

diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
new file mode 100644
index 000..d82d1fa2d544a1d
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
+ 

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())

egorzhdan wrote:

Not quite, `Readers` is a `DenseMap` where the value type is a `PointerUnion`, 
so we need to cast it to one of the possible types which is `APINotesReader *`.

I like the idea of making `CurrentModuleReaders` an array of unique pointers 
regardless. I'll go ahead and do that.

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/72389

>From aa80c53b94e0d0a4ae86be41b47f8837a96b39d9 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 15 Nov 2023 13:46:54 +
Subject: [PATCH] [APINotes] Upstream APINotesManager

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
---
 .../include/clang/APINotes/APINotesManager.h  | 169 +++
 clang/include/clang/APINotes/Types.h  |   3 +
 .../clang/Basic/DiagnosticCommonKinds.td  |  13 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Basic/Module.h|   3 +
 clang/include/clang/Basic/SourceMgrAdapter.h  |  85 
 clang/lib/APINotes/APINotesManager.cpp| 458 ++
 clang/lib/APINotes/CMakeLists.txt |   1 +
 clang/lib/Basic/CMakeLists.txt|   1 +
 clang/lib/Basic/SourceMgrAdapter.cpp  | 136 ++
 10 files changed, 871 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesManager.h
 create mode 100644 clang/include/clang/Basic/SourceMgrAdapter.h
 create mode 100644 clang/lib/APINotes/APINotesManager.cpp
 create mode 100644 clang/lib/Basic/SourceMgrAdapter.cpp

diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
new file mode 100644
index 000..f1b346e181aae9c
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -0,0 +1,169 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  enum ReaderKind : unsigned { Public = 0, Private = 1 };
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  Option

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};

egorzhdan wrote:

That makes sense, I added an enum.

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
+StringRef FileName,
+bool WantPublic = true);
+
+  /// Attempt to load API notes for the given framework.
+  ///
+  /// \param FrameworkPath The path to the framework.
+  /// \param Public Whether to load the public API notes. Otherwise, attempt
+  /// to load the private API notes.
+  ///
+  /// \returns the header directory entry (e.g., for Headers or PrivateHeaders)
+  /// for which the API notes were successfully loaded, or NULL if API notes
+  /// could not be loaded for any reason.
+  OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef 
FrameworkPath,

egorzhdan wrote:

A framework will have the API notes file under either `{framework 
root}/APINotes`, `{framework root}/Headers` or `{framework 
root}/PrivateHeaders`, while a library will have API notes simply in its 
directory.

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
+StringRef FileName,
+bool WantPublic = true);
+
+  /// Attempt to load API notes for the given framework.
+  ///
+  /// \param FrameworkPath The path to the framework.
+  /// \param Public Whether to load the public API notes. Otherwise, attempt
+  /// to load the private API notes.
+  ///
+  /// \returns the header directory entry (e.g., for Headers or PrivateHeaders)
+  /// for which the API notes were successfully loaded, or NULL if API notes
+  /// could not be loaded for any reason.
+  OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef 
FrameworkPath,
+  llvm::StringRef 
FrameworkName,
+  bool Public);
+
+public:
+  APINotesManager(SourceManager &SM, const LangOptions &LangOpts);
+  ~APINotesManager();
+
+  /// Set the Swift version to use when filtering API notes.
+  void setSwiftVersion(llvm::VersionTuple Version) {
+this->SwiftVersion = Version;
+  }
+
+  /// Load the API notes for the current module.
+  ///
+  /// \param M The current module.
+  /// \param LookInModule Whether to look inside the module itself.

egorzhdan wrote:

Clarified the comment to indicate that we really mean looking into the 
directory of the current module.

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llv

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
+StringRef FileName,
+bool WantPublic = true);
+
+  /// Attempt to load API notes for the given framework.
+  ///
+  /// \param FrameworkPath The path to the framework.
+  /// \param Public Whether to load the public API notes. Otherwise, attempt
+  /// to load the private API notes.
+  ///
+  /// \returns the header directory entry (e.g., for Headers or PrivateHeaders)
+  /// for which the API notes were successfully loaded, or NULL if API notes
+  /// could not be loaded for any reason.
+  OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef 
FrameworkPath,
+  llvm::StringRef 
FrameworkName,
+  bool Public);
+
+public:
+  APINotesManager(SourceManager &SM, const LangOptions &LangOpts);
+  ~APINotesManager();
+
+  /// Set the Swift version to use when filtering API notes.
+  void setSwiftVersion(llvm::VersionTuple Version) {
+this->SwiftVersion = Version;
+  }
+
+  /// Load the API notes for the current module.
+  ///
+  /// \param M The current module.
+  /// \param LookInModule Whether to look inside the module itself.
+  /// \param SearchPaths The paths in which we should search for API notes
+  /// for the current module.
+  ///
+  /// \returns true if API notes were successfully loaded, \c false otherwise.
+  bool loadCurrentModuleAPINotes(Module *M, bool LookInModule,
+ ArrayRef Searc

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -737,6 +737,9 @@ inline bool operator!=(const TypedefInfo &LHS, const 
TypedefInfo &RHS) {
   return !(LHS == RHS);
 }
 
+/// The file extension used for the source representation of API notes.
+static const char SOURCE_APINOTES_EXTENSION[] = "apinotes";

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())

egorzhdan wrote:

Just realized that using `unique_ptr`s here is a bit tricky, because we are 
storing these pointers in `llvm::PointerUnion`. Looks like we'd increase the 
memory footprint by abandoning `llvm::PointerUnion`. Do you think it's still 
worth refactoring this?

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/72389

>From 9e171fa5e51a1c6572938da815f9d129f49fb046 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 15 Nov 2023 13:46:54 +
Subject: [PATCH] [APINotes] Upstream APINotesManager

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
---
 .../include/clang/APINotes/APINotesManager.h  | 169 +++
 clang/include/clang/APINotes/Types.h  |   3 +
 .../clang/Basic/DiagnosticCommonKinds.td  |  13 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Basic/Module.h|   3 +
 clang/include/clang/Basic/SourceMgrAdapter.h  |  85 
 clang/lib/APINotes/APINotesManager.cpp| 458 ++
 clang/lib/APINotes/CMakeLists.txt |   1 +
 clang/lib/Basic/CMakeLists.txt|   1 +
 clang/lib/Basic/SourceMgrAdapter.cpp  | 136 ++
 10 files changed, 871 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesManager.h
 create mode 100644 clang/include/clang/Basic/SourceMgrAdapter.h
 create mode 100644 clang/lib/APINotes/APINotesManager.cpp
 create mode 100644 clang/lib/Basic/SourceMgrAdapter.cpp

diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
new file mode 100644
index 000..f1b346e181aae9c
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -0,0 +1,169 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  enum ReaderKind : unsigned { Public = 0, Private = 1 };
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  Option

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-15 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())
+  delete Reader;
+  }
+
+  delete CurrentModuleReaders[0];
+  delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+  PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+  // Open the source file.
+  auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+  auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+  if (!SourceBuffer)
+return nullptr;
+
+  // Compile the API notes source into a buffer.
+  // FIXME: Either propagate OSType through or, better yet, improve the binary
+  // APINotes format to maintain complete availability information.
+  // FIXME: We don't even really need to go through the binary format at all;
+  // we're just going to immediately deserialize it again.
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  {
+SourceMgrAdapter SMAdapter(
+SM, SM.getDiagnostics(), diag::err_apinotes_message,
+diag::warn_apinotes_message, diag::note_apinotes_message, 
APINotesFile);
+llvm::raw_svector_ostream OS(APINotesBuffer);
+if (api_notes::compileAPINotes(
+SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+  return nullptr;
+
+// Make a copy of the compiled form into the buffer.
+CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  }
+
+  // Load the binary form we just compiled.
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+}
+
+std::unique_ptr
+APINotesManager::loadAPINotes(StringRef Buffer) {
+  llvm::SmallVector APINotesBuffer;
+  std::unique_ptr CompiledBuffer;
+  SourceMgrAdapter SMAdapter(
+  SM, SM.getDiagnostics(), diag::err_apinotes_message,
+  diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+  llvm::raw_svector_ostream OS(APINotesBuffer);
+
+  if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+return nullptr;
+
+  CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+  StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+  auto Reader = APINotesReader::Create(std::move(CompiledBuffer), 
SwiftVersion);
+  assert(Reader && "Could not load the API notes we just generated?");
+  return Reader;
+

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-16 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/72389

>From c4c9e3bffdcc80d7c153c0c4945844876894d98e Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 15 Nov 2023 13:46:54 +
Subject: [PATCH] [APINotes] Upstream APINotesManager

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
---
 .../include/clang/APINotes/APINotesManager.h  | 175 +++
 clang/include/clang/APINotes/Types.h  |   3 +
 .../clang/Basic/DiagnosticCommonKinds.td  |  13 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Basic/Module.h|   3 +
 clang/include/clang/Basic/SourceMgrAdapter.h  |  85 
 clang/lib/APINotes/APINotesManager.cpp| 458 ++
 clang/lib/APINotes/CMakeLists.txt |   1 +
 clang/lib/Basic/CMakeLists.txt|   1 +
 clang/lib/Basic/SourceMgrAdapter.cpp  | 136 ++
 10 files changed, 877 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesManager.h
 create mode 100644 clang/include/clang/Basic/SourceMgrAdapter.h
 create mode 100644 clang/lib/APINotes/APINotesManager.cpp
 create mode 100644 clang/lib/Basic/SourceMgrAdapter.cpp

diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
new file mode 100644
index 000..823b52ed28b5981
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -0,0 +1,175 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  enum ReaderKind : unsigned { Public = 0, Private = 1 };
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  ///
+  /// Not using std::unique_ptr to store these, since the reader pointers are
+  /// also stored in llvm::PointerUnion below.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesF

[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-16 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,163 @@
+//===--- APINotesManager.h - Manage API Notes Files -*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class LangOptions;
+class SourceManager;
+
+namespace api_notes {
+
+class APINotesReader;
+
+/// The API notes manager helps find API notes associated with declarations.
+///
+/// API notes are externally-provided annotations for declarations that can
+/// introduce new attributes (covering availability, nullability of
+/// parameters/results, and so on) for specific declarations without directly
+/// modifying the headers that contain those declarations.
+///
+/// The API notes manager is responsible for finding and loading the
+/// external API notes files that correspond to a given header. Its primary
+/// operation is \c findAPINotes(), which finds the API notes reader that
+/// provides information about the declarations at that location.
+class APINotesManager {
+  using ReaderEntry = llvm::PointerUnion;
+
+  SourceManager &SM;
+
+  /// Whether to implicitly search for API notes files based on the
+  /// source file from which an entity was declared.
+  bool ImplicitAPINotes;
+
+  /// The Swift version to use when interpreting versioned API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// API notes readers for the current module.
+  ///
+  /// There can be up to two of these, one for public headers and one
+  /// for private headers.
+  APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
+
+  /// A mapping from header file directories to the API notes reader for
+  /// that directory, or a redirection to another directory entry that may
+  /// have more information, or NULL to indicate that there is no API notes
+  /// reader for this directory.
+  llvm::DenseMap Readers;
+
+  /// Load the API notes associated with the given file, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(FileEntryRef APINotesFile);
+
+  /// Load the API notes associated with the given buffer, whether it is
+  /// the binary or source form of API notes.
+  ///
+  /// \returns the API notes reader for this file, or null if there is
+  /// a failure.
+  std::unique_ptr loadAPINotes(StringRef Buffer);
+
+  /// Load the given API notes file for the given header directory.
+  ///
+  /// \param HeaderDir The directory at which we
+  ///
+  /// \returns true if an error occurred.
+  bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef 
APINotesFile);
+
+  /// Look for API notes in the given directory.
+  ///
+  /// This might find either a binary or source API notes.
+  OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
+StringRef FileName,
+bool WantPublic = true);
+
+  /// Attempt to load API notes for the given framework.
+  ///
+  /// \param FrameworkPath The path to the framework.
+  /// \param Public Whether to load the public API notes. Otherwise, attempt
+  /// to load the private API notes.
+  ///
+  /// \returns the header directory entry (e.g., for Headers or PrivateHeaders)
+  /// for which the API notes were successfully loaded, or NULL if API notes
+  /// could not be loaded for any reason.
+  OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef 
FrameworkPath,

egorzhdan wrote:

Good point, added a comment to reflect that

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-16 Thread Egor Zhdan via cfe-commits


@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+  StringRef First, Second;
+
+public:
+  PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+  : First(First), Second(Second) {}
+  void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions 
&LangOpts)
+: SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+  // Free the API notes readers.
+  for (const auto &Entry : Readers) {
+if (auto Reader = Entry.second.dyn_cast())

egorzhdan wrote:

Done, added a comment

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-17 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesManager (PR #72389)

2023-11-20 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

@nico sorry for not leaving a more detailed description. I'll make sure to add 
a release note once the API notes are upstreamed entirely.

https://github.com/llvm/llvm-project/pull/72389
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Introduce APINotes in Clang Sema and Frontend (PR #72907)

2023-11-20 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/72907

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

This adds the initial Clang APINotes infrastructure to Clang Sema and Clang 
Frontend.

There will shortly be a follow-up patch with the actual usages of this API. I'm 
splitting these changes into separate PRs to keep the diffs easier to review.

>From 10bb536d577e18cc210b15df2746b1af17e8d9b2 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 19:13:39 +
Subject: [PATCH 1/2] [APINotes] Introduce APINotes in Sema

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

This adds the initial Clang APINotes infrastructure to Clang Sema.
---
 clang/include/clang/Sema/Sema.h | 2 ++
 clang/lib/Sema/CMakeLists.txt   | 1 +
 clang/lib/Sema/Sema.cpp | 3 ++-
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 63a9f9d4cffe2f2..e9872cdeb0b2522 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_SEMA_SEMA_H
 #define LLVM_CLANG_SEMA_SEMA_H
 
+#include "clang/APINotes/APINotesManager.h"
 #include "clang/AST/ASTConcept.h"
 #include "clang/AST/ASTFwd.h"
 #include "clang/AST/Attr.h"
@@ -408,6 +409,7 @@ class Sema final {
   ASTConsumer &Consumer;
   DiagnosticsEngine &Diags;
   SourceManager &SourceMgr;
+  api_notes::APINotesManager APINotes;
 
   /// Flag indicating whether or not to collect detailed statistics.
   bool CollectStats;
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index d3d403c1d5d79ef..1856a88e9a3271a 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -74,6 +74,7 @@ add_clang_library(clangSema
   ClangDriverOptions
 
   LINK_LIBS
+  clangAPINotes
   clangAST
   clangAnalysis
   clangBasic
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index d7d8d2eaa37e1d6..9771aaa2f3b0371 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -191,7 +191,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer 
&consumer,
 : ExternalSource(nullptr), CurFPFeatures(pp.getLangOpts()),
   LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
   Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
-  CollectStats(false), CodeCompleter(CodeCompleter), CurContext(nullptr),
+  APINotes(SourceMgr, LangOpts), CollectStats(false),
+  CodeCompleter(CodeCompleter), CurContext(nullptr),
   OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
   MSPointerToMemberRepresentationMethod(
   LangOpts.getMSPointerToMemberRepresentationMethod()),

>From b8421b0570cc634e205e5b06d10997a802d5dd76 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 19:23:37 +
Subject: [PATCH 2/2] [APINotes] Introduce APINotes in Frontend

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

This adds the initial Clang APINotes infrastructure to Clang Frontend.
---
 clang/include/clang/Frontend/CompilerInstance.h | 5 +
 clang/lib/Frontend/CMakeLists.txt   | 1 +
 clang/lib/Frontend/CompilerInstance.cpp | 4 
 3 files changed, 10 insertions(+)

diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index d26a452cf94cc3b..ac2f940769fbe90 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -304,6 +304,11 @@ class CompilerInstance : public ModuleLoader {
 return Invocation->getHeaderSearchOptsPtr();
   }
 
+  APINotesOptions &getAPINotesOpts() { return Invocation->getAPINotesOpts(); }
+  const APINotesOptions &getAPINotesOpts() const {
+return Invocation->getAPINotesOpts();
+  }
+
   LangOptions &getLangOpts() { return Invocation->getLangOpts(); }
   const LangOptions &getLangOpts() const { return Invocation->getLangOpts(); }
 
diff --git a/clang/lib/Frontend/CMakeLists.txt 
b/clang/lib/Frontend/CMakeLists.txt
index 1e5f0a859dfd568..a91666720884591 100644
--- a/clang/lib/Frontend/CMakeLists.txt
+++ b/clang/lib/Frontend/CMakeLists.txt
@@ -48,6 +48,7 @@ add_clang_library(clangFrontend
   intrinsics_gen
 
   LINK_LIBS
+  clangAPINotes
   clangAST
   clangBasic
   clangDriver
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index d749195585eca5b..be5b38d6110fc3b 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -747,6 +747,10 @@ void CompilerInstance::createSema(Trans

[clang] [APINotes] Introduce APINotes infrastructure in Clang Sema and Frontend (PR #72907)

2023-11-20 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan edited 
https://github.com/llvm/llvm-project/pull/72907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Introduce APINotes infrastructure in Clang Sema and Frontend (PR #72907)

2023-11-20 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

The clang-format failure is unrelated to this patch.

https://github.com/llvm/llvm-project/pull/72907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Introduce APINotes infrastructure in Clang Sema and Frontend (PR #72907)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/72907
___
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 #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/73017

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

This is the largest chunk of the API Notes functionality in the upstreaming 
process. I will soon submit a follow-up patch to actually enable usage of this 
functionality by having a Clang driver flag that enables API Notes, along with 
tests.

(it might be easier to review commit-by-commit)

>From ae8c604e9333b1ea54fc6e80134bdba948eeecb7 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..acfb75a3dee3e7a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr { 
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From ae8c604e9333b1ea54fc6e80134bdba948eeecb7 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..acfb75a3dee3e7a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr { 
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Result.getAsSingle()) {
+S.Diag(IdentLoc->Loc, d

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From ae8c604e9333b1ea54fc6e80134bdba948eeecb7 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..acfb75a3dee3e7a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr { 
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Result.getAsSingle()) {
+S.Diag(IdentLoc->Loc, d

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From ae8c604e9333b1ea54fc6e80134bdba948eeecb7 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..acfb75a3dee3e7a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr { 
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Result.getAsSingle()) {
+S.Diag(IdentLoc->Loc, d

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From d7d8e8520681b6a71fda9848b18828cff8ed7415 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..a9ad6c878306ad3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Result.getAsSingle()) {
+S.Diag(IdentLoc->Loc, di

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

2023-11-21 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From cea6998f68ffca08edb8bed555df093c8fe48d1c Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/test/Sema/ns_error_enum.m   |  3 +-
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 5 files changed, 93 insertions(+), 18 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index c2fbdfc66c540d6..a9ad6c878306ad3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2257,7 +2260,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2593,6 +2596,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2614,6 +2633,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fd778793346f502..8552b28e51acd97 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6210,29 +6210,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Re

[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/73120

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

>From 41f0d8ce31e656288cb5753c372829fcf4bb80bc Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 22 Nov 2023 13:54:04 +
Subject: [PATCH] [APINotes] Upstream Driver and Frontend options that enable
 API Notes

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/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 13 +
 clang/lib/Driver/ToolChains/Clang.cpp | 11 +++
 clang/lib/Frontend/CompilerInstance.cpp   |  8 
 clang/lib/Frontend/CompilerInvocation.cpp | 23 +++
 5 files changed, 56 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index cd77b22bf3ace4b..c3d5399905a3fda 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -405,6 +405,7 @@ LANGOPT(XLPragmaPack, 1, 0, "IBM XL #pragma pack handling")
 LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments 
from system headers in the AST")
 
 LANGOPT(APINotes, 1, 0, "use external API notes")
+LANGOPT(APINotesModules, 1, 0, "use module-based external API notes")
 
 LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
"field padding (0: none, 1:least "
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b2f2bcb6ac37910..ff2e4572ec4305f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1754,6 +1754,19 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+defm apinotes : BoolOption<"f", "apinotes",
+  LangOpts<"APINotes">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption, CC1Option], " external API notes support">>,
+  Group;
+defm apinotes_modules : BoolOption<"f", "apinotes-modules",
+  LangOpts<"APINotesModules">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption, CC1Option],
+  " module-based external API notes support">>,
+  Group;
 def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
   Group, Visibility<[ClangOption, CC1Option]>,
   MetaVarName<"">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 6dec117aed1056b..575ba57eef758db 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6720,6 +6720,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
  options::OPT_fno_assume_sane_operator_new);
 
+  if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false) ||
+  Args.hasArg(options::OPT_iapinotes_modules)) {
+if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false))
+  CmdArgs.push_back("-fapinotes");
+if (Args.hasFlag(options::OPT_fapinotes_modules,
+ options::OPT_fno_apinotes_modules, false))
+  CmdArgs.push_back("-fapinotes-modules");
+
+Args.AddLastArg(CmdArgs, options::OPT_fapinotes_swift_version);
+  }
+
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
TC.IsBlocksDefault()) ||
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index be5b38d6110fc3b..f9f839b3d391292 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -756,6 +756,14 @@ void CompilerInstance::createSema(TranslationUnitKind 
TUKind,
 TheSema->addExternalSource(ExternalSemaSrc.get());
 ExternalSemaSrc->InitializeSema(*TheSema);
   }
+
+  // If we're building a module and are supposed to load API notes,
+  // notify the API notes manager.
+  if (auto currentModule = getPreprocessor().getCurrentModule()) {
+(void)TheSema->APINotes.loadCurrentModuleAPINotes(
+currentModule, getLangOpts().APINotesModules,
+getAPINotesOpts().ModuleSearchPaths);
+  }
 }
 
 // Output Files
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 3f4ca02539080d0..3b92cc1281f9e0e 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3267,6 +3267,16 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
&Opts, ArgList &Args,
   return D

[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73120

>From 43cbb211490efdd2449ebef9847ce44eab02d3e4 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 22 Nov 2023 13:54:04 +
Subject: [PATCH] [APINotes] Upstream Driver and Frontend options that enable
 API Notes

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/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 12 
 clang/lib/Driver/ToolChains/Clang.cpp | 13 +
 clang/lib/Frontend/CompilerInstance.cpp   |  8 
 clang/lib/Frontend/CompilerInvocation.cpp | 23 +++
 5 files changed, 57 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index cd77b22bf3ace4b..c3d5399905a3fda 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -405,6 +405,7 @@ LANGOPT(XLPragmaPack, 1, 0, "IBM XL #pragma pack handling")
 LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments 
from system headers in the AST")
 
 LANGOPT(APINotes, 1, 0, "use external API notes")
+LANGOPT(APINotesModules, 1, 0, "use module-based external API notes")
 
 LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
"field padding (0: none, 1:least "
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b2f2bcb6ac37910..9191ccd2a66ac4a 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1754,6 +1754,18 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+defm apinotes : BoolOption<"f", "apinotes",
+LangOpts<"APINotes">, DefaultFalse,
+PosFlag,
+NegFlag,
+BothFlags<[], [ClangOption, CC1Option], "external API notes support">>,
+Group;
+defm apinotes_modules : BoolOption<"f", "apinotes-modules",
+LangOpts<"APINotesModules">, DefaultFalse,
+PosFlag,
+NegFlag,
+BothFlags<[], [ClangOption, CC1Option], "module-based external API notes 
support">>,
+Group;
 def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
   Group, Visibility<[ClangOption, CC1Option]>,
   MetaVarName<"">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 6dec117aed1056b..972bdb37e45209b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6720,6 +6720,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
  options::OPT_fno_assume_sane_operator_new);
 
+  if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false) ||
+  Args.hasFlag(options::OPT_fapinotes_modules,
+   options::OPT_fno_apinotes_modules, false) ||
+  Args.hasArg(options::OPT_iapinotes_modules)) {
+if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false))
+  CmdArgs.push_back("-fapinotes");
+if (Args.hasFlag(options::OPT_fapinotes_modules,
+ options::OPT_fno_apinotes_modules, false))
+  CmdArgs.push_back("-fapinotes-modules");
+
+Args.AddLastArg(CmdArgs, options::OPT_fapinotes_swift_version);
+  }
+
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
TC.IsBlocksDefault()) ||
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index be5b38d6110fc3b..e5f8c0746a99dd4 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -756,6 +756,14 @@ void CompilerInstance::createSema(TranslationUnitKind 
TUKind,
 TheSema->addExternalSource(ExternalSemaSrc.get());
 ExternalSemaSrc->InitializeSema(*TheSema);
   }
+
+  // If we're building a module and are supposed to load API notes,
+  // notify the API notes manager.
+  if (auto *currentModule = getPreprocessor().getCurrentModule()) {
+(void)TheSema->APINotes.loadCurrentModuleAPINotes(
+currentModule, getLangOpts().APINotesModules,
+getAPINotesOpts().ModuleSearchPaths);
+  }
 }
 
 // Output Files
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 3f4ca02539080d0..3b92cc1281f9e0e 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3267,6 +3267,16 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
&Opts, ArgList &Args,
   return Diags.getNumErrors() == NumErrorsBefore;
 }
 
+sta

[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits


@@ -1754,6 +1754,19 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+defm apinotes : BoolOption<"f", "apinotes",
+  LangOpts<"APINotes">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption, CC1Option], " external API notes support">>,
+  Group;

egorzhdan wrote:

Done

https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits


@@ -1754,6 +1754,19 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+defm apinotes : BoolOption<"f", "apinotes",
+  LangOpts<"APINotes">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption, CC1Option], " external API notes support">>,

egorzhdan wrote:

Doesn't seem to be intentional, removed it.

https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits


@@ -6720,6 +6720,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
  options::OPT_fno_assume_sane_operator_new);
 
+  if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false) ||
+  Args.hasArg(options::OPT_iapinotes_modules)) {

egorzhdan wrote:

My mistake, the outer `if` condition became wrong during my refactoring 
attempt. Fixed it.

https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-22 Thread Egor Zhdan via cfe-commits


@@ -756,6 +756,14 @@ void CompilerInstance::createSema(TranslationUnitKind 
TUKind,
 TheSema->addExternalSource(ExternalSemaSrc.get());
 ExternalSemaSrc->InitializeSema(*TheSema);
   }
+
+  // If we're building a module and are supposed to load API notes,
+  // notify the API notes manager.
+  if (auto currentModule = getPreprocessor().getCurrentModule()) {

egorzhdan wrote:

Alright, done

https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesReader (PR #66769)

2023-10-30 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/66769

>From e165261eb5baa8c2660ac8b2319cb96d13578572 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Tue, 19 Sep 2023 13:42:16 +0100
Subject: [PATCH] [APINotes] Upstream APINotesReader

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/include/clang/APINotes/APINotesReader.h |  200 ++
 clang/include/clang/APINotes/Types.h  |8 +-
 clang/lib/APINotes/APINotesReader.cpp | 2048 +
 clang/lib/APINotes/CMakeLists.txt |3 +
 4 files changed, 2252 insertions(+), 7 deletions(-)
 create mode 100644 clang/include/clang/APINotes/APINotesReader.h
 create mode 100644 clang/lib/APINotes/APINotesReader.cpp

diff --git a/clang/include/clang/APINotes/APINotesReader.h 
b/clang/include/clang/APINotes/APINotesReader.h
new file mode 100644
index 000..1c5aab09595509e
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -0,0 +1,200 @@
+//===--- APINotesReader.h - API Notes Reader *- C++ 
-*-===//
+//
+// 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 defines the \c APINotesReader class that reads source API notes
+// data providing additional information about source code as a separate input,
+// such as the non-nil/nilable annotations for method parameters.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_READER_H
+#define LLVM_CLANG_APINOTES_READER_H
+
+#include "clang/APINotes/Types.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VersionTuple.h"
+#include 
+
+namespace clang {
+namespace api_notes {
+
+/// A class that reads API notes data from a binary file that was written by
+/// the \c APINotesWriter.
+class APINotesReader {
+  class Implementation;
+  std::unique_ptr Implementation;
+
+  APINotesReader(llvm::MemoryBuffer *InputBuffer,
+ llvm::VersionTuple SwiftVersion, bool &Failed);
+
+public:
+  /// Create a new API notes reader from the given member buffer, which
+  /// contains the contents of a binary API notes file.
+  ///
+  /// \returns the new API notes reader, or null if an error occurred.
+  static std::unique_ptr
+  Create(std::unique_ptr InputBuffer,
+ llvm::VersionTuple SwiftVersion);
+
+  ~APINotesReader();
+
+  APINotesReader(const APINotesReader &) = delete;
+  APINotesReader &operator=(const APINotesReader &) = delete;
+
+  /// Captures the completed versioned information for a particular part of
+  /// API notes, including both unversioned API notes and each versioned API
+  /// note for that particular entity.
+  template  class VersionedInfo {
+/// The complete set of results.
+llvm::SmallVector, 1> Results;
+
+/// The index of the result that is the "selected" set based on the desired
+/// Swift version, or null if nothing matched.
+std::optional Selected;
+
+  public:
+/// Form an empty set of versioned information.
+VersionedInfo(std::nullopt_t) : Selected(std::nullopt) {}
+
+/// Form a versioned info set given the desired version and a set of
+/// results.
+VersionedInfo(
+llvm::VersionTuple Version,
+llvm::SmallVector, 1> Results);
+
+/// Retrieve the selected index in the result set.
+std::optional getSelected() const { return Selected; }
+
+/// Return the number of versioned results we know about.
+unsigned size() const { return Results.size(); }
+
+/// Access all versioned results.
+const std::pair *begin() const {
+  assert(!Results.empty());
+  return Results.begin();
+}
+const std::pair *end() const {
+  return Results.end();
+}
+
+/// Access a specific versioned result.
+const std::pair &operator[](unsigned index) const {
+  assert(index < Results.size());
+  return Results[index];
+}
+  };
+
+  /// Look for the context ID of the given Objective-C class.
+  ///
+  /// \param Name The name of the class we're looking for.
+  ///
+  /// \returns The ID, if known.
+  std::optional lookupObjCClassID(llvm::StringRef Name);
+
+  /// Look for information regarding the given Objective-C class.
+  ///
+  /// \param Name The name of the class we're looking for.
+  ///
+  /// \returns The information about the class, if known.
+  VersionedInfo lookupObjCClassInfo(llvm::StringRef Name);
+
+  /// Look for the context ID of the given Objective-C protocol.
+  ///
+  /// \param Name The name of the protocol we're looking for.
+  ///
+  /// \returns The ID of the protocol, if known.
+  std::optional lookupObjCPro

[clang] [APINotes] Upstream APINotesReader (PR #66769)

2023-10-30 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/66769
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-10-31 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/70827

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

This adds the first compiler options related to API Notes to the upstream 
Clang: `-iapinotes-modules` and `-fapinotes-swift-version=`. However, this does 
not add the `-fapinotes` flag that enables API Notes, since the feature is not 
fully functional yet.

>From 368f2b2580ef7ba8777020c40edcbb3b08c5b9ad Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Tue, 31 Oct 2023 16:39:45 +
Subject: [PATCH] [APINotes] Upstream APINotesOptions

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

This adds the first compiler options related to API Notes to the upstream 
Clang: `-iapinotes-modules` and `-fapinotes-swift-version=`. However, this does 
not add the `-fapinotes` flag that enables API Notes, since the feature is not 
fully functional yet.
---
 .../include/clang/APINotes/APINotesOptions.h  | 34 +++
 clang/include/clang/Driver/Options.td |  7 
 .../clang/Frontend/CompilerInvocation.h   |  6 
 clang/lib/Frontend/CompilerInvocation.cpp | 12 +++
 4 files changed, 59 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesOptions.h

diff --git a/clang/include/clang/APINotes/APINotesOptions.h 
b/clang/include/clang/APINotes/APINotesOptions.h
new file mode 100644
index 000..e8b8a9ed2261fa1
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesOptions.h
@@ -0,0 +1,34 @@
+//===--- APINotesOptions.h --*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+#define LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+/// Tracks various options which control how API notes are found and handled.
+class APINotesOptions {
+public:
+  /// The Swift version which should be used for API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// The set of search paths where we API notes can be found for particular
+  /// modules.
+  ///
+  /// The API notes in this directory are stored as .apinotes, and
+  /// are only applied when building the module .
+  std::vector ModuleSearchPaths;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8b730e0f7ecd84..940f63dd5736750 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1733,6 +1733,10 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  MetaVarName<"">,
+  HelpText<"Specify the Swift version to use when filtering API notes">;
 
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
@@ -4129,6 +4133,9 @@ def ibuiltininc : Flag<["-"], "ibuiltininc">, 
Group,
 def index_header_map : Flag<["-"], "index-header-map">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Make the next included directory (-I or -F) an indexer header 
map">;
+def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, 
Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Add directory to the API notes search path referenced by module 
name">, MetaVarName<"">;
 def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Add directory to AFTER include search path">;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h 
b/clang/include/clang/Frontend/CompilerInvocation.h
index 45e263e7bc76822..d9c757a8a156861 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 #define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 
+#include "clang/APINotes/APINotesOptions.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -92,6 +93,9 @@ class CompilerInvocationBase {
 
   std::shared_ptr MigratorOpts;
 
+  /// Options controlling API notes.
+  std::shared_ptr APINotesOpts;
+
   /// Op

[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-10-31 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

The clang-format failure is not related to the changes in this PR.

https://github.com/llvm/llvm-project/pull/70827
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-10-31 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/70827

>From 552995265316fd04bd73148fce010aa3cd0368f5 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Tue, 31 Oct 2023 16:39:45 +
Subject: [PATCH] [APINotes] Upstream APINotesOptions

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

This adds the first compiler options related to API Notes to the upstream 
Clang: `-iapinotes-modules` and `-fapinotes-swift-version=`. However, this does 
not add the `-fapinotes` flag that enables API Notes, since the feature is not 
fully functional yet.
---
 .../include/clang/APINotes/APINotesOptions.h  | 34 +++
 clang/include/clang/Driver/Options.td |  7 
 .../clang/Frontend/CompilerInvocation.h   |  6 
 clang/lib/Frontend/CompilerInvocation.cpp | 12 +++
 4 files changed, 59 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesOptions.h

diff --git a/clang/include/clang/APINotes/APINotesOptions.h 
b/clang/include/clang/APINotes/APINotesOptions.h
new file mode 100644
index 000..e8b8a9ed2261fa1
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesOptions.h
@@ -0,0 +1,34 @@
+//===--- APINotesOptions.h --*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+#define LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+/// Tracks various options which control how API notes are found and handled.
+class APINotesOptions {
+public:
+  /// The Swift version which should be used for API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// The set of search paths where we API notes can be found for particular
+  /// modules.
+  ///
+  /// The API notes in this directory are stored as .apinotes, and
+  /// are only applied when building the module .
+  std::vector ModuleSearchPaths;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8b730e0f7ecd84..940f63dd5736750 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1733,6 +1733,10 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  MetaVarName<"">,
+  HelpText<"Specify the Swift version to use when filtering API notes">;
 
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
@@ -4129,6 +4133,9 @@ def ibuiltininc : Flag<["-"], "ibuiltininc">, 
Group,
 def index_header_map : Flag<["-"], "index-header-map">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Make the next included directory (-I or -F) an indexer header 
map">;
+def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, 
Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Add directory to the API notes search path referenced by module 
name">, MetaVarName<"">;
 def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Add directory to AFTER include search path">;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h 
b/clang/include/clang/Frontend/CompilerInvocation.h
index 45e263e7bc76822..d9c757a8a156861 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 #define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 
+#include "clang/APINotes/APINotesOptions.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -92,6 +93,9 @@ class CompilerInvocationBase {
 
   std::shared_ptr MigratorOpts;
 
+  /// Options controlling API notes.
+  std::shared_ptr APINotesOpts;
+
   /// Options controlling IRgen and the backend.
   std::shared_ptr CodeGenOpts;
 
@@ -131,6 +135,7 @@ class CompilerInvocationBase {
   const PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
   const AnalyzerOptions &getAnalyzerOpts() const { return *AnalyzerOpts; }
   const MigratorOptions &getMigratorOpts() const { return *MigratorOpts; }
+  const APINotesOptions &getAPINotesOpts() const { return *APINotesOpts; }
   

[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-11-01 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/70827

>From 573e7ea751af1be41b3c984e7dc6b334f0ac0142 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Tue, 31 Oct 2023 16:39:45 +
Subject: [PATCH] [APINotes] Upstream APINotesOptions

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

This adds the first compiler options related to API Notes to the upstream 
Clang: `-iapinotes-modules` and `-fapinotes-swift-version=`. However, this does 
not add the `-fapinotes` flag that enables API Notes, since the feature is not 
fully functional yet.
---
 .../include/clang/APINotes/APINotesOptions.h  | 34 +++
 clang/include/clang/Driver/Options.td |  7 
 .../clang/Frontend/CompilerInvocation.h   |  6 
 clang/lib/Frontend/CompilerInvocation.cpp | 12 +++
 4 files changed, 59 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesOptions.h

diff --git a/clang/include/clang/APINotes/APINotesOptions.h 
b/clang/include/clang/APINotes/APINotesOptions.h
new file mode 100644
index 000..e8b8a9ed2261fa1
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesOptions.h
@@ -0,0 +1,34 @@
+//===--- APINotesOptions.h --*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+#define LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+/// Tracks various options which control how API notes are found and handled.
+class APINotesOptions {
+public:
+  /// The Swift version which should be used for API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// The set of search paths where we API notes can be found for particular
+  /// modules.
+  ///
+  /// The API notes in this directory are stored as .apinotes, and
+  /// are only applied when building the module .
+  std::vector ModuleSearchPaths;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8b730e0f7ecd84..940f63dd5736750 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1733,6 +1733,10 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  MetaVarName<"">,
+  HelpText<"Specify the Swift version to use when filtering API notes">;
 
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
@@ -4129,6 +4133,9 @@ def ibuiltininc : Flag<["-"], "ibuiltininc">, 
Group,
 def index_header_map : Flag<["-"], "index-header-map">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Make the next included directory (-I or -F) an indexer header 
map">;
+def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, 
Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Add directory to the API notes search path referenced by module 
name">, MetaVarName<"">;
 def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Add directory to AFTER include search path">;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h 
b/clang/include/clang/Frontend/CompilerInvocation.h
index 45e263e7bc76822..d9c757a8a156861 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 #define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 
+#include "clang/APINotes/APINotesOptions.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -92,6 +93,9 @@ class CompilerInvocationBase {
 
   std::shared_ptr MigratorOpts;
 
+  /// Options controlling API notes.
+  std::shared_ptr APINotesOpts;
+
   /// Options controlling IRgen and the backend.
   std::shared_ptr CodeGenOpts;
 
@@ -131,6 +135,7 @@ class CompilerInvocationBase {
   const PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
   const AnalyzerOptions &getAnalyzerOpts() const { return *AnalyzerOpts; }
   const MigratorOptions &getMigratorOpts() const { return *MigratorOpts; }
+  const APINotesOptions &getAPINotesOpts() const { return *APINotesOpts; }
   

[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-11-01 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/70827
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-11-01 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

```
47.207 [1384/8/4064] ASTNodeAPI.json
FAILED: tools/clang/lib/Tooling/ASTNodeAPI.json 
/home/buildbot/worker/as-builder-7/ramdisk/flang-runtime-cuda-clang/build/clang/tools/clang/lib/Tooling/ASTNodeAPI.json
```

Looking into this

https://github.com/llvm/llvm-project/pull/70827
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Revert "Revert "[APINotes] Upstream APINotesOptions"" (PR #70975)

2023-11-01 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/70975

This re-lands https://github.com/llvm/llvm-project/pull/70827 while preventing 
the assertion failure that occurred when generating `ASTNodeAPI.json` on 
non-Apple platforms.

>From 07f57b151a455a9a3587bd257bfd9a92889120be Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 1 Nov 2023 19:03:57 +
Subject: [PATCH 1/2] Revert "Revert "[APINotes] Upstream APINotesOptions""

This reverts commit 0e06ddf0f6896cfd817a1b97a43b78331e0b1d66.
---
 .../include/clang/APINotes/APINotesOptions.h  | 34 +++
 clang/include/clang/Driver/Options.td |  7 
 .../clang/Frontend/CompilerInvocation.h   |  6 
 clang/lib/Frontend/CompilerInvocation.cpp | 12 +++
 4 files changed, 59 insertions(+)
 create mode 100644 clang/include/clang/APINotes/APINotesOptions.h

diff --git a/clang/include/clang/APINotes/APINotesOptions.h 
b/clang/include/clang/APINotes/APINotesOptions.h
new file mode 100644
index 000..e8b8a9ed2261fa1
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesOptions.h
@@ -0,0 +1,34 @@
+//===--- APINotesOptions.h --*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+#define LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
+
+#include "llvm/Support/VersionTuple.h"
+#include 
+#include 
+
+namespace clang {
+
+/// Tracks various options which control how API notes are found and handled.
+class APINotesOptions {
+public:
+  /// The Swift version which should be used for API notes.
+  llvm::VersionTuple SwiftVersion;
+
+  /// The set of search paths where we API notes can be found for particular
+  /// modules.
+  ///
+  /// The API notes in this directory are stored as .apinotes, and
+  /// are only applied when building the module .
+  std::vector ModuleSearchPaths;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b1229b2f4562379..fcf6a4b2ccb2369 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1733,6 +1733,10 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  MetaVarName<"">,
+  HelpText<"Specify the Swift version to use when filtering API notes">;
 
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
@@ -4129,6 +4133,9 @@ def ibuiltininc : Flag<["-"], "ibuiltininc">, 
Group,
 def index_header_map : Flag<["-"], "index-header-map">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Make the next included directory (-I or -F) an indexer header 
map">;
+def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, 
Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Add directory to the API notes search path referenced by module 
name">, MetaVarName<"">;
 def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Add directory to AFTER include search path">;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h 
b/clang/include/clang/Frontend/CompilerInvocation.h
index 45e263e7bc76822..d9c757a8a156861 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 #define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
 
+#include "clang/APINotes/APINotesOptions.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -92,6 +93,9 @@ class CompilerInvocationBase {
 
   std::shared_ptr MigratorOpts;
 
+  /// Options controlling API notes.
+  std::shared_ptr APINotesOpts;
+
   /// Options controlling IRgen and the backend.
   std::shared_ptr CodeGenOpts;
 
@@ -131,6 +135,7 @@ class CompilerInvocationBase {
   const PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
   const AnalyzerOptions &getAnalyzerOpts() const { return *AnalyzerOpts; }
   const MigratorOptions &getMigratorOpts() const { return *MigratorOpts; }
+  const APINotesOptions &getAPINotesOpts() const { return *APINotesOpts; }
   const CodeGenOptions &getCodeGenOpts() const { return *CodeGenOpts; }
   const FileSystemOptions &getFileSystemOpts() const { return *FSOpts; }
   const FrontendOptions &getFr

[clang] [APINotes] Upstream APINotesOptions (PR #70827)

2023-11-01 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

Apologies for the broken build!
I put up a re-land patch: https://github.com/llvm/llvm-project/pull/70975

https://github.com/llvm/llvm-project/pull/70827
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Revert "Revert "[APINotes] Upstream APINotesOptions"" (PR #70975)

2023-11-02 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/70975
___
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 #73017)

2023-12-15 Thread Egor Zhdan via cfe-commits

egorzhdan wrote:

@compnerd ping :)

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix `-Wdocumentation` warning (NFC) (PR #73243)

2023-11-23 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan created 
https://github.com/llvm/llvm-project/pull/73243

```
llvm-project/clang/include/clang/AST/OpenMPClause.h:7762:14: warning: parameter 
'Modifier' not found in the function declaration [-Wdocumentation]
  /// \param Modifier The modifier applied to 'order' clause.
 ^~~~
llvm-project/clang/include/clang/AST/OpenMPClause.h:7762:14: note: did you mean 
'M'?
  /// \param Modifier The modifier applied to 'order' clause.
```

>From d1a1245492950601c8513c1a80b2d361b1ededc5 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Thu, 23 Nov 2023 14:19:17 +
Subject: [PATCH] [Clang] Fix `-Wdocumentation` warning (NFC)

```
llvm-project/clang/include/clang/AST/OpenMPClause.h:7762:14: warning: parameter 
'Modifier' not found in the function declaration [-Wdocumentation]
  /// \param Modifier The modifier applied to 'order' clause.
 ^~~~
llvm-project/clang/include/clang/AST/OpenMPClause.h:7762:14: note: did you mean 
'M'?
  /// \param Modifier The modifier applied to 'order' clause.
```
---
 clang/include/clang/AST/OpenMPClause.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/OpenMPClause.h 
b/clang/include/clang/AST/OpenMPClause.h
index 549f12e87df597a..51155e63dcb8f7d 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -7776,10 +7776,10 @@ class OMPOrderClause final : public OMPClause {
   /// \param MLoc Location of the modifier
   OMPOrderClause(OpenMPOrderClauseKind A, SourceLocation ALoc,
  SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, OpenMPOrderClauseModifier M,
+ SourceLocation EndLoc, OpenMPOrderClauseModifier Modifier,
  SourceLocation MLoc)
   : OMPClause(llvm::omp::OMPC_order, StartLoc, EndLoc),
-LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc), Modifier(M),
+LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc), Modifier(Modifier),
 ModifierKwLoc(MLoc) {}
 
   /// Build an empty clause.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-23 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73120

>From 5fcceda3e5904b82ccac23e2137d95e0e357b475 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Wed, 22 Nov 2023 13:54:04 +
Subject: [PATCH] [APINotes] Upstream Driver and Frontend options that enable
 API Notes

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/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 12 
 clang/lib/Driver/ToolChains/Clang.cpp |  7 +++
 clang/lib/Frontend/CompilerInstance.cpp   |  8 
 clang/lib/Frontend/CompilerInvocation.cpp | 23 +++
 5 files changed, 51 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index cd77b22bf3ace4b..c3d5399905a3fda 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -405,6 +405,7 @@ LANGOPT(XLPragmaPack, 1, 0, "IBM XL #pragma pack handling")
 LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments 
from system headers in the AST")
 
 LANGOPT(APINotes, 1, 0, "use external API notes")
+LANGOPT(APINotesModules, 1, 0, "use module-based external API notes")
 
 LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
"field padding (0: none, 1:least "
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b2f2bcb6ac37910..9191ccd2a66ac4a 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1754,6 +1754,18 @@ def fswift_async_fp_EQ : Joined<["-"], 
"fswift-async-fp=">,
 NormalizedValuesScope<"CodeGenOptions::SwiftAsyncFramePointerKind">,
 NormalizedValues<["Auto", "Always", "Never"]>,
 MarshallingInfoEnum, "Always">;
+defm apinotes : BoolOption<"f", "apinotes",
+LangOpts<"APINotes">, DefaultFalse,
+PosFlag,
+NegFlag,
+BothFlags<[], [ClangOption, CC1Option], "external API notes support">>,
+Group;
+defm apinotes_modules : BoolOption<"f", "apinotes-modules",
+LangOpts<"APINotesModules">, DefaultFalse,
+PosFlag,
+NegFlag,
+BothFlags<[], [ClangOption, CC1Option], "module-based external API notes 
support">>,
+Group;
 def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
   Group, Visibility<[ClangOption, CC1Option]>,
   MetaVarName<"">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 6dec117aed1056b..2d73f42772a29dc 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6720,6 +6720,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
  options::OPT_fno_assume_sane_operator_new);
 
+  if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false))
+CmdArgs.push_back("-fapinotes");
+  if (Args.hasFlag(options::OPT_fapinotes_modules,
+   options::OPT_fno_apinotes_modules, false))
+CmdArgs.push_back("-fapinotes-modules");
+  Args.AddLastArg(CmdArgs, options::OPT_fapinotes_swift_version);
+
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
TC.IsBlocksDefault()) ||
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index be5b38d6110fc3b..e5f8c0746a99dd4 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -756,6 +756,14 @@ void CompilerInstance::createSema(TranslationUnitKind 
TUKind,
 TheSema->addExternalSource(ExternalSemaSrc.get());
 ExternalSemaSrc->InitializeSema(*TheSema);
   }
+
+  // If we're building a module and are supposed to load API notes,
+  // notify the API notes manager.
+  if (auto *currentModule = getPreprocessor().getCurrentModule()) {
+(void)TheSema->APINotes.loadCurrentModuleAPINotes(
+currentModule, getLangOpts().APINotesModules,
+getAPINotesOpts().ModuleSearchPaths);
+  }
 }
 
 // Output Files
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 3f4ca02539080d0..3b92cc1281f9e0e 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3267,6 +3267,16 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
&Opts, ArgList &Args,
   return Diags.getNumErrors() == NumErrorsBefore;
 }
 
+static void GenerateAPINotesArgs(const APINotesOptions &Opts,
+ ArgumentConsumer Consumer) {
+  if (!Opts.SwiftVersion.empty())
+GenerateArg(Consumer, OPT_fapinotes_swift_version,
+Opts.SwiftVersion.getAsString());
+
+  for (con

[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-23 Thread Egor Zhdan via cfe-commits


@@ -6720,6 +6720,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
  options::OPT_fno_assume_sane_operator_new);
 
+  if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false) ||
+  Args.hasArg(options::OPT_iapinotes_modules)) {

egorzhdan wrote:

That's a good point, we don't actually need the outer check here. I removed it.

https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [APINotes] Upstream Driver and Frontend options that enable API Notes (PR #73120)

2023-11-23 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/73120
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix `-Wdocumentation` warning (NFC) (PR #73243)

2023-11-24 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan closed 
https://github.com/llvm/llvm-project/pull/73243
___
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 #73017)

2023-11-27 Thread Egor Zhdan via cfe-commits

https://github.com/egorzhdan updated 
https://github.com/llvm/llvm-project/pull/73017

>From 4f7e29fe46a011153b3fbeee4d93875bb1a1a233 Mon Sep 17 00:00:00 2001
From: Egor Zhdan 
Date: Mon, 20 Nov 2023 18:03:18 +
Subject: [PATCH 1/4] [APINotes] Upstream attributes that are created
 implicitly from APINotes

---
 clang/include/clang/Basic/Attr.td | 46 ++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 34 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +
 clang/test/Sema/ns_error_enum.m   |  3 +-
 clang/utils/TableGen/ClangAttrEmitter.cpp | 26 -
 5 files changed, 93 insertions(+), 18 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 03ed6accf700c4e..fb45991821ac059 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -301,6 +301,9 @@ class VariadicEnumArgument values,
   bit IsExternalType = isExternalType;
 }
 
+// Represents an attribute wrapped by another attribute.
+class AttrArgument : Argument;
+
 // This handles one spelling of an attribute.
 class Spelling {
   string Name = name;
@@ -2265,7 +2268,7 @@ def ObjCBridgeRelated : InheritableAttr {
 def NSErrorDomain : InheritableAttr {
   let Spellings = [GNU<"ns_error_domain">];
   let Subjects = SubjectList<[Enum], ErrorDiag>;
-  let Args = [DeclArgument];
+  let Args = [IdentifierArgument<"ErrorDomain">];
   let Documentation = [NSErrorDomainDocs];
 }
 
@@ -2601,6 +2604,22 @@ def SwiftError : InheritableAttr {
   let Documentation = [SwiftErrorDocs];
 }
 
+def SwiftImportAsNonGeneric : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftImportPropertyAsAccessors : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def SwiftName : InheritableAttr {
   let Spellings = [GNU<"swift_name">];
   let Args = [StringArgument<"Name">];
@@ -2622,6 +2641,31 @@ def SwiftPrivate : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def SwiftVersioned : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
+def SwiftVersionedRemoval : Attr {
+  // This attribute has no spellings as it is only ever created implicitly
+  // from API notes.
+  let Spellings = [];
+  let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+  BoolArgument<"IsReplacedByActive">];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+  let AdditionalMembers = [{
+attr::Kind getAttrKindToRemove() const {
+  return static_cast(getRawKind());
+}
+  }];
+}
+
 def NoDeref : TypeAttr {
   let Spellings = [Clang<"noderef">];
   let Documentation = [NoDerefDocs];
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 8966a301de1db3f..21835ca74dd69de 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6215,29 +6215,35 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl 
*D,
   D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
 }
 
-static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
-  auto *E = AL.getArgAsExpr(0);
-  auto Loc = E ? E->getBeginLoc() : AL.getLoc();
-
-  auto *DRE = dyn_cast(AL.getArgAsExpr(0));
-  if (!DRE) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) {
+  if (!isa(D)) {
+S.Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  auto *VD = dyn_cast(DRE->getDecl());
-  if (!VD) {
-S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+  IdentifierLoc *IdentLoc =
+  Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+  if (!IdentLoc || !IdentLoc->Ident) {
+// Try to locate the argument directly.
+SourceLocation Loc = Attr.getLoc();
+if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
+  Loc = Attr.getArgAsExpr(0)->getBeginLoc();
+
+S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
 return;
   }
 
-  if (!isNSStringType(VD->getType(), S.Context) &&
-  !isCFStringType(VD->getType(), S.Context)) {
-S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+  // Verify that the identifier is a valid decl in the C decl namespace.
+  LookupResult Result(S, DeclarationName(IdentLoc->Ident), SourceLocation(),
+  Sema::LookupNameKind::LookupOrdinaryName);
+  if (!S.LookupName(Result, S.TUScope) || !Re

[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #73017)

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

egorzhdan wrote:

@compnerd ping ;)

https://github.com/llvm/llvm-project/pull/73017
___
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 #73017)

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

egorzhdan wrote:

@compnerd pinging again :)

https://github.com/llvm/llvm-project/pull/73017
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 5f2cf3a - [Clang][Preprocessor] Fix inconsistent `FLT_EVAL_METHOD` when compiling vs preprocessing

2022-06-29 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-06-29T19:36:22+01:00
New Revision: 5f2cf3a21f3aabff85d178a110602ce150914ff7

URL: 
https://github.com/llvm/llvm-project/commit/5f2cf3a21f3aabff85d178a110602ce150914ff7
DIFF: 
https://github.com/llvm/llvm-project/commit/5f2cf3a21f3aabff85d178a110602ce150914ff7.diff

LOG: [Clang][Preprocessor] Fix inconsistent `FLT_EVAL_METHOD` when compiling vs 
preprocessing

When running `clang -E -Ofast` on macOS, the `__FLT_EVAL_METHOD__` macro is 
`0`, which causes the following typedef to be emitted into the preprocessed 
source: `typedef float float_t`.

However, when running `clang -c -Ofast`, `__FLT_EVAL_METHOD__` is `-1`, and 
`typedef long double float_t` is emitted.

This causes build errors for certain projects, which are not reproducible when 
compiling from preprocessed source.

The issue is that `__FLT_EVAL_METHOD__` is configured in `Sema::Sema` which is 
not executed when running in `-E` mode.

This change moves that logic into the preprocessor initialization method, which 
is invoked correctly in `-E` mode.

rdar://96134605
rdar://92748429

Differential Revision: https://reviews.llvm.org/D128814

Added: 


Modified: 
clang/lib/Lex/Preprocessor.cpp
clang/lib/Sema/Sema.cpp
clang/test/Preprocessor/flt_eval_macro.cpp

Removed: 




diff  --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index fcc2d43a34ac9..281f01fb28a40 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -206,6 +206,18 @@ void Preprocessor::Initialize(const TargetInfo &Target,
 
   // Initialize the __FTL_EVAL_METHOD__ macro to the TargetInfo.
   setTUFPEvalMethod(getTargetInfo().getFPEvalMethod());
+
+  if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine)
+// Use setting from TargetInfo.
+setCurrentFPEvalMethod(SourceLocation(), Target.getFPEvalMethod());
+  else
+// Set initial value of __FLT_EVAL_METHOD__ from the command line.
+setCurrentFPEvalMethod(SourceLocation(), getLangOpts().getFPEvalMethod());
+  // When `-ffast-math` option is enabled, it triggers several driver math
+  // options to be enabled. Among those, only one the following two modes
+  // affect the eval-method:  reciprocal or reassociate.
+  if (getLangOpts().AllowFPReassoc || getLangOpts().AllowRecip)
+setCurrentFPEvalMethod(SourceLocation(), LangOptions::FEM_Indeterminable);
 }
 
 void Preprocessor::InitializeForModelFile() {

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index ad2cb62a18f0c..e2ec8eec60c33 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -249,21 +249,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer 
&consumer,
   SemaPPCallbackHandler = Callbacks.get();
   PP.addPPCallbacks(std::move(Callbacks));
   SemaPPCallbackHandler->set(*this);
-  if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine)
-// Use setting from TargetInfo.
-PP.setCurrentFPEvalMethod(SourceLocation(),
-  ctxt.getTargetInfo().getFPEvalMethod());
-  else
-// Set initial value of __FLT_EVAL_METHOD__ from the command line.
-PP.setCurrentFPEvalMethod(SourceLocation(),
-  getLangOpts().getFPEvalMethod());
+
   CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod());
-  // When `-ffast-math` option is enabled, it triggers several driver math
-  // options to be enabled. Among those, only one the following two modes
-  // affect the eval-method:  reciprocal or reassociate.
-  if (getLangOpts().AllowFPReassoc || getLangOpts().AllowRecip)
-PP.setCurrentFPEvalMethod(SourceLocation(),
-  LangOptions::FEM_Indeterminable);
 }
 
 // Anchor Sema's type info to this TU.

diff  --git a/clang/test/Preprocessor/flt_eval_macro.cpp 
b/clang/test/Preprocessor/flt_eval_macro.cpp
index 02829dcd267ec..37c28f21333f9 100644
--- a/clang/test/Preprocessor/flt_eval_macro.cpp
+++ b/clang/test/Preprocessor/flt_eval_macro.cpp
@@ -16,6 +16,9 @@
 // RUN: %clang_cc1 -E -dM -triple=arm64_32-apple-ios -target-feature -sse \
 // RUN:   %s -o - | FileCheck %s  -strict-whitespace
 
+// RUN: %clang_cc1 -E -dM -triple=x86_64-apple-macos13.0 -ffast-math \
+// RUN:   %s -o - | FileCheck %s -check-prefix=CHECK-MINUS-ONE 
-strict-whitespace
+
 // RUN: %clang_cc1 -E -dM -triple i386-pc-windows -target-cpu pentium4 %s -o - 
\
 // RUN:   | FileCheck %s  -strict-whitespace
 
@@ -35,7 +38,9 @@
 #define __GLIBC_FLT_EVAL_METHOD 2
 #endif
 
-#if __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16
+#if __GLIBC_FLT_EVAL_METHOD == -1
+#define Name "MinusOne"
+#elif __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16
 #define Name "One"
 #elif __GLIBC_FLT_EVAL_METHOD == 1
 #define Name "Two"
@@ -59,6 +64,7 @@
 
 int foo() {
   // CHECK: #define Name "One"
+  // CHECK-MINUS-ONE: #define Name "MinusOne"
   // EXT: #define Na

[clang] 6ca2f19 - [Clang][Sema] Avoid crashing for `__builtin_memcpy_inline` with an array argument

2022-03-14 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-03-14T12:47:30Z
New Revision: 6ca2f1938f96a71abdecdd96508f48e4d20a5694

URL: 
https://github.com/llvm/llvm-project/commit/6ca2f1938f96a71abdecdd96508f48e4d20a5694
DIFF: 
https://github.com/llvm/llvm-project/commit/6ca2f1938f96a71abdecdd96508f48e4d20a5694.diff

LOG: [Clang][Sema] Avoid crashing for `__builtin_memcpy_inline` with an array 
argument

This change teaches the Sema logic for `__builtin_memcpy_inline` to implicitly 
convert arrays passed as arguments to pointers, similarly to regular `memcpy`.

This code will no longer cause a compiler crash:
```
void f(char *p) {
char s[1] = {0};
__builtin_memcpy_inline(p, s, 1);
}
```

rdar://88147527

Differential Revision: https://reviews.llvm.org/D121475

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/builtins-memcpy-inline.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2bd0d113fc992..2d14019cdbf18 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1943,6 +1943,17 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
   case Builtin::BI__builtin_nontemporal_store:
 return SemaBuiltinNontemporalOverloaded(TheCallResult);
   case Builtin::BI__builtin_memcpy_inline: {
+auto ArgArrayConversionFailed = [&](unsigned Arg) {
+  ExprResult ArgExpr =
+  DefaultFunctionArrayLvalueConversion(TheCall->getArg(Arg));
+  if (ArgExpr.isInvalid())
+return true;
+  TheCall->setArg(Arg, ArgExpr.get());
+  return false;
+};
+
+if (ArgArrayConversionFailed(0) || ArgArrayConversionFailed(1))
+  return true;
 clang::Expr *SizeOp = TheCall->getArg(2);
 // We warn about copying to or from `nullptr` pointers when `size` is
 // greater than 0. When `size` is value dependent we cannot evaluate its

diff  --git a/clang/test/Sema/builtins-memcpy-inline.cpp 
b/clang/test/Sema/builtins-memcpy-inline.cpp
index 81b11fc021fff..30bc636c78393 100644
--- a/clang/test/Sema/builtins-memcpy-inline.cpp
+++ b/clang/test/Sema/builtins-memcpy-inline.cpp
@@ -36,3 +36,9 @@ void test_memcpy_inline_template(void *dst, const void *src) {
   // we do not try to evaluate size in non intantiated templates.
   __builtin_memcpy_inline(dst, src, size);
 }
+
+void test_memcpy_inline_implicit_conversion(void *ptr) {
+  char a[5];
+  __builtin_memcpy_inline(ptr, a, 5);
+  __builtin_memcpy_inline(a, ptr, 5);
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 33a9eac - [Clang] Support multiple attributes in a single pragma

2022-03-18 Thread Egor Zhdan via cfe-commits

Author: Egor Zhdan
Date: 2022-03-18T12:20:41Z
New Revision: 33a9eac6aaa495fce6fd9b17cd48aa57a95461e6

URL: 
https://github.com/llvm/llvm-project/commit/33a9eac6aaa495fce6fd9b17cd48aa57a95461e6
DIFF: 
https://github.com/llvm/llvm-project/commit/33a9eac6aaa495fce6fd9b17cd48aa57a95461e6.diff

LOG: [Clang] Support multiple attributes in a single pragma

This adds support for multiple attributes in `#pragma clang attribute push`, 
for example:

```
```
or
```
```

Related attributes can now be applied with a single pragma, which makes it 
harder for developers to make an accidental error later when editing the code.

rdar://78269653

Differential Revision: https://reviews.llvm.org/D121283

Added: 
clang/test/AST/pragma-multiple-attributes-declspec.cpp
clang/test/AST/pragma-multiple-attributes.cpp

Modified: 
clang/docs/LanguageExtensions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/AttrSubjectMatchRules.h
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParsePragma.cpp
clang/test/FixIt/fixit-pragma-attribute.c
clang/test/FixIt/fixit-pragma-attribute.cpp
clang/test/Parser/pragma-attribute-declspec.cpp
clang/test/Parser/pragma-attribute.cpp

Removed: 




diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index d670bf55eec98..685f834a8495a 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -4121,8 +4121,22 @@ The ``__declspec`` style syntax is also supported:
 
   #pragma clang attribute pop
 
-A single push directive accepts only one attribute regardless of the syntax
-used.
+A single push directive can contain multiple attributes, however, 
+only one syntax style can be used within a single directive:
+
+.. code-block:: c++
+
+  #pragma clang attribute push ([[noreturn, noinline]], apply_to = function)
+
+  void function1(); // The function now has the [[noreturn]] and [[noinline]] 
attributes
+
+  #pragma clang attribute pop
+  
+  #pragma clang attribute push (__attribute((noreturn, noinline)), apply_to = 
function)
+
+  void function2(); // The function now has the __attribute((noreturn)) and 
__attribute((noinline)) attributes
+
+  #pragma clang attribute pop
 
 Because multiple push directives can be nested, if you're writing a macro that
 expands to ``_Pragma("clang attribute")`` it's good hygiene (though not

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 21531bf72cd5b..5ddec067bc22f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -106,6 +106,8 @@ Attribute Changes in Clang
 - Statement attributes ``[[clang::noinline]]`` and  
``[[clang::always_inline]]``
   can be used to control inlining decisions at callsites.
 
+- ``#pragma clang attribute push`` now supports multiple attributes within a 
single directive.
+
 Windows Support
 ---
 

diff  --git a/clang/include/clang/Basic/AttrSubjectMatchRules.h 
b/clang/include/clang/Basic/AttrSubjectMatchRules.h
index 4a4c1a883cf42..e3dcb943e59d4 100644
--- a/clang/include/clang/Basic/AttrSubjectMatchRules.h
+++ b/clang/include/clang/Basic/AttrSubjectMatchRules.h
@@ -18,6 +18,9 @@ namespace attr {
 /// A list of all the recognized kinds of attributes.
 enum SubjectMatchRule {
 #define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X,
+#include "clang/Basic/AttrSubMatchRulesList.inc"
+  SubjectMatchRule_Last = -1
+#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) +1
 #include "clang/Basic/AttrSubMatchRulesList.inc"
 };
 

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 7af15f5504ff9..1640a75391831 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1237,8 +1237,6 @@ def err_pragma_attribute_extra_tokens_after_attribute : 
Error<
   "extra tokens after attribute in a '#pragma clang attribute push'">;
 def err_pragma_attribute_unsupported_attribute : Error<
   "attribute %0 is not supported by '#pragma clang attribute'">;
-def err_pragma_attribute_multiple_attributes : Error<
-  "more than one attribute specified in '#pragma clang attribute push'">;
 def err_pragma_attribute_expected_attribute_syntax : Error<
   "expected an attribute that is specified using the GNU, C++11 or 
'__declspec'"
   " syntax">;

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 44a05eec4e350..135b2dfe54167 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -600,6 +600,8 @@ unsigned Parser::ParseClangAttributeArgs(
 bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
 SourceLocation AttrNameLoc,
 ParsedAttributes &Attrs) {
+  unsigned ExistingAttrs = Attrs.size();
+
  

[clang] 1d0cc51 - [Clang][Driver] Fix include paths for `--sysroot /` on OpenBSD/FreeBSD

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

Author: Egor Zhdan
Date: 2022-07-22T14:30:32+01:00
New Revision: 1d0cc510516d50c459f78896a0375fadb13a2b45

URL: 
https://github.com/llvm/llvm-project/commit/1d0cc510516d50c459f78896a0375fadb13a2b45
DIFF: 
https://github.com/llvm/llvm-project/commit/1d0cc510516d50c459f78896a0375fadb13a2b45.diff

LOG: [Clang][Driver] Fix include paths for `--sysroot /` on OpenBSD/FreeBSD

This is the same change as https://reviews.llvm.org/D126289, but applied for 
OpenBSD & FreeBSD.

Differential Revision: https://reviews.llvm.org/D129654

Added: 
clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/bin/.keep
clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/include/c++/v1/.keep
clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/lib/.keep
clang/test/Driver/Inputs/basic_openbsd_libcxx_tree/usr/bin/.keep
clang/test/Driver/Inputs/basic_openbsd_libcxx_tree/usr/include/c++/v1/.keep
clang/test/Driver/Inputs/basic_openbsd_libcxx_tree/usr/lib/.keep

Modified: 
clang/lib/Driver/ToolChains/FreeBSD.cpp
clang/lib/Driver/ToolChains/OpenBSD.cpp
clang/test/Driver/freebsd.cpp
clang/test/Driver/openbsd.cpp

Removed: 




diff  --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp 
b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index fec80f85e2787..e5451c20a00c8 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -389,10 +389,10 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple 
&Triple,
   // back to '/usr/lib' if it doesn't exist.
   if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
Triple.isPPC32()) &&
-  D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
-getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
+  D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o")))
+getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32"));
   else
-getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
 }
 
 ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
@@ -411,14 +411,14 @@ unsigned FreeBSD::GetDefaultDwarfVersion() const {
 void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
 llvm::opt::ArgStringList &CC1Args) const {
   addSystemInclude(DriverArgs, CC1Args,
-   getDriver().SysRoot + "/usr/include/c++/v1");
+   concat(getDriver().SysRoot, "/usr/include/c++/v1"));
 }
 
 void FreeBSD::addLibStdCxxIncludePaths(
 const llvm::opt::ArgList &DriverArgs,
 llvm::opt::ArgStringList &CC1Args) const {
-  addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", 
"",
-   DriverArgs, CC1Args);
+  addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"),
+   "", "", DriverArgs, CC1Args);
 }
 
 void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,

diff  --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp 
b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 44cc9dee67f4d..8b3a40606ff32 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -284,7 +284,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
 OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
  const ArgList &Args)
 : Generic_ELF(D, Triple, Args) {
-  getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+  getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
 }
 
 void OpenBSD::AddClangSystemIncludeArgs(
@@ -317,13 +317,14 @@ void OpenBSD::AddClangSystemIncludeArgs(
 return;
   }
 
-  addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
+  addExternCSystemInclude(DriverArgs, CC1Args,
+  concat(D.SysRoot, "/usr/include"));
 }
 
 void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
 llvm::opt::ArgStringList &CC1Args) const {
   addSystemInclude(DriverArgs, CC1Args,
-   getDriver().SysRoot + "/usr/include/c++/v1");
+   concat(getDriver().SysRoot, "/usr/include/c++/v1"));
 }
 
 void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,

diff  --git a/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/bin/.keep 
b/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/bin/.keep
new file mode 100644
index 0..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/include/c++/v1/.keep 
b/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/include/c++/v1/.keep
new file mode 100644
index 0..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/lib/.keep 
b/clang/test/Driver/Inputs/basic_freebsd_libcxx_tree/usr/lib/.keep
new file mode 100644
index 0

[clang] 2f04e70 - [Clang] Add DriverKit support

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

Author: Egor Zhdan
Date: 2022-05-13T20:34:57+01:00
New Revision: 2f04e703bff3d9858f53225fa7c780b240c3e247

URL: 
https://github.com/llvm/llvm-project/commit/2f04e703bff3d9858f53225fa7c780b240c3e247
DIFF: 
https://github.com/llvm/llvm-project/commit/2f04e703bff3d9858f53225fa7c780b240c3e247.diff

LOG: [Clang] Add DriverKit support

This is the second patch that upstreams the support for Apple's DriverKit.

The first patch: https://reviews.llvm.org/D118046.

Differential Revision: https://reviews.llvm.org/D121911

Added: 
clang/test/CodeGen/availability-check-driverkit.c
clang/test/Driver/Inputs/DriverKit19.0.sdk/SDKSettings.plist

clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/usr/include/.keep

clang/test/Driver/Inputs/basic_darwin_driverkit_sdk_usr_cxx_v1/System/DriverKit/usr/include/c++/v1/.keep

clang/test/Driver/Inputs/basic_darwin_driverkit_sdk_usr_cxx_v1/System/DriverKit/usr/lib/.keep
clang/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.driverkit.a
clang/test/Driver/darwin-ld-platform-version-driverkit.c
clang/test/Driver/driverkit-arm64.c
clang/test/Driver/driverkit-arm64e.c
clang/test/Driver/driverkit-armv7k.s
clang/test/Driver/driverkit-cplusplus.cpp
clang/test/Driver/driverkit-exceptions.cpp
clang/test/Driver/driverkit-framework.c
clang/test/Driver/driverkit-rtti.cpp
clang/test/Driver/driverkit-target-cpu.c
clang/test/Driver/driverkit-version-min.c
clang/test/Sema/attr-availability-driverkit.c

Modified: 
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/Features.def
clang/include/clang/Driver/Options.td
clang/lib/Basic/LangStandards.cpp
clang/lib/Basic/Targets/OSTargets.cpp
clang/lib/Basic/Targets/OSTargets.h
clang/lib/CodeGen/CGObjC.cpp
clang/lib/Driver/Driver.cpp
clang/lib/Driver/ToolChain.cpp
clang/lib/Driver/ToolChains/Arch/ARM.cpp
clang/lib/Driver/ToolChains/Arch/X86.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/Darwin.cpp
clang/lib/Driver/ToolChains/Darwin.h
clang/test/Driver/darwin-ld.c
clang/test/Driver/darwin-version.c
clang/test/Driver/debug-options.c
clang/test/Driver/incompatible_sysroot.c
clang/test/Driver/instrprof-ld.c
clang/test/Driver/pic.c
clang/test/Driver/stack-protector.c
clang/test/Frontend/darwin-version.c
clang/test/Preprocessor/arm-target-features.c

Removed: 




diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3c41edb474e89..0c95adfa237d7 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -870,6 +870,7 @@ def Availability : InheritableAttr {
  .Case("macos", "macOS")
  .Case("tvos", "tvOS")
  .Case("watchos", "watchOS")
+ .Case("driverkit", "DriverKit")
  .Case("ios_app_extension", "iOS (App Extension)")
  .Case("macos_app_extension", "macOS (App Extension)")
  .Case("tvos_app_extension", "tvOS (App Extension)")

diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index b389ff9c02c45..d635da6b84b84 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1555,6 +1555,10 @@ attributes are ignored. Supported platforms are:
 ``watchos``
   Apple's watchOS operating system. The minimum deployment target is specified 
by
   the ``-mwatchos-version-min=*version*`` command-line argument.
+  
+``driverkit``
+  Apple's DriverKit userspace kernel extensions. The minimum deployment target
+  is specified as part of the triple.
 
 A declaration can typically be used even when deploying back to a platform
 version prior to when the declaration was introduced. When this happens, the

diff  --git a/clang/include/clang/Basic/Features.def 
b/clang/include/clang/Basic/Features.def
index c3f3fe79770db..f241d68a23ed9 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -61,6 +61,7 @@ FEATURE(attribute_availability_app_extension, true)
 FEATURE(attribute_availability_with_version_underscores, true)
 FEATURE(attribute_availability_tvos, true)
 FEATURE(attribute_availability_watchos, true)
+FEATURE(attribute_availability_driverkit, true)
 FEATURE(attribute_availability_with_strict, true)
 FEATURE(attribute_availability_with_replacement, true)
 FEATURE(attribute_availability_in_templates, true)

diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index d1d7ca9698b14..ecdddff5b6831 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3914,6 +3914,7 @@ def nogpulib : Flag<["-"], "nogpulib">, 
MarshallingInfoFlag
   Flags<[CC1Option]>, Help

[clang] af845d7 - [Clang] Fix DriverKit tests on Linux

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

Author: Egor Zhdan
Date: 2022-05-13T22:10:13+01:00
New Revision: af845d7e437a0380f65db841f2917f3c1a95ecf5

URL: 
https://github.com/llvm/llvm-project/commit/af845d7e437a0380f65db841f2917f3c1a95ecf5
DIFF: 
https://github.com/llvm/llvm-project/commit/af845d7e437a0380f65db841f2917f3c1a95ecf5.diff

LOG: [Clang] Fix DriverKit tests on Linux

Some new DriverKit tests were added in https://reviews.llvm.org/D121911, and 
unfortunately they fail on Linux build bots.

Added: 


Modified: 
clang/test/Driver/darwin-ld-platform-version-driverkit.c
clang/test/Driver/darwin-ld.c

Removed: 




diff  --git a/clang/test/Driver/darwin-ld-platform-version-driverkit.c 
b/clang/test/Driver/darwin-ld-platform-version-driverkit.c
index f4fadc45079e..539d4c4f2557 100644
--- a/clang/test/Driver/darwin-ld-platform-version-driverkit.c
+++ b/clang/test/Driver/darwin-ld-platform-version-driverkit.c
@@ -6,11 +6,11 @@
 // RUN: %clang -target x86_64-apple-driverkit19 -isysroot %t.sdk 
-mlinker-version=520 -### %t.o 2>&1 \
 // RUN:   | FileCheck --check-prefix=MISSING-SDK-JSON-WORKAROUND %s
 
-// RUN: %clang -target arm64-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -mlinker-version=520 -### %t.o 2>&1 \
+// RUN: %clang -target arm64-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -fuse-ld= -mlinker-version=520 -### %t.o 2>&1 \
 // RUN:   | FileCheck --check-prefix=ARM64_NEW %s
-// RUN: %clang -target arm64-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -mlinker-version=400 -### %t.o 2>&1 \
+// RUN: %clang -target arm64-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -fuse-ld= -mlinker-version=400 -### %t.o 2>&1 \
 // RUN:   | FileCheck --check-prefix=ARM64_OLD %s
-// RUN: %clang -target arm64e-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -mlinker-version=520 -### %t.o 2>&1 \
+// RUN: %clang -target arm64e-apple-driverkit19 -isysroot 
%S/Inputs/MacOSX10.14.sdk -fuse-ld= -mlinker-version=520 -### %t.o 2>&1 \
 // RUN:   | FileCheck --check-prefix=ARM64_NEW %s
 
 // CHECK: "-platform_version" "driverkit" "10.15.0" "10.14"

diff  --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c
index 73840d1b56b6..3a836d4dd1f1 100644
--- a/clang/test/Driver/darwin-ld.c
+++ b/clang/test/Driver/darwin-ld.c
@@ -185,7 +185,7 @@
 // LINK_TVOS_KEXT: libclang_rt.cc_kext_tvos.a
 // LINK_TVOS_KEXT: libclang_rt.tvos.a
 
-// RUN: %clang -target x86-64-apple-driverkit19.0 -mlinker-version=400 
-resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
+// RUN: %clang -target x86-64-apple-driverkit19.0 -fuse-ld= 
-mlinker-version=400 -resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
 // RUN: FileCheck -check-prefix=LINK_DRIVERKIT %s < %t.log
 // LINK_DRIVERKIT: {{ld(.exe)?"}}
 // LINK_DRIVERKIT: -driverkit_version_min



___
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] [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


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


  1   2   3   4   >