sammccall created this revision. sammccall added a reviewer: hokein. Herald added a project: clang. Herald added a subscriber: cfe-commits. sammccall requested review of this revision.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D89743 Files: clang/include/clang/AST/ASTFwd.h clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/ASTMatchers/ASTMatchFinder.h clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/lib/AST/ASTTypeTraits.cpp clang/lib/ASTMatchers/ASTMatchFinder.cpp clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/unittests/AST/ASTTypeTraitsTest.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1875,6 +1875,15 @@ nestedNameSpecifier())); } +TEST_P(ASTMatchersTest, Attr) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(matches("struct [[nodiscard]] F{};", attr())); + EXPECT_TRUE(matches("int x(int * __attribute__((nonnull)) );", attr())); + EXPECT_TRUE(notMatches("struct F{}; int x(int *);", attr())); +} + TEST_P(ASTMatchersTest, NullStmt) { EXPECT_TRUE(matches("void f() {int i;;}", nullStmt())); EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt())); Index: clang/unittests/AST/ASTTypeTraitsTest.cpp =================================================================== --- clang/unittests/AST/ASTTypeTraitsTest.cpp +++ clang/unittests/AST/ASTTypeTraitsTest.cpp @@ -120,6 +120,7 @@ VERIFY_NAME(CallExpr); VERIFY_NAME(Type); VERIFY_NAME(ConstantArrayType); + VERIFY_NAME(NonNullAttr); #undef VERIFY_NAME } @@ -148,6 +149,13 @@ nestedNameSpecifierLoc())); } +TEST(DynTypedNode, AttrSourceRange) { + RangeVerifier<DynTypedNode> Verifier; + Verifier.expectRange(1, 31, 1, 31); + EXPECT_TRUE(Verifier.match("void x(char *y __attribute__((nonnull)) );", + ast_matchers::attr())); +} + TEST(DynTypedNode, DeclDump) { DumpVerifier Verifier; Verifier.expectSubstring("FunctionDecl"); Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -973,6 +973,7 @@ const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc> nestedNameSpecifierLoc; +const internal::VariadicAllOfMatcher<Attr> attr; const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> cudaKernelCallExpr; const AstTypeMatcher<BuiltinType> builtinType; Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -131,6 +131,8 @@ else if (const TemplateArgumentLoc *TALoc = DynNode.get<TemplateArgumentLoc>()) traverse(*TALoc); + else if (const Attr *A = DynNode.get<Attr>()) + traverse(*A); // FIXME: Add other base types after adding tests. // It's OK to always overwrite the bound nodes, as if there was @@ -231,6 +233,10 @@ ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(TAL); } + bool TraverseAttr(Attr *A) { + ScopedIncrement ScopedDepth(&CurrentDepth); + return (A == nullptr || traverse(*A)); + } bool TraverseLambdaExpr(LambdaExpr *Node) { if (Finder->getASTContext().getParentMapContext().getTraversalKind() != TK_IgnoreUnlessSpelledInSource) @@ -314,6 +320,9 @@ bool baseTraverse(TemplateArgumentLoc TAL) { return VisitorBase::TraverseTemplateArgumentLoc(TAL); } + bool baseTraverse(const Attr &AttrNode) { + return VisitorBase::TraverseAttr(const_cast<Attr *>(&AttrNode)); + } // Sets 'Matched' to true if 'Matcher' matches 'Node' and: // 0 < CurrentDepth <= MaxDepth. @@ -458,6 +467,7 @@ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit); bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL); + bool TraverseAttr(Attr *AttrNode); // Matches children or descendants of 'Node' with 'BaseMatcher'. bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx, @@ -571,6 +581,8 @@ match(*N); } else if (auto *N = Node.get<TemplateArgumentLoc>()) { match(*N); + } else if (auto *N = Node.get<Attr>()) { + match(*N); } } @@ -697,6 +709,9 @@ void matchDispatch(const TemplateArgumentLoc *Node) { matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc); } + void matchDispatch(const Attr *Node) { + matchWithoutFilter(*Node, Matchers->Attr); + } void matchDispatch(const void *) { /* Do nothing. */ } /// @} @@ -1068,6 +1083,11 @@ return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc); } +bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) { + match(*AttrNode); + return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode); +} + class MatchASTConsumer : public ASTConsumer { public: MatchASTConsumer(MatchFinder *Finder, @@ -1150,6 +1170,12 @@ Matchers.AllCallbacks.insert(Action); } +void MatchFinder::addMatcher(const AttrMatcher &AttrMatch, + MatchCallback *Action) { + Matchers.Attr.emplace_back(AttrMatch, Action); + Matchers.AllCallbacks.insert(Action); +} + bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action) { if (NodeMatch.canConvertTo<Decl>()) { @@ -1176,6 +1202,9 @@ } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) { addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action); return true; + } else if (NodeMatch.canConvertTo<Attr>()) { + addMatcher(NodeMatch.convertTo<Attr>(), Action); + return true; } return false; } Index: clang/lib/AST/ASTTypeTraits.cpp =================================================================== --- clang/lib/AST/ASTTypeTraits.cpp +++ clang/lib/AST/ASTTypeTraits.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OpenMPClause.h" @@ -21,28 +22,31 @@ using namespace clang; const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { - { NKI_None, "<None>" }, - { NKI_None, "TemplateArgument" }, - { NKI_None, "TemplateArgumentLoc" }, - { NKI_None, "TemplateName" }, - { NKI_None, "NestedNameSpecifierLoc" }, - { NKI_None, "QualType" }, - { NKI_None, "TypeLoc" }, - { NKI_None, "CXXBaseSpecifier" }, - { NKI_None, "CXXCtorInitializer" }, - { NKI_None, "NestedNameSpecifier" }, - { NKI_None, "Decl" }, + {NKI_None, "<None>"}, + {NKI_None, "TemplateArgument"}, + {NKI_None, "TemplateArgumentLoc"}, + {NKI_None, "TemplateName"}, + {NKI_None, "NestedNameSpecifierLoc"}, + {NKI_None, "QualType"}, + {NKI_None, "TypeLoc"}, + {NKI_None, "CXXBaseSpecifier"}, + {NKI_None, "CXXCtorInitializer"}, + {NKI_None, "NestedNameSpecifier"}, + {NKI_None, "Decl"}, #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, #include "clang/AST/DeclNodes.inc" - { NKI_None, "Stmt" }, + {NKI_None, "Stmt"}, #define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED }, #include "clang/AST/StmtNodes.inc" - { NKI_None, "Type" }, + {NKI_None, "Type"}, #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, #include "clang/AST/TypeNodes.inc" - { NKI_None, "OMPClause" }, + {NKI_None, "OMPClause"}, #define OMP_CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class}, #include "llvm/Frontend/OpenMP/OMPKinds.def" + {NKI_None, "Attr"}, +#define ATTR(A) {NKI_Attr, #A "Attr"}, +#include "clang/Basic/AttrList.inc" }; bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { @@ -123,7 +127,17 @@ break; #include "llvm/Frontend/OpenMP/OMPKinds.def" } - llvm_unreachable("invalid stmt kind"); + llvm_unreachable("invalid omp clause kind"); +} + +ASTNodeKind ASTNodeKind::getFromNode(const Attr &A) { + switch (A.getKind()) { +#define ATTR(A) \ + case attr::A: \ + return ASTNodeKind(NKI_##A##Attr); +#include "clang/Basic/AttrList.inc" + } + llvm_unreachable("invalid attr kind"); } void DynTypedNode::print(llvm::raw_ostream &OS, @@ -151,6 +165,8 @@ S->printPretty(OS, nullptr, PP); else if (const Type *T = get<Type>()) QualType(T, 0).print(OS, PP); + else if (const Attr *A = get<Attr>()) + A->printPretty(OS, PP); else OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; } @@ -182,5 +198,7 @@ return TAL->getSourceRange(); if (const auto *C = get<OMPClause>()) return SourceRange(C->getBeginLoc(), C->getEndLoc()); + if (const auto *A = get<Attr>()) + return A->getRange(); return SourceRange(); } Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -944,7 +944,8 @@ std::is_same<T, NestedNameSpecifier>::value || std::is_same<T, NestedNameSpecifierLoc>::value || std::is_same<T, CXXCtorInitializer>::value || - std::is_same<T, TemplateArgumentLoc>::value; + std::is_same<T, TemplateArgumentLoc>::value || + std::is_same<T, Attr>::value; }; template <typename T> const bool IsBaseType<T>::value; Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -146,6 +146,7 @@ using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>; using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>; using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>; +using AttrMatcher = internal::Matcher<Attr>; /// @} /// Matches any node. @@ -6728,6 +6729,17 @@ return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); } +/// Matches attributes. +/// +/// Given +/// \code +/// struct [[nodiscard]] Foo{}; +/// void bar(int * __attribute__((nonnull)) ); +/// \endcode +/// attr() +/// matches "nodiscard" and "nonnull" +extern const internal::VariadicAllOfMatcher<Attr> attr; + /// Overloads for the \c equalsNode matcher. /// FIXME: Implement for other node types. /// @{ Index: clang/include/clang/ASTMatchers/ASTMatchFinder.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -161,6 +161,7 @@ MatchCallback *Action); void addMatcher(const TemplateArgumentLocMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const AttrMatcher &NodeMatch, MatchCallback *Action); /// @} /// Adds a matcher to execute when running over the AST. @@ -213,6 +214,7 @@ std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>> TemplateArgumentLoc; + std::vector<std::pair<AttrMatcher, MatchCallback *>> Attr; /// All the callbacks in one container to simplify iteration. llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; }; Index: clang/include/clang/AST/ASTTypeTraits.h =================================================================== --- clang/include/clang/AST/ASTTypeTraits.h +++ clang/include/clang/AST/ASTTypeTraits.h @@ -25,10 +25,8 @@ #include "llvm/Support/AlignOf.h" namespace llvm { - class raw_ostream; - -} +} // namespace llvm namespace clang { @@ -70,6 +68,7 @@ static ASTNodeKind getFromNode(const Stmt &S); static ASTNodeKind getFromNode(const Type &T); static ASTNodeKind getFromNode(const OMPClause &C); + static ASTNodeKind getFromNode(const Attr &A); /// \} /// Returns \c true if \c this and \c Other represent the same kind. @@ -153,6 +152,9 @@ NKI_OMPClause, #define OMP_CLAUSE_CLASS(Enum, Str, Class) NKI_##Class, #include "llvm/Frontend/OpenMP/OMPKinds.def" + NKI_Attr, +#define ATTR(A) NKI_##A##Attr, +#include "clang/Basic/AttrList.inc" NKI_NumberOfKinds }; @@ -202,6 +204,7 @@ KIND_TO_KIND_ID(Stmt) KIND_TO_KIND_ID(Type) KIND_TO_KIND_ID(OMPClause) +KIND_TO_KIND_ID(Attr) KIND_TO_KIND_ID(CXXBaseSpecifier) #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) #include "clang/AST/DeclNodes.inc" @@ -211,6 +214,8 @@ #include "clang/AST/TypeNodes.inc" #define OMP_CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class) #include "llvm/Frontend/OpenMP/OMPKinds.def" +#define ATTR(A) KIND_TO_KIND_ID(A##Attr) +#include "clang/Basic/AttrList.inc" #undef KIND_TO_KIND_ID inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { @@ -487,6 +492,11 @@ T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>> : public DynCastPtrConverter<T, OMPClause> {}; +template <typename T> +struct DynTypedNode::BaseConverter< + T, std::enable_if_t<std::is_base_of<Attr, T>::value>> + : public DynCastPtrConverter<T, Attr> {}; + template <> struct DynTypedNode::BaseConverter< NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; Index: clang/include/clang/AST/ASTFwd.h =================================================================== --- clang/include/clang/AST/ASTFwd.h +++ clang/include/clang/AST/ASTFwd.h @@ -29,7 +29,9 @@ class OMPClause; #define OMP_CLAUSE_CLASS(Enum, Str, Class) class Class; #include "llvm/Frontend/OpenMP/OMPKinds.def" - +class Attr; +#define ATTR(A) class A##Attr; +#include "clang/Basic/AttrList.inc" } // end namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits