30AST_MATCHER_P2(Stmt, argumentOf,
bool, AllowPartialMove, StatementMatcher,
33 return stmt(anyOf(Ref, hasDescendant(Ref))).matches(Node, Finder, Builder);
39 auto ToParam = hasAnyParameter(parmVarDecl(equalsBoundNode(
"param")));
41 const StatementMatcher MoveCallMatcher =
44 anyOf(callee(functionDecl(hasName(MoveFunction))),
45 callee(unresolvedLookupExpr(hasAnyDeclaration(
46 namedDecl(hasUnderlyingDecl(hasName(MoveFunction))))))),
50 declRefExpr(to(equalsBoundNode(
"param"))).bind(
"ref"))),
52 lambdaExpr(valueCapturesVar(equalsBoundNode(
"param"))))),
53 unless(anyOf(hasAncestor(typeLoc()),
54 hasAncestor(expr(hasUnevaluatedContext())))))
59 const StatementMatcher ImplicitMoveReturnMatcher = traverse(
60 TK_IgnoreUnlessSpelledInSource,
61 returnStmt(hasReturnValue(ignoringParens(
62 declRefExpr(to(equalsBoundNode(
"param"))).bind(
"ref"))))
63 .bind(
"implicit-move-return"));
65 const StatementMatcher UsageMatcher = stmt(
66 anyOf(MoveCallMatcher, AllowImplicitMove ? ImplicitMoveReturnMatcher
67 : stmt(unless(anything()))));
71 hasType(type(rValueReferenceType())), parmVarDecl().bind(
"param"),
72 unless(hasType(references(qualType(
73 anyOf(isConstQualified(), substTemplateTypeParmType()))))),
74 optionally(hasType(qualType(references(templateTypeParmType(
75 hasDeclaration(templateTypeParmDecl().bind(
"template-type"))))))),
78 isDefinition(), unless(isDeleted()), unless(isDefaulted()),
80 unless(cxxConstructorDecl(isMoveConstructor())),
81 unless(cxxMethodDecl(isMoveAssignmentOperator())), ToParam,
82 anyOf(cxxConstructorDecl(
83 optionally(hasDescendant(UsageMatcher))),
85 unless(cxxConstructorDecl()),
86 optionally(hasBody(hasDescendant(UsageMatcher))))))
92 const MatchFinder::MatchResult &Result) {
93 const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>(
"param");
94 const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
95 const auto *TemplateType =
96 Result.Nodes.getNodeAs<TemplateTypeParmDecl>(
"template-type");
98 if (!Param || !Function)
101 if (IgnoreUnnamedParams && Param->getName().empty())
104 if (!Param->isUsed() && Param->hasAttr<UnusedAttr>())
107 if (IgnoreNonDeducedTemplateTypes && TemplateType)
111 if (
const FunctionTemplateDecl *FuncTemplate =
112 Function->getDescribedFunctionTemplate()) {
113 const TemplateParameterList *Params =
114 FuncTemplate->getTemplateParameters();
115 if (llvm::is_contained(*Params, TemplateType)) {
122 const auto *MoveCall = Result.Nodes.getNodeAs<CallExpr>(
"move-call");
123 const auto *ImplicitMoveReturn =
124 Result.Nodes.getNodeAs<ReturnStmt>(
"implicit-move-return");
125 if (MoveCall || ImplicitMoveReturn)
128 diag(Param->getLocation(),
129 "rvalue reference parameter %0 is never moved from "
130 "inside the function body")
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.