njames93 created this revision. njames93 added reviewers: klimek, aaron.ballman, steveire. njames93 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Add `deletes` traveral matcher which matches on the expression being delete Extend `CXXNewExpr::isArray` matcher to work for `CXXDeleteExpr`. Currently this only matches array delete expressions as written. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D97681 Files: clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -5466,5 +5466,31 @@ IsPlacementNew)); } +TEST(CXXDeleteExpr, Deletes) { + StatementMatcher IsDeletingPtrVar = cxxDeleteExpr( + deletes(ignoringImpCasts(declRefExpr(to(varDecl(hasName("Ptr"))))))); + + EXPECT_TRUE(matches("void foo(int* Ptr) { delete Ptr; }", IsDeletingPtrVar)); + EXPECT_TRUE(notMatches(R"( + struct Foo{ + int* Address; + }; + void Bar(Foo& Ptr) { + delete Ptr.Address; + } + )", + IsDeletingPtrVar)); + + EXPECT_TRUE(notMatches(R"( + struct Foo{ + int* Ptr; + }; + void Bar(Foo& Ptr) { + delete Ptr.Ptr; + } + )", + IsDeletingPtrVar)); +} + } // namespace ast_matchers } // namespace clang Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -3779,6 +3779,12 @@ EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];", cxxNewExpr(isArray()))); + + EXPECT_TRUE( + matches("void foo(int* p) { delete[] p; }", cxxDeleteExpr(isArray()))); + + EXPECT_TRUE( + notMatches("void foo(int* p) { delete p; }", cxxDeleteExpr(isArray()))); } TEST_P(ASTMatchersTest, HasArraySize) { Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -214,6 +214,7 @@ REGISTER_MATCHER(decltypeType); REGISTER_MATCHER(deducedTemplateSpecializationType); REGISTER_MATCHER(defaultStmt); + REGISTER_MATCHER(deletes); REGISTER_MATCHER(dependentSizedArrayType); REGISTER_MATCHER(designatedInitExpr); REGISTER_MATCHER(designatorCountIs); @@ -266,7 +267,6 @@ REGISTER_MATCHER(hasAnySubstatement); REGISTER_MATCHER(hasAnyTemplateArgument); REGISTER_MATCHER(hasAnyUsingShadowDecl); - REGISTER_MATCHER(hasArgument); REGISTER_MATCHER(hasArgumentOfType); REGISTER_MATCHER(hasArraySize); REGISTER_MATCHER(hasAttr); Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -155,6 +155,14 @@ return Node.getAccessSpecifier(); } +/// Unifies obtaining the whether as new or delete operator operates on an +/// array. +inline bool isArrayOperator(const CXXNewExpr &Node) { return Node.isArray(); } + +inline bool isArrayOperator(const CXXDeleteExpr &Node) { + return Node.isArrayFormAsWritten(); +} + /// Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -7550,16 +7550,21 @@ return Node.hasDefaultArg(); } -/// Matches array new expressions. +/// Matches array new and delete expressions. /// /// Given: /// \code /// MyClass *p1 = new MyClass[10]; +/// delete[] p1; /// \endcode /// cxxNewExpr(isArray()) /// matches the expression 'new MyClass[10]'. -AST_MATCHER(CXXNewExpr, isArray) { - return Node.isArray(); +/// cxxDeleteExpr(isArray()) +/// matches the expression 'delete[] p1'. +AST_POLYMORPHIC_MATCHER(isArray, + AST_POLYMORPHIC_SUPPORTED_TYPES(CXXNewExpr, + CXXDeleteExpr)) { + return isArrayOperator(Node); } /// Matches placement new expression arguments. @@ -7604,6 +7609,20 @@ InnerMatcher.matches(**Node.getArraySize(), Finder, Builder); } +/// Matchers the expression being deleted. +/// +/// Given: +/// \code +/// int *Ptr = nullptr; +/// delete Ptr; +/// \endcode +/// cxxDeleteExpr(deletes(declRefExpr(ignoringImpCasts(to(varDecl(hasName("Ptr"))))))) +/// matches the expression 'delete Ptr'. +AST_MATCHER_P_OVERLOAD(CXXDeleteExpr, deletes, internal::Matcher<Expr>, + InnerMatcher, 1) { + return InnerMatcher.matches(*Node.getArgument(), Finder, Builder); +} + /// Matches a class declaration that is defined. /// /// Example matches x (matcher = cxxRecordDecl(hasDefinition())) Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -3075,6 +3075,19 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDeleteExpr.html">CXXDeleteExpr</a>></td><td class="name" onclick="toggle('isArray1')"><a name="isArray1Anchor">isArray</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isArray1"><pre>Matches array new and delete expressions. + +Given: + MyClass *p1 = new MyClass[10]; + delete[] p1; +cxxNewExpr(isArray()) + matches the expression 'new MyClass[10]'. +cxxDeleteExpr(isArray()) + matches the expression 'delete[] p1'. +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>></td><td class="name" onclick="toggle('hasMemberName0')"><a name="hasMemberName0Anchor">hasMemberName</a></td><td>std::string N</td></tr> <tr><td colspan="4" class="doc" id="hasMemberName0"><pre>Matches template-dependent, but known, member names. @@ -3296,12 +3309,15 @@ <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('isArray0')"><a name="isArray0Anchor">isArray</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isArray0"><pre>Matches array new expressions. +<tr><td colspan="4" class="doc" id="isArray0"><pre>Matches array new and delete expressions. Given: MyClass *p1 = new MyClass[10]; + delete[] p1; cxxNewExpr(isArray()) matches the expression 'new MyClass[10]'. +cxxDeleteExpr(isArray()) + matches the expression 'delete[] p1'. </pre></td></tr> @@ -6303,6 +6319,17 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDeleteExpr.html">CXXDeleteExpr</a>></td><td class="name" onclick="toggle('deletes0')"><a name="deletes0Anchor">deletes</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="deletes0"><pre>Matchers the expression being deleted. + +Given: + int *Ptr = nullptr; + delete Ptr; +cxxDeleteExpr(deletes(declRefExpr(ignoringImpCasts(to(varDecl(hasName("Ptr"))))))) + matches the expression 'delete Ptr'. +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>></td><td class="name" onclick="toggle('hasObjectExpression2')"><a name="hasObjectExpression2Anchor">hasObjectExpression</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasObjectExpression2"><pre>Matches a member expression where the object expression is matched by a given matcher. Implicit object expressions are included; that is, it matches Index: clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp +++ clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp @@ -27,7 +27,7 @@ hasName("std::default_delete"))))))); Finder->addMatcher( - cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr( + cxxDeleteExpr(deletes(ignoringParenImpCasts(cxxMemberCallExpr( on(expr(hasType(UniquePtrWithDefaultDelete), unless(hasType(IsSusbstituted))) .bind("uptr")), Index: clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp +++ clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp @@ -21,11 +21,11 @@ void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) { const auto DeleteExpr = cxxDeleteExpr( - has(declRefExpr(to(decl(equalsBoundNode("deletedPointer")))))) + deletes(declRefExpr(to(decl(equalsBoundNode("deletedPointer")))))) .bind("deleteExpr"); const auto DeleteMemberExpr = - cxxDeleteExpr(has(memberExpr(hasDeclaration( + cxxDeleteExpr(deletes(memberExpr(hasDeclaration( fieldDecl(equalsBoundNode("deletedMemberPointer")))))) .bind("deleteMemberExpr"); Index: clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp +++ clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp @@ -59,9 +59,9 @@ findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(RefMatcher)))), *If, *Result.Context) .empty() || - !match( - findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(RefMatcher))))), - *If, *Result.Context) + !match(findAll(cxxDeleteExpr( + deletes(ignoringParenImpCasts(expr(RefMatcher))))), + *If, *Result.Context) .empty()) return;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits