summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc/MoveConstantArgumentCheck.cpp
blob: d8e817523b808027edcf08bd2add35020a106910 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//===--- MoveConstandArgumentCheck.cpp - clang-tidy -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MoveConstantArgumentCheck.h"

#include <clang/Lex/Lexer.h>

namespace clang {
namespace tidy {
namespace misc {

using namespace ast_matchers;

void MoveConstantArgumentCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;
  Finder->addMatcher(callExpr(callee(functionDecl(hasName("::std::move"))),
                              argumentCountIs(1),
                              unless(isInTemplateInstantiation()))
                         .bind("call-move"),
                     this);
}

void MoveConstantArgumentCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
  const Expr *Arg = CallMove->getArg(0);
  SourceManager &SM = Result.Context->getSourceManager();

  bool IsConstArg = Arg->getType().isConstQualified();
  bool IsTriviallyCopyable =
      Arg->getType().isTriviallyCopyableType(*Result.Context);

  if (IsConstArg || IsTriviallyCopyable) {
    auto MoveRange = CharSourceRange::getCharRange(CallMove->getSourceRange());
    auto FileMoveRange = Lexer::makeFileCharRange(MoveRange, SM, getLangOpts());
    if (!FileMoveRange.isValid())
      return;
    bool IsVariable = isa<DeclRefExpr>(Arg);
    auto Diag = diag(FileMoveRange.getBegin(),
                     "std::move of the %select{|const }0"
                     "%select{expression|variable}1 "
                     "%select{|of a trivially-copyable type }2"
                     "has no effect; remove std::move()")
                << IsConstArg << IsVariable << IsTriviallyCopyable;

    auto BeforeArgumentsRange = Lexer::makeFileCharRange(
        CharSourceRange::getCharRange(CallMove->getLocStart(),
                                      Arg->getLocStart()),
        SM, getLangOpts());
    auto AfterArgumentsRange = Lexer::makeFileCharRange(
        CharSourceRange::getCharRange(
            CallMove->getLocEnd(), CallMove->getLocEnd().getLocWithOffset(1)),
        SM, getLangOpts());

    if (BeforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) {
      Diag << FixItHint::CreateRemoval(BeforeArgumentsRange)
           << FixItHint::CreateRemoval(AfterArgumentsRange);
    }
  }
}

} // namespace misc
} // namespace tidy
} // namespace clang
OpenPOWER on IntegriCloud