clang-tools 19.0.0git
NoAutomaticMoveCheck.cpp
Go to the documentation of this file.
1//===--- NoAutomaticMoveCheck.cpp - clang-tidy ----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "../utils/Matchers.h"
11#include "../utils/OptionsUtils.h"
12#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14
15using namespace clang::ast_matchers;
16
18
19namespace {
20
21AST_MATCHER(VarDecl, isNRVOVariable) { return Node.isNRVOVariable(); }
22
23} // namespace
24
26 ClangTidyContext *Context)
27 : ClangTidyCheck(Name, Context),
28 AllowedTypes(
29 utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
30
31void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) {
32 const auto NonNrvoConstLocalVariable =
33 varDecl(hasLocalStorage(), unless(hasType(lValueReferenceType())),
34 unless(isNRVOVariable()),
35 hasType(qualType(
36 isConstQualified(),
37 hasCanonicalType(matchers::isExpensiveToCopy()),
38 unless(hasDeclaration(namedDecl(
39 matchers::matchesAnyListedName(AllowedTypes)))))))
40 .bind("vardecl");
41
42 // A matcher for a `DstT::DstT(const Src&)` where DstT also has a
43 // `DstT::DstT(Src&&)`.
44 const auto LValueRefCtor = cxxConstructorDecl(
45 hasParameter(0,
46 hasType(lValueReferenceType(pointee(type().bind("SrcT"))))),
47 ofClass(cxxRecordDecl(hasMethod(cxxConstructorDecl(
48 hasParameter(0, hasType(rValueReferenceType(
49 pointee(type(equalsBoundNode("SrcT")))))))))));
50
51 // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
52 // instantiation of `template <typename U> DstT::DstT(U&&)`.
53 const auto ConstRefRefCtor = cxxConstructorDecl(
54 parameterCountIs(1),
55 hasParameter(0,
56 hasType(rValueReferenceType(pointee(isConstQualified())))));
57
58 Finder->addMatcher(
59 traverse(
60 TK_AsIs,
61 returnStmt(hasReturnValue(
62 ignoringElidableConstructorCall(ignoringParenImpCasts(
63 cxxConstructExpr(
64 hasDeclaration(anyOf(LValueRefCtor, ConstRefRefCtor)),
65 hasArgument(0, ignoringParenImpCasts(declRefExpr(
66 to(NonNrvoConstLocalVariable)))))
67 .bind("ctor_call")))))),
68 this);
69}
70
71void NoAutomaticMoveCheck::check(const MatchFinder::MatchResult &Result) {
72 const auto *Var = Result.Nodes.getNodeAs<VarDecl>("vardecl");
73 const auto *CtorCall = Result.Nodes.getNodeAs<Expr>("ctor_call");
74 diag(CtorCall->getExprLoc(), "constness of '%0' prevents automatic move")
75 << Var->getName();
76}
77
79 Options.store(Opts, "AllowedTypes",
81}
82
83} // namespace clang::tidy::performance
llvm::SmallString< 256U > Name
::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.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
NoAutomaticMoveCheck(StringRef Name, ClangTidyContext *Context)
AST_MATCHER(Decl, declHasNoReturnAttr)
matches a Decl if it has a "no return" attribute of any kind
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap