ajohnson-uoregon updated this revision to Diff 413693. ajohnson-uoregon added a comment.
Actually has the right doc updates now Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120949/new/ https://reviews.llvm.org/D120949 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2509,6 +2509,28 @@ EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr)); } +TEST(ASTMatchersTest, AttributedStmtBasic) { + StringRef Code = "int foo() { [[likely]] return 1; }"; + EXPECT_TRUE(matchesConditionally(Code, attributedStmt(), + true, {"-std=c++20"})); +} + +TEST(ASTMatchersTest, AttributedStmt_isAttr) { + StringRef Code = "int foo() { [[unlikely]] return 1; }"; + EXPECT_TRUE(matchesConditionally(Code, attributedStmt(isAttr(attr::Unlikely)), + true, {"-std=c++20"})); + EXPECT_FALSE(matchesConditionally(Code, attributedStmt(isAttr(attr::Builtin)), + true, {"-std=c++20"})); +} + +TEST(ASTMatchersTest, AttributedStmt_hasSubStmt) { + StringRef Code = "int foo() { [[likely]] return 1; }"; + EXPECT_TRUE(matchesConditionally(Code, + attributedStmt(hasSubStmt(returnStmt())), true, {"-std=c++20"})); + EXPECT_FALSE(matchesConditionally(Code, + attributedStmt(hasSubStmt(ifStmt())), true, {"-std=c++20"})); +} + TEST(MatchFinderAPI, MatchesDynamic) { StringRef SourceCode = "struct A { void f() {} };"; auto Matcher = functionDecl(isDefinition()).bind("method"); Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -142,6 +142,7 @@ REGISTER_MATCHER(atomicExpr); REGISTER_MATCHER(atomicType); REGISTER_MATCHER(attr); + REGISTER_MATCHER(attributedStmt); REGISTER_MATCHER(autoType); REGISTER_MATCHER(autoreleasePoolStmt) REGISTER_MATCHER(binaryConditionalOperator); @@ -355,6 +356,7 @@ REGISTER_MATCHER(hasSpecializedTemplate); REGISTER_MATCHER(hasStaticStorageDuration); REGISTER_MATCHER(hasStructuredBlock); + REGISTER_MATCHER(hasSubStmt); REGISTER_MATCHER(hasSyntacticForm); REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); @@ -395,6 +397,7 @@ REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isAssignmentOperator); REGISTER_MATCHER(isAtPosition); + REGISTER_MATCHER(isAttr); REGISTER_MATCHER(isBaseInitializer); REGISTER_MATCHER(isBitField); REGISTER_MATCHER(isCatchAll); Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -981,6 +981,8 @@ predefinedExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr> designatedInitExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, AttributedStmt> + attributedStmt; const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits<unsigned>::max()> eachOf = {internal::DynTypedMatcher::VO_EachOf}; Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2699,6 +2699,61 @@ return Node.size() == N; } +/// Matches the attribute(s) attached to a Stmt +/// +/// Given: +/// \code +/// constexpr double pow(double x, long long n) noexcept { +/// if (n > 0) [[likely]] +/// return x * pow(x, n - 1); +/// else [[unlikely]] +/// return 1; +/// } +/// \endcode +/// attributedStmt() matches "[[likely]] return ...;" and +/// "[[unlikely]] return 1;" +extern const internal::VariadicDynCastAllOfMatcher<Stmt, AttributedStmt> + attributedStmt; + +/// Matches the specified attribute. +/// +/// Example: +/// \code +/// attributedStmt(isAttr(attr::Likely)) +/// \endcode +/// would only match "[[likely]] return ...;" here: +/// \code +/// constexpr double pow(double x, long long n) noexcept { +/// if (n > 0) [[likely]] +/// return x * pow(x, n - 1); +/// else [[unlikely]] +/// return 1; +/// } +/// \endcode +AST_MATCHER_P(AttributedStmt, isAttr, attr::Kind, AttrKind) { + return llvm::any_of(Node.getAttrs(), [&](const Attr *A) { + return A->getKind() == AttrKind; + }); +} + +/// Matches the statement an attribute is attached to. +/// +/// Example: +/// \code +/// attributedStmt(hasSubStmt(returnStmt())) +/// \endcode +/// would match "return 1;" here: +/// \code +/// else [[unlikely]] +/// return 1; +/// \endcode +AST_MATCHER_P(AttributedStmt, hasSubStmt, internal::Matcher<Stmt>, + InnerMatcher) { + const Stmt *Statement = Node.getSubStmt(); + return Statement != nullptr && + InnerMatcher.matches(*Statement, Finder, Builder); +} + /// Matches \c QualTypes in the clang AST. extern const internal::VariadicAllOfMatcher<QualType> qualType; @@ -3911,6 +3966,44 @@ return false; } +/// Matches the type of a return statement as declared by the enclosing +/// function. +/// +/// Example: returnStmt(hasExpectedReturnType(asString("int *"))) will match +/// return 0; in +/// \code +/// int* foo() { +/// return 0; +/// } +/// \endcode +/// despite the return value being an IntegerLiteral. + +AST_MATCHER_P(ReturnStmt, hasExpectedReturnType, internal::Matcher<QualType>, + InnerMatcher) { + const auto &Parents = Finder->getASTContext().getParents(Node); + + llvm::SmallVector<DynTypedNode, 8> Stack(Parents.begin(), Parents.end()); + const FunctionDecl* FuncDeclNode; + while (!Stack.empty()) { + const auto &CurNode = Stack.back(); + Stack.pop_back(); + FuncDeclNode = CurNode.get<FunctionDecl>(); + if (FuncDeclNode != nullptr) { + break; + } + else { + for (const auto &Parent : Finder->getASTContext().getParents(CurNode)) + Stack.push_back(Parent); + } + } + if (FuncDeclNode == nullptr) { + return false; + } + else { + return InnerMatcher.matches(FuncDeclNode->getReturnType(), Finder, Builder); + } +} + /// Matches if the type location of a node matches the inner matcher. /// /// Examples: @@ -4386,6 +4479,29 @@ return NumArgs == N; } +/// Checks that a call expression or a constructor call expression has +/// a specific number of arguments (EXCLUDING absent default arguments). +/// +/// Example matches f(0, 0) but not f(0) (matcher = callExpr(argumentsGivenCountIs(2))) +/// \code +/// void f(int x, int y = 0); +/// f(0, 0); +/// f(0); +/// \endcode +AST_POLYMORPHIC_MATCHER_P(argumentsGivenCountIs, + AST_POLYMORPHIC_SUPPORTED_TYPES( + CallExpr, CXXConstructExpr, + CXXUnresolvedConstructExpr, ObjCMessageExpr), + unsigned, N) { + unsigned NumArgs = Node.getNumArgs(); + while (NumArgs) { + if (!isa<CXXDefaultArgExpr>(Node.getArg(NumArgs - 1))) + break; + --NumArgs; + } + return NumArgs == N; +} + /// Matches the n'th argument of a call expression or a constructor /// call expression. /// @@ -7794,6 +7910,80 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> cudaKernelCallExpr; +/// Matches the config in <<<>>> on CUDA kernel calls. +/// +/// Example: will match <<<i,j>>> in +/// \code +/// kernel<<<i,j>>>(); +/// \endcode +AST_MATCHER_P(CUDAKernelCallExpr, hasKernelConfig, internal::Matcher<CallExpr>, + InnerMatcher) { + if (const CallExpr *Config = Node.getConfig()) { + return InnerMatcher.matches(*Config, Finder, Builder); + } + return false; +} + +/// Matches the first argument (grid dim) in <<<>>> on CUDA kernel calls. +/// +/// Example: will match i in +/// \code +/// kernel<<<i,j>>>(); +/// \endcode +AST_MATCHER_P(CUDAKernelCallExpr, cudaGridDim, internal::Matcher<Expr>, + InnerMatcher) { + const CallExpr *Config = Node.getConfig(); + if (Config && Config->getNumArgs() > 0) { + return InnerMatcher.matches(*(Config->getArg(0)), Finder, Builder); + } + return false; +} + +/// Matches the second argument (block dim) in <<<>>> on CUDA kernel calls. +/// +/// Example: will match j in +/// \code +/// kernel<<<i,j>>>(); +/// \endcode +AST_MATCHER_P(CUDAKernelCallExpr, cudaBlockDim, internal::Matcher<Expr>, + InnerMatcher) { + const CallExpr *Config = Node.getConfig(); + if (Config && Config->getNumArgs() > 1) { + return InnerMatcher.matches(*(Config->getArg(1)), Finder, Builder); + } + return false; +} + +/// Matches the third argument (shared mem size) in <<<>>> on CUDA kernel calls. +/// +/// Example: will match mem in +/// \code +/// kernel<<<i, j, mem, 0>>>(); +/// \endcode +AST_MATCHER_P(CUDAKernelCallExpr, cudaSharedMemPerBlock, internal::Matcher<Expr>, + InnerMatcher) { + const CallExpr *Config = Node.getConfig(); + if (Config && Config->getNumArgs() > 2) { + return InnerMatcher.matches(*(Config->getArg(2)), Finder, Builder); + } + return false; +} + +/// Matches the fourth argument (CUDA stream) in <<<>>> on CUDA kernel calls. +/// +/// Example: will match 0 in +/// \code +/// kernel<<<i, j, mem, 0>>>(); +/// \endcode +AST_MATCHER_P(CUDAKernelCallExpr, cudaStream, internal::Matcher<Expr>, + InnerMatcher) { + const CallExpr *Config = Node.getConfig(); + if (Config && Config->getNumArgs() > 3) { + return InnerMatcher.matches(*(Config->getArg(3)), Finder, Builder); + } + return false; +} + /// Matches expressions that resolve to a null pointer constant, such as /// GNU's __null, C++11's nullptr, or C's NULL macro. /// Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -1283,6 +1283,21 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('attributedStmt0')"><a name="attributedStmt0Anchor">attributedStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="attributedStmt0"><pre>Matches the attribute(s) attached to a Stmt + +Given: + constexpr double pow(double x, long long n) noexcept { + if (n > 0) [[likely]] + return x * pow(x, n - 1); + else [[unlikely]] + return 1; + } +attributedStmt() matches "[[likely]] return ...;" and +"[[unlikely]] return 1;" +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('autoreleasePoolStmt0')"><a name="autoreleasePoolStmt0Anchor">autoreleasePoolStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAutoreleasePoolStmt.html">ObjCAutoreleasePoolStmt</a>>...</td></tr> <tr><td colspan="4" class="doc" id="autoreleasePoolStmt0"><pre>Matches an Objective-C autorelease pool statement. @@ -2852,6 +2867,21 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>></td><td class="name" onclick="toggle('isAttr0')"><a name="isAttr0Anchor">isAttr</a></td><td>attr::Kind AttrKind</td></tr> +<tr><td colspan="4" class="doc" id="isAttr0"><pre>Matches the specified attribute. + +Example: + attributedStmt(isAttr(attr::Likely)) +would only match "[[likely]] return ...;" here: + constexpr double pow(double x, long long n) noexcept { + if (n > 0) [[likely]] + return x * pow(x, n - 1); + else [[unlikely]] + return 1; + } +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>></td><td class="name" onclick="toggle('isImplicit1')"><a name="isImplicit1Anchor">isImplicit</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isImplicit1"><pre>Matches an entity that has been implicitly added by the compiler (e.g. implicit default/copy constructors). @@ -6214,6 +6244,17 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>></td><td class="name" onclick="toggle('hasSubStmt0')"><a name="hasSubStmt0Anchor">hasSubStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasSubStmt0"><pre>Matches the statement an attribute is attached to. + +Example: + attributedStmt(hasSubStmt(returnStmt())) +would match "return 1;" here: + else [[unlikely]] + return 1; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>></td><td class="name" onclick="toggle('hasDeducedType0')"><a name="hasDeducedType0Anchor">hasDeducedType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr> <tr><td colspan="4" class="doc" id="hasDeducedType0"><pre>Matches AutoType nodes where the deduced type is a specific type. @@ -9799,5 +9840,3 @@ </div> </body> </html> - -
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits