[clang-tools-extra] [clang-tidy] Add support for lambdas in cppcoreguidelines-owning-memory (PR #77246)
Julian Schmidt via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 11 09:48:38 PST 2024
================
@@ -147,10 +161,51 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) {
// Matching on functions, that return an owner/resource, but don't declare
// their return type as owner.
Finder->addMatcher(
- functionDecl(hasDescendant(returnStmt(hasReturnValue(ConsideredOwner))
- .bind("bad_owner_return")),
- unless(returns(qualType(hasDeclaration(OwnerDecl)))))
- .bind("function_decl"),
+ functionDecl(
+ decl().bind("function_decl"),
+ hasBody(stmt(
+ stmt().bind("body"),
+ hasDescendant(
+ returnStmt(hasReturnValue(ConsideredOwner),
+ // Ignore sub-lambda expressions
+ hasAncestor(stmt(anyOf(equalsBoundNode("body"),
+ lambdaExpr()))
+ .bind("scope")),
+ hasAncestor(stmt(equalsBoundNode("scope"),
+ equalsBoundNode("body"))),
+ // Ignore sub-functions
+ hasAncestor(functionDecl().bind("context")),
+ hasAncestor(functionDecl(
+ equalsBoundNode("context"),
+ equalsBoundNode("function_decl"))))
+ .bind("bad_owner_return")))),
+ returns(qualType(unless(hasDeclaration(OwnerDecl))).bind("result"))),
+ this);
+
+ // Matching on lambdas, that return an owner/resource, but don't declare
+ // their return type as owner.
+ Finder->addMatcher(
+ lambdaExpr(
+ hasAncestor(decl(ScopeDeclaration).bind("scope-decl")),
+ hasLambdaBody(stmt(
+ stmt().bind("body"),
+ hasDescendant(
+ returnStmt(
+ hasReturnValue(ConsideredOwner),
+ // Ignore sub-lambdas
+ hasAncestor(
+ stmt(anyOf(equalsBoundNode("body"), lambdaExpr()))
+ .bind("scope")),
+ hasAncestor(stmt(equalsBoundNode("scope"),
+ equalsBoundNode("body"))),
+ // Ignore sub-functions
+ hasAncestor(decl(ScopeDeclaration).bind("context")),
+ hasAncestor(decl(equalsBoundNode("context"),
+ equalsBoundNode("scope-decl"))))
+ .bind("bad_owner_return")))),
+ hasCallOperator(returns(
+ qualType(unless(hasDeclaration(OwnerDecl))).bind("result"))))
+ .bind("lambda"),
----------------
5chmidti wrote:
While looking at this PR again, I came up with this matcher that makes checking for sub-lambdas/-functions more readable:
```c++
// Matching on functions, that return an owner/resource, but don't declare
// their return type as owner.
Finder->addMatcher(
functionDecl(
decl().bind("function_decl"),
hasBody(stmt(stmt().bind("body"),
hasDescendant(returnStmt(hasReturnValue(ConsideredOwner))
.bind("bad_owner_return")),
unless(hasDescendant(decl(
ScopeDeclaration, hasDescendant(stmt(equalsBoundNode(
"bad_owner_return")))))),
unless(hasDescendant(lambdaExpr(hasDescendant(
stmt(equalsBoundNode("bad_owner_return")))))))),
returns(qualType(unless(hasDeclaration(OwnerDecl))).bind("result"))),
this);
// Matching on lambdas, that return an owner/resource, but don't declare
// their return type as owner.
Finder->addMatcher(
lambdaExpr(
hasLambdaBody(stmt(
stmt().bind("body"),
hasDescendant(returnStmt(hasReturnValue(ConsideredOwner))
.bind("bad_owner_return")),
unless(hasDescendant(decl(
ScopeDeclaration,
hasDescendant(stmt(equalsBoundNode("bad_owner_return")))))),
unless(hasDescendant(lambdaExpr(
hasDescendant(stmt(equalsBoundNode("bad_owner_return")))))))),
hasCallOperator(returns(
qualType(unless(hasDeclaration(OwnerDecl))).bind("result"))))
.bind("lambda"),
this);
```
Note that I used `ScopeDeclaration` in both matchers, while you only used it in the matcher where `lambdaExpr` was the top matcher. I'm not sure if this was intended by you or not.
There is also an opportunity to give these sub-matchers good names and reuse them (either parts of them or whole), e.g.: `ReturnIsPartOfCurrentBody` for both `unless` sub-matchers.
https://github.com/llvm/llvm-project/pull/77246
More information about the cfe-commits
mailing list