[PATCH] D151373: [libclang] Expose arguments of clang::annotate{_type}

2023-07-25 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof updated this revision to Diff 544142.
fridtjof added a comment.

I fixed the failing IBOutletCollection.m test - there was code to do special 
handling for the respective attribute type, which my patch accidentally skipped 
previously. I reordered the generic attribute handling to come after the 
special cases in VisitChildren.

I cleaned up my unit test. After trying a bit to fix it for testing 
annotate_type as well, I found out that for some unknown reason it is not 
exposed like usual attributes (maybe because it's a type attribute?).
Therefore, I decided to drop it from the test altogether.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

Files:
  clang/docs/ReleaseNotes.rst
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -1246,6 +1246,50 @@
   EXPECT_EQ(fromCXString(clang_getCursorSpelling(*staticAssertCsr)), "");
 }
 
+TEST_F(LibclangParseTest, ExposesAnnotateArgs) {
+  const char testSource[] = R"cpp(
+[[clang::annotate("category", 42)]]
+void func() {}
+)cpp";
+  std::string fileName = "main.cpp";
+  WriteFile(fileName, testSource);
+
+  const char *Args[] = {"-xc++"};
+  ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), Args, 1,
+   nullptr, 0, TUFlags);
+
+  int attrCount = 0;
+
+  Traverse(
+  [&attrCount](CXCursor cursor, CXCursor parent) -> CXChildVisitResult {
+if (cursor.kind == CXCursor_AnnotateAttr) {
+  int childCount = 0;
+  clang_visitChildren(
+  cursor,
+  [](CXCursor child, CXCursor,
+ CXClientData data) -> CXChildVisitResult {
+int *pcount = static_cast(data);
+
+// we only expect one argument here, so bail otherwise
+EXPECT_EQ(*pcount, 0);
+
+auto *result = clang_Cursor_Evaluate(child);
+EXPECT_NE(result, nullptr);
+EXPECT_EQ(clang_EvalResult_getAsInt(result), 42);
+++*pcount;
+
+return CXChildVisit_Recurse;
+  },
+  &childCount);
+  attrCount++;
+  return CXChildVisit_Continue;
+}
+return CXChildVisit_Recurse;
+  });
+
+  EXPECT_EQ(attrCount, 1);
+}
+
 class LibclangRewriteTest : public LibclangParseTest {
 public:
   CXRewriter Rew = nullptr;
Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -23,6 +23,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -575,6 +576,13 @@
   A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   // If pointing inside a macro definition, check if the token is an identifier
   // that was ever defined as a macro. In such a case, create a "pseudo" macro
   // expansion cursor for that token.
@@ -2089,7 +2097,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2231,6 +2240,10 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+  void VisitAnnotateTypeAttr(const AnnotateTypeAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2242,6 +2255,11 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  template ::value ||
+ 

[PATCH] D151373: [libclang] Expose arguments of clang::annotate

2023-08-10 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof updated this revision to Diff 549197.
fridtjof added a comment.

It was the unit test I added - I forgot to properly dispose of the EvalResult 
there


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

Files:
  clang/docs/ReleaseNotes.rst
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -1246,6 +1246,52 @@
   EXPECT_EQ(fromCXString(clang_getCursorSpelling(*staticAssertCsr)), "");
 }
 
+TEST_F(LibclangParseTest, ExposesAnnotateArgs) {
+  const char testSource[] = R"cpp(
+[[clang::annotate("category", 42)]]
+void func() {}
+)cpp";
+  std::string fileName = "main.cpp";
+  WriteFile(fileName, testSource);
+
+  const char *Args[] = {"-xc++"};
+  ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), Args, 1,
+   nullptr, 0, TUFlags);
+
+  int attrCount = 0;
+
+  Traverse(
+  [&attrCount](CXCursor cursor, CXCursor parent) -> CXChildVisitResult {
+if (cursor.kind == CXCursor_AnnotateAttr) {
+  int childCount = 0;
+  clang_visitChildren(
+  cursor,
+  [](CXCursor child, CXCursor,
+ CXClientData data) -> CXChildVisitResult {
+int *pcount = static_cast(data);
+
+// we only expect one argument here, so bail otherwise
+EXPECT_EQ(*pcount, 0);
+
+auto *result = clang_Cursor_Evaluate(child);
+EXPECT_NE(result, nullptr);
+EXPECT_EQ(clang_EvalResult_getAsInt(result), 42);
+clang_EvalResult_dispose(result);
+
+++*pcount;
+
+return CXChildVisit_Recurse;
+  },
+  &childCount);
+  attrCount++;
+  return CXChildVisit_Continue;
+}
+return CXChildVisit_Recurse;
+  });
+
+  EXPECT_EQ(attrCount, 1);
+}
+
 class LibclangRewriteTest : public LibclangParseTest {
 public:
   CXRewriter Rew = nullptr;
Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -23,6 +23,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -575,6 +576,13 @@
   A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   // If pointing inside a macro definition, check if the token is an identifier
   // that was ever defined as a macro. In such a case, create a "pseudo" macro
   // expansion cursor for that token.
@@ -2089,7 +2097,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2231,6 +2240,9 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2242,6 +2254,7 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  void EnqueueChildren(const AnnotateAttr *A);
 };
 } // namespace
 
@@ -2736,6 +2749,20 @@
   VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
   std::reverse(I, E);
 }
+
+void EnqueueVisitor::EnqueueChildren(const AnnotateAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+VisitStmt(Arg);
+  }
+  if (size == WL.size())
+return;
+  // Now reverse the entries we just added.  This will match the DFS
+  // ordering performed by the wor

[PATCH] D151373: [libclang] Expose arguments of clang::annotate

2023-07-28 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof updated this revision to Diff 545305.
fridtjof retitled this revision from "[libclang] Expose arguments of 
clang::annotate{_type}" to "[libclang] Expose arguments of clang::annotate".
fridtjof edited the summary of this revision.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

Files:
  clang/docs/ReleaseNotes.rst
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -1246,6 +1246,50 @@
   EXPECT_EQ(fromCXString(clang_getCursorSpelling(*staticAssertCsr)), "");
 }
 
+TEST_F(LibclangParseTest, ExposesAnnotateArgs) {
+  const char testSource[] = R"cpp(
+[[clang::annotate("category", 42)]]
+void func() {}
+)cpp";
+  std::string fileName = "main.cpp";
+  WriteFile(fileName, testSource);
+
+  const char *Args[] = {"-xc++"};
+  ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), Args, 1,
+   nullptr, 0, TUFlags);
+
+  int attrCount = 0;
+
+  Traverse(
+  [&attrCount](CXCursor cursor, CXCursor parent) -> CXChildVisitResult {
+if (cursor.kind == CXCursor_AnnotateAttr) {
+  int childCount = 0;
+  clang_visitChildren(
+  cursor,
+  [](CXCursor child, CXCursor,
+ CXClientData data) -> CXChildVisitResult {
+int *pcount = static_cast(data);
+
+// we only expect one argument here, so bail otherwise
+EXPECT_EQ(*pcount, 0);
+
+auto *result = clang_Cursor_Evaluate(child);
+EXPECT_NE(result, nullptr);
+EXPECT_EQ(clang_EvalResult_getAsInt(result), 42);
+++*pcount;
+
+return CXChildVisit_Recurse;
+  },
+  &childCount);
+  attrCount++;
+  return CXChildVisit_Continue;
+}
+return CXChildVisit_Recurse;
+  });
+
+  EXPECT_EQ(attrCount, 1);
+}
+
 class LibclangRewriteTest : public LibclangParseTest {
 public:
   CXRewriter Rew = nullptr;
Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -23,6 +23,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -575,6 +576,13 @@
   A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   // If pointing inside a macro definition, check if the token is an identifier
   // that was ever defined as a macro. In such a case, create a "pseudo" macro
   // expansion cursor for that token.
@@ -2089,7 +2097,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2231,6 +2240,9 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2242,6 +2254,10 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  template ::value,
+ bool> = true>
+  void EnqueueChildren(const AnnAttr *A);
 };
 } // namespace
 
@@ -2736,6 +2752,23 @@
   VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
   std::reverse(I, E);
 }
+
+template ::value,
+   bool>>
+void EnqueueVisitor::EnqueueChildren(const AnnAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+VisitStmt(Arg);
+  }
+  if (

[PATCH] D151373: [libclang] Expose arguments of clang::annotate

2023-07-28 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof added a comment.

In D151373#4538604 , @aaron.ballman 
wrote:

> I think we should drop the `annotate_type` functionality from the patch 
> entirely rather than add it without any test coverage knowing it doesn't seem 
> to work as expected.

Agreed - I removed the superfluous code and also cleaned up the summary 
accordingly.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

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


[PATCH] D151373: [libclang] Expose arguments of clang::annotate

2023-07-29 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof updated this revision to Diff 545388.
fridtjof added a comment.

Whoops, forgot to run clang-format on the last diff. Also took the opportunity 
to just get rid of the template mess now that we're only dealing with 
AnnotateAttr anyway.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

Files:
  clang/docs/ReleaseNotes.rst
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -1246,6 +1246,50 @@
   EXPECT_EQ(fromCXString(clang_getCursorSpelling(*staticAssertCsr)), "");
 }
 
+TEST_F(LibclangParseTest, ExposesAnnotateArgs) {
+  const char testSource[] = R"cpp(
+[[clang::annotate("category", 42)]]
+void func() {}
+)cpp";
+  std::string fileName = "main.cpp";
+  WriteFile(fileName, testSource);
+
+  const char *Args[] = {"-xc++"};
+  ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), Args, 1,
+   nullptr, 0, TUFlags);
+
+  int attrCount = 0;
+
+  Traverse(
+  [&attrCount](CXCursor cursor, CXCursor parent) -> CXChildVisitResult {
+if (cursor.kind == CXCursor_AnnotateAttr) {
+  int childCount = 0;
+  clang_visitChildren(
+  cursor,
+  [](CXCursor child, CXCursor,
+ CXClientData data) -> CXChildVisitResult {
+int *pcount = static_cast(data);
+
+// we only expect one argument here, so bail otherwise
+EXPECT_EQ(*pcount, 0);
+
+auto *result = clang_Cursor_Evaluate(child);
+EXPECT_NE(result, nullptr);
+EXPECT_EQ(clang_EvalResult_getAsInt(result), 42);
+++*pcount;
+
+return CXChildVisit_Recurse;
+  },
+  &childCount);
+  attrCount++;
+  return CXChildVisit_Continue;
+}
+return CXChildVisit_Recurse;
+  });
+
+  EXPECT_EQ(attrCount, 1);
+}
+
 class LibclangRewriteTest : public LibclangParseTest {
 public:
   CXRewriter Rew = nullptr;
Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -23,6 +23,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -575,6 +576,13 @@
   A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   // If pointing inside a macro definition, check if the token is an identifier
   // that was ever defined as a macro. In such a case, create a "pseudo" macro
   // expansion cursor for that token.
@@ -2089,7 +2097,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2231,6 +2240,9 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2242,6 +2254,7 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  void EnqueueChildren(const AnnotateAttr *A);
 };
 } // namespace
 
@@ -2736,6 +2749,20 @@
   VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
   std::reverse(I, E);
 }
+
+void EnqueueVisitor::EnqueueChildren(const AnnotateAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+VisitStmt(Arg);
+  }
+  if (size == WL.size())
+return;
+  // Now reverse the entries we just added.  This will match the DFS
+

[PATCH] D151373: [libclang] Expose arguments of clang::annotate

2023-08-10 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof added a comment.

(Whoops, somehow never got a mail for that reply)

Yes, please. You can attribute the commit to "fridtjof "


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

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


[PATCH] D151373: [libclang] Expose arguments of clang::annotate{_type}

2023-05-24 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof created this revision.
fridtjof added a reviewer: aaron.ballman.
Herald added a subscriber: arphaman.
Herald added a project: All.
fridtjof requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This enables easy consumption of arbitrary data added
to these annotations in addition to the annotation category,
which was already exposed.

I mostly just copied all the bits and pieces that seemed to do similar stuff, 
which seems to work.

I tested this locally with a very small C++ program to try and dump arguments 
for clang::annotate, which works.
Adding annotate_type to my test source code does not even expose the annotation 
itself however (I've attached it to parameter and variable types to no 
success), which seems like an unrelated bug (it should work for all Decls!).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151373

Files:
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h

Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -22,6 +22,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Mangle.h"
 #include "clang/AST/OpenMPClause.h"
@@ -523,6 +524,13 @@
 return false;
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   if (clang_isTranslationUnit(Cursor.kind)) {
 CXTranslationUnit TU = getCursorTU(Cursor);
 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
@@ -2085,7 +2093,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2227,6 +2236,10 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+  void VisitAnnotateTypeAttr(const AnnotateTypeAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2238,6 +2251,8 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  void EnqueueChildren(const AnnotateAttr *A);
+  void EnqueueChildren(const AnnotateTypeAttr *A);
 };
 } // namespace
 
@@ -2727,6 +2742,31 @@
   VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
   std::reverse(I, E);
 }
+// TODO these two methods are exactly the same. Can this be expressed better?
+void EnqueueVisitor::EnqueueChildren(const AnnotateAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+VisitStmt(Arg);
+  }
+  if (size == WL.size())
+return;
+  // Now reverse the entries we just added.  This will match the DFS
+  // ordering performed by the worklist.
+  VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+  std::reverse(I, E);
+}
+void EnqueueVisitor::EnqueueChildren(const AnnotateTypeAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+AddStmt(Arg);
+  }
+  if (size == WL.size())
+return;
+  // Now reverse the entries we just added.  This will match the DFS
+  // ordering performed by the worklist.
+  VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+  std::reverse(I, E);
+}
 void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) {
   WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
 }
@@ -2999,7 +3039,7 @@
   // If the opaque value has a source expression, just transparently
   // visit that.  This is useful for (e.g.) pseudo-object expressions.
   if (Expr *SourceExpr = E->getSourceExpr())
-return Visit(SourceExpr);
+return ConstStmtVisitor::Visit(SourceExpr);
 }
 void EnqueueVisitor::VisitLambdaExpr(const LambdaExpr *E) {
   AddStmt(E->getBody());
@@ -3019,7 +3059,7 @@
 }
 void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
   // Treat the expression like its syntact

[PATCH] D151373: [libclang] Expose arguments of clang::annotate{_type}

2023-06-10 Thread Fridtjof Mund via Phabricator via cfe-commits
fridtjof updated this revision to Diff 530219.
fridtjof added a comment.

- Deduplicated code by using templates (looks a bit ridicilous though)
- Release notes entry added
- Unit test added


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151373/new/

https://reviews.llvm.org/D151373

Files:
  clang/docs/ReleaseNotes.rst
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CursorVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -1172,6 +1172,48 @@
   });
 }
 
+TEST_F(LibclangParseTest, ExposedAnnotateArgs) {
+  // TODO
+  const char testSource[] = R"cpp(
+int [[clang::annotate_type("category_type", 42)]] f;
+
+[[clang::annotate("category", 42)]]
+void func() {}
+)cpp";
+  std::string fileName = "main.cpp";
+  WriteFile(fileName, testSource);
+
+  const char *Args[] = {"-xc++"};
+  ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), Args, 1,
+   nullptr, 0, TUFlags);
+
+  Traverse([&](CXCursor cursor, CXCursor parent) -> CXChildVisitResult {
+if (cursor.kind != CXCursor_AnnotateAttr)
+  return CXChildVisit_Recurse;
+
+int childCount = 0;
+
+clang_visitChildren(
+cursor,
+[](CXCursor child, CXCursor, CXClientData data) -> CXChildVisitResult {
+  int *pcount = static_cast(data);
+
+  // we only expect one argument here, so bail
+  EXPECT_EQ(*pcount, 0);
+
+  auto *result = clang_Cursor_Evaluate(child);
+  EXPECT_NE(result, nullptr);
+  EXPECT_EQ(clang_EvalResult_getAsInt(result), 42);
+  ++*pcount;
+
+  return CXChildVisit_Recurse;
+},
+&childCount);
+
+return CXChildVisit_Continue;
+  });
+}
+
 class LibclangRewriteTest : public LibclangParseTest {
 public:
   CXRewriter Rew = nullptr;
Index: clang/tools/libclang/CursorVisitor.h
===
--- clang/tools/libclang/CursorVisitor.h
+++ clang/tools/libclang/CursorVisitor.h
@@ -276,7 +276,9 @@
   bool IsInRegionOfInterest(CXCursor C);
   bool RunVisitorWorkList(VisitorWorkList &WL);
   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+  void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);
   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);
 
 private:
   std::optional handleDeclForVisitation(const Decl *D);
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -22,6 +22,7 @@
 #include "CursorVisitor.h"
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
 #include "clang/AST/DeclObjCCommon.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -526,6 +527,13 @@
 return false;
   }
 
+  if (clang_isAttribute(Cursor.kind)) {
+if (const Attr *A = getCursorAttr(Cursor))
+  return Visit(A);
+
+return false;
+  }
+
   if (clang_isTranslationUnit(Cursor.kind)) {
 CXTranslationUnit TU = getCursorTU(Cursor);
 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
@@ -2088,7 +2096,8 @@
 (SourceLocation::UIntTy)(uintptr_t)data[1]);
   }
 };
-class EnqueueVisitor : public ConstStmtVisitor {
+class EnqueueVisitor : public ConstStmtVisitor,
+   public ConstAttrVisitor {
   friend class OMPClauseEnqueue;
   VisitorWorkList &WL;
   CXCursor Parent;
@@ -2230,6 +2239,10 @@
   void VisitOMPTargetTeamsDistributeSimdDirective(
   const OMPTargetTeamsDistributeSimdDirective *D);
 
+  // Attributes
+  void VisitAnnotateAttr(const AnnotateAttr *A);
+  void VisitAnnotateTypeAttr(const AnnotateTypeAttr *A);
+
 private:
   void AddDeclarationNameInfo(const Stmt *S);
   void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
@@ -2241,6 +2254,11 @@
   void AddTypeLoc(TypeSourceInfo *TI);
   void EnqueueChildren(const Stmt *S);
   void EnqueueChildren(const OMPClause *S);
+  template ::value ||
+ std::is_same::value,
+ bool> = true>
+  void EnqueueChildren(const AnnAttr *A);
 };
 } // namespace
 
@@ -2730,6 +2748,24 @@
   VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
   std::reverse(I, E);
 }
+
+template ::value ||
+   std::is_same::value,
+   bool>>
+void EnqueueVisitor::EnqueueChildren(const AnnAttr *A) {
+  unsigned size = WL.size();
+  for (const Expr *Arg : A->args()) {
+VisitStmt(Arg);
+  }
+  if (size == WL.size())
+return;
+  // Now reverse the entries we just added.  This will match the DFS
+  // ordering performed by the worklist.
+  VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+  s