Make test more lenient for custom clang version strings
[llvm-project.git] / clang-tools-extra / clang-tidy / performance / NoAutomaticMoveCheck.cpp
blob7022e9d784fa74106da2c989d6d0a744d32495f1
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 //===----------------------------------------------------------------------===//
9 #include "NoAutomaticMoveCheck.h"
10 #include "../utils/Matchers.h"
11 #include "../utils/OptionsUtils.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 using namespace clang::ast_matchers;
17 namespace clang::tidy::performance {
19 namespace {
21 AST_MATCHER(VarDecl, isNRVOVariable) { return Node.isNRVOVariable(); }
23 } // namespace
25 NoAutomaticMoveCheck::NoAutomaticMoveCheck(StringRef Name,
26 ClangTidyContext *Context)
27 : ClangTidyCheck(Name, Context),
28 AllowedTypes(
29 utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
31 void 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");
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")))))))))));
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())))));
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);
71 void 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();
78 void NoAutomaticMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
79 Options.store(Opts, "AllowedTypes",
80 utils::options::serializeStringList(AllowedTypes));
83 } // namespace clang::tidy::performance