10#include "../utils/Matchers.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
18using matchers::hasUnevaluatedContext;
21AST_MATCHER_P(LambdaExpr, valueCapturesVar, DeclarationMatcher, VarMatcher) {
22 return std::find_if(
Node.capture_begin(),
Node.capture_end(),
23 [&](
const LambdaCapture &Capture) {
24 return Capture.capturesVariable() &&
25 VarMatcher.matches(*Capture.getCapturedVar(),
27 Capture.getCaptureKind() == LCK_ByCopy;
28 }) !=
Node.capture_end();
30AST_MATCHER_P2(Stmt, argumentOf,
bool, AllowPartialMove, StatementMatcher,
32 if (AllowPartialMove) {
33 return stmt(anyOf(Ref, hasDescendant(Ref))).matches(Node, Finder,
Builder);
35 return Ref.matches(Node, Finder,
Builder);
40 auto ToParam = hasAnyParameter(parmVarDecl(equalsBoundNode(
"param")));
42 StatementMatcher MoveCallMatcher =
45 anyOf(callee(functionDecl(hasName(
"::std::move"))),
46 callee(unresolvedLookupExpr(hasAnyDeclaration(
47 namedDecl(hasUnderlyingDecl(hasName(
"::std::move"))))))),
51 declRefExpr(to(equalsBoundNode(
"param"))).bind(
"ref"))),
53 lambdaExpr(valueCapturesVar(equalsBoundNode(
"param"))))),
54 unless(anyOf(hasAncestor(typeLoc()),
55 hasAncestor(expr(hasUnevaluatedContext())))))
60 hasType(type(rValueReferenceType())), parmVarDecl().bind(
"param"),
61 unless(hasType(references(qualType(
62 anyOf(isConstQualified(), substTemplateTypeParmType()))))),
63 optionally(hasType(qualType(references(templateTypeParmType(
64 hasDeclaration(templateTypeParmDecl().bind(
"template-type"))))))),
67 isDefinition(), unless(isDeleted()), unless(isDefaulted()),
68 unless(cxxConstructorDecl(isMoveConstructor())),
69 unless(cxxMethodDecl(isMoveAssignmentOperator())), ToParam,
70 anyOf(cxxConstructorDecl(
71 optionally(hasDescendant(MoveCallMatcher))),
72 functionDecl(unless(cxxConstructorDecl()),
74 hasDescendant(MoveCallMatcher))))))
80 const MatchFinder::MatchResult &Result) {
81 const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>(
"param");
82 const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
83 const auto *TemplateType =
84 Result.Nodes.getNodeAs<TemplateTypeParmDecl>(
"template-type");
86 if (!Param || !Function)
89 if (IgnoreUnnamedParams && Param->getName().empty())
92 if (!Param->isUsed() && Param->hasAttr<UnusedAttr>())
95 if (IgnoreNonDeducedTemplateTypes && TemplateType)
99 if (
const FunctionTemplateDecl *FuncTemplate =
100 Function->getDescribedFunctionTemplate()) {
101 const TemplateParameterList *Params =
102 FuncTemplate->getTemplateParameters();
103 if (llvm::is_contained(*Params, TemplateType)) {
110 const auto *MoveCall = Result.Nodes.getNodeAs<CallExpr>(
"move-call");
112 diag(Param->getLocation(),
113 "rvalue reference parameter %0 is never moved from "
114 "inside the function body")
122 AllowPartialMove(Options.getLocalOrGlobal(
"AllowPartialMove", false)),
124 Options.getLocalOrGlobal(
"IgnoreUnnamedParams", false)),
125 IgnoreNonDeducedTemplateTypes(
126 Options.getLocalOrGlobal(
"IgnoreNonDeducedTemplateTypes", false)) {}
130 Options.
store(Opts,
"AllowPartialMove", AllowPartialMove);
131 Options.
store(Opts,
"IgnoreUnnamedParams", IgnoreUnnamedParams);
133 IgnoreNonDeducedTemplateTypes);
llvm::SmallString< 256U > Name
CodeCompletionBuilder Builder
::clang::DynTypedNode Node
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
RvalueReferenceParamNotMovedCheck(StringRef Name, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
AST_MATCHER_P(UserDefinedLiteral, hasLiteral, clang::ast_matchers::internal::Matcher< Expr >, InnerMatcher)
llvm::StringMap< ClangTidyValue > OptionMap