blob: 172dc4ff24f9171adf55b4e2a633040506287dc4 [file] [log] [blame]
Alexander Kornienkoe4ac60d2015-11-25 15:56:11 +00001//===--- MoveConstandArgumentCheck.cpp - clang-tidy -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MoveConstantArgumentCheck.h"
11
12#include <clang/Lex/Lexer.h>
13
14namespace clang {
15namespace tidy {
16namespace misc {
17
18using namespace ast_matchers;
19
20void MoveConstantArgumentCheck::registerMatchers(MatchFinder *Finder) {
21 if (!getLangOpts().CPlusPlus)
22 return;
23 Finder->addMatcher(callExpr(unless(isInTemplateInstantiation()),
24 callee(functionDecl(hasName("::std::move"))))
25 .bind("call-move"),
26 this);
27}
28
29void MoveConstantArgumentCheck::check(const MatchFinder::MatchResult &Result) {
30 const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
31 if (CallMove->getNumArgs() != 1)
32 return;
33 const Expr *Arg = CallMove->getArg(0);
34 SourceManager &SM = Result.Context->getSourceManager();
35
36 bool IsConstArg = Arg->getType().isConstQualified();
37 bool IsTriviallyCopyable =
38 Arg->getType().isTriviallyCopyableType(*Result.Context);
39
40 if (IsConstArg || IsTriviallyCopyable) {
41 auto MoveRange = CharSourceRange::getCharRange(CallMove->getSourceRange());
42 auto FileMoveRange = Lexer::makeFileCharRange(MoveRange, SM, getLangOpts());
43 if (!FileMoveRange.isValid())
44 return;
45 bool IsVariable = isa<DeclRefExpr>(Arg);
46 auto Diag =
47 diag(FileMoveRange.getBegin(), "std::move of the %select{|const }0"
48 "%select{expression|variable}1 "
49 "%select{|of trivially-copyable type }2"
50 "has no effect; remove std::move()")
51 << IsConstArg << IsVariable << IsTriviallyCopyable;
52
53 auto BeforeArgumentsRange = Lexer::makeFileCharRange(
54 CharSourceRange::getCharRange(CallMove->getLocStart(),
55 Arg->getLocStart()),
56 SM, getLangOpts());
57 auto AfterArgumentsRange = Lexer::makeFileCharRange(
58 CharSourceRange::getCharRange(
59 CallMove->getLocEnd(), CallMove->getLocEnd().getLocWithOffset(1)),
60 SM, getLangOpts());
61
62 if (BeforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) {
63 DB << FixItHint::CreateRemoval(BeforeArgumentsRange)
64 << FixItHint::CreateRemoval(AfterArgumentsRange);
65 }
66 }
67}
68
69} // namespace misc
70} // namespace tidy
71} // namespace clang