11 #include "clang/Lex/Lexer.h" 17 namespace performance {
20 const SourceManager &SM,
21 const LangOptions &LangOpts) {
22 const Expr *Arg = Call->getArg(0);
24 CharSourceRange BeforeArgumentsRange = Lexer::makeFileCharRange(
25 CharSourceRange::getCharRange(Call->getBeginLoc(), Arg->getBeginLoc()),
27 CharSourceRange AfterArgumentsRange = Lexer::makeFileCharRange(
28 CharSourceRange::getCharRange(Call->getEndLoc(),
29 Call->getEndLoc().getLocWithOffset(1)),
32 if (BeforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) {
33 Diag << FixItHint::CreateRemoval(BeforeArgumentsRange)
34 << FixItHint::CreateRemoval(AfterArgumentsRange);
39 Options.store(Opts,
"CheckTriviallyCopyableMove", CheckTriviallyCopyableMove);
42 void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) {
43 if (!getLangOpts().CPlusPlus)
46 auto MoveCallMatcher =
47 callExpr(callee(functionDecl(hasName(
"::std::move"))), argumentCountIs(1),
48 unless(isInTemplateInstantiation()))
51 Finder->addMatcher(MoveCallMatcher,
this);
53 auto ConstParamMatcher = forEachArgumentWithParam(
54 MoveCallMatcher, parmVarDecl(hasType(references(isConstQualified()))));
56 Finder->addMatcher(callExpr(ConstParamMatcher).bind(
"receiving-expr"),
this);
57 Finder->addMatcher(cxxConstructExpr(ConstParamMatcher).bind(
"receiving-expr"),
61 void MoveConstArgCheck::check(
const MatchFinder::MatchResult &
Result) {
62 const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>(
"call-move");
63 const auto *ReceivingExpr = Result.Nodes.getNodeAs<Expr>(
"receiving-expr");
64 const Expr *Arg = CallMove->getArg(0);
65 SourceManager &SM = Result.Context->getSourceManager();
67 CharSourceRange MoveRange =
68 CharSourceRange::getCharRange(CallMove->getSourceRange());
69 CharSourceRange FileMoveRange =
70 Lexer::makeFileCharRange(MoveRange, SM, getLangOpts());
71 if (!FileMoveRange.isValid())
74 bool IsConstArg = Arg->getType().isConstQualified();
75 bool IsTriviallyCopyable =
76 Arg->getType().isTriviallyCopyableType(*Result.Context);
78 if (IsConstArg || IsTriviallyCopyable) {
79 if (
const CXXRecordDecl *R = Arg->getType()->getAsCXXRecordDecl()) {
86 for (
const auto *Ctor : R->ctors()) {
87 if (Ctor->isCopyConstructor() && Ctor->isDeleted())
92 if (!IsConstArg && IsTriviallyCopyable && !CheckTriviallyCopyableMove)
95 bool IsVariable = isa<DeclRefExpr>(Arg);
97 IsVariable ? dyn_cast<DeclRefExpr>(Arg)->getDecl() :
nullptr;
98 auto Diag = diag(FileMoveRange.getBegin(),
99 "std::move of the %select{|const }0" 100 "%select{expression|variable %4}1 " 101 "%select{|of the trivially-copyable type %5 }2" 102 "has no effect; remove std::move()" 103 "%select{| or make the variable non-const}3")
104 << IsConstArg << IsVariable << IsTriviallyCopyable
105 << (IsConstArg && IsVariable && !IsTriviallyCopyable) << Var
109 }
else if (ReceivingExpr) {
110 auto Diag = diag(FileMoveRange.getBegin(),
111 "passing result of std::move() as a const reference " 112 "argument; no move will actually happen");
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result