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<int *>(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<bool> 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<EnqueueVisitor, void> {
+class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>,
+ public ConstAttrVisitor<EnqueueVisitor, void> {
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 <typename AnnAttr,
+ std::enable_if_t<std::is_same<AnnAttr, AnnotateAttr>::value ||
+ std::is_same<AnnAttr, AnnotateTypeAttr>::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 <typename AnnAttr,
+ std::enable_if_t<std::is_same<AnnAttr, AnnotateAttr>::value ||
+ std::is_same<AnnAttr, AnnotateTypeAttr>::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();
+ std::reverse(I, E);
+}
+
void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) {
WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
}
@@ -3002,7 +3038,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());
@@ -3022,7 +3058,7 @@
}
void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
// Treat the expression like its syntactic form.
- Visit(E->getSyntacticForm());
+ ConstStmtVisitor::Visit(E->getSyntacticForm());
}
void EnqueueVisitor::VisitOMPExecutableDirective(
@@ -3332,9 +3368,32 @@
VisitOMPLoopDirective(D);
}
+void EnqueueVisitor::VisitAnnotateAttr(const AnnotateAttr *A) {
+ EnqueueChildren(A);
+}
+
+void EnqueueVisitor::VisitAnnotateTypeAttr(const AnnotateTypeAttr *A) {
+ EnqueueChildren(A);
+}
+
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU, RegionOfInterest))
- .Visit(S);
+ .ConstStmtVisitor::Visit(S);
+}
+
+void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Attr *A) {
+ // Parent is the attribute itself when this is indirectly called from
+ // VisitChildren. Because we need to make a CXCursor for A, we need *its*
+ // parent.
+ auto AttrCursor = Parent;
+
+ // Get the attribute's parent as stored in
+ // cxcursor::MakeCXCursor(const Attr *A, const Decl *Parent, CXTranslationUnit
+ // TU)
+ const Decl *AttrParent = static_cast<const Decl *>(AttrCursor.data[1]);
+
+ EnqueueVisitor(WL, MakeCXCursor(A, AttrParent, TU))
+ .ConstAttrVisitor::Visit(A);
}
bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
@@ -3599,6 +3658,22 @@
return result;
}
+bool CursorVisitor::Visit(const Attr *A) {
+ VisitorWorkList *WL = nullptr;
+ if (!WorkListFreeList.empty()) {
+ WL = WorkListFreeList.back();
+ WL->clear();
+ WorkListFreeList.pop_back();
+ } else {
+ WL = new VisitorWorkList();
+ WorkListCache.push_back(WL);
+ }
+ EnqueueWorkList(*WL, A);
+ bool result = RunVisitorWorkList(*WL);
+ WorkListFreeList.push_back(WL);
+ return result;
+}
+
namespace {
typedef SmallVector<SourceRange, 4> RefNamePieces;
RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -731,6 +731,8 @@
- Added ``CXBinaryOperatorKind`` and ``CXUnaryOperatorKind``.
(`#29138 <https://github.com/llvm/llvm-project/issues/29138>`_)
+- Exposed arguments of ``clang::annotate`` and ``clang::annotate_type``.
+
Static Analyzer
---------------
- Fix incorrect alignment attribute on the this parameter of certain
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits