@@ -330,7 +330,8 @@ void UseAfterMoveFinder::getReinits(
330
330
traverse (TK_AsIs, DeclRefMatcher),
331
331
unless (parmVarDecl (hasType (
332
332
references (qualType (isConstQualified ())))))),
333
- unless (callee (functionDecl (hasName (" ::std::move" )))))))
333
+ unless (callee (functionDecl (
334
+ hasAnyName (" ::std::move" , " ::std::forward" )))))))
334
335
.bind (" reinit" );
335
336
336
337
Stmts->clear ();
@@ -359,24 +360,52 @@ void UseAfterMoveFinder::getReinits(
359
360
}
360
361
}
361
362
363
+ enum class MoveType {
364
+ Move, // std::move
365
+ Forward, // std::forward
366
+ };
367
+
368
+ static MoveType determineMoveType (const FunctionDecl *FuncDecl) {
369
+ if (FuncDecl->getName () == " move" )
370
+ return MoveType::Move;
371
+ if (FuncDecl->getName () == " forward" )
372
+ return MoveType::Forward;
373
+
374
+ assert (false && " Invalid move type" );
375
+ }
376
+
362
377
static void emitDiagnostic (const Expr *MovingCall, const DeclRefExpr *MoveArg,
363
378
const UseAfterMove &Use, ClangTidyCheck *Check,
364
- ASTContext *Context) {
379
+ ASTContext *Context, MoveType Type ) {
365
380
SourceLocation UseLoc = Use.DeclRef ->getExprLoc ();
366
381
SourceLocation MoveLoc = MovingCall->getExprLoc ();
367
382
368
- Check->diag (UseLoc, " '%0' used after it was moved" )
369
- << MoveArg->getDecl ()->getName ();
370
- Check->diag (MoveLoc, " move occurred here" , DiagnosticIDs::Note);
383
+ StringRef ActionType;
384
+ StringRef ActionTypePastTense;
385
+ switch (Type) {
386
+ case MoveType::Move:
387
+ ActionType = " move" ;
388
+ ActionTypePastTense = " moved" ;
389
+ break ;
390
+ case MoveType::Forward:
391
+ ActionType = " forward" ;
392
+ ActionTypePastTense = " forwarded" ;
393
+ break ;
394
+ }
395
+
396
+ Check->diag (UseLoc, " '%0' used after it was %1" )
397
+ << MoveArg->getDecl ()->getName () << ActionTypePastTense;
398
+ Check->diag (MoveLoc, " %0 occurred here" , DiagnosticIDs::Note) << ActionType;
371
399
if (Use.EvaluationOrderUndefined ) {
372
400
Check->diag (UseLoc,
373
- " the use and move are unsequenced, i.e. there is no guarantee "
401
+ " the use and %0 are unsequenced, i.e. there is no guarantee "
374
402
" about the order in which they are evaluated" ,
375
- DiagnosticIDs::Note);
403
+ DiagnosticIDs::Note)
404
+ << ActionType;
376
405
} else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) {
377
- Check->diag (UseLoc,
378
- " the use happens in a later loop iteration than the move " ,
379
- DiagnosticIDs::Note) ;
406
+ Check->diag (UseLoc, " the use happens in a later loop iteration than the %0 " ,
407
+ DiagnosticIDs::Note)
408
+ << ActionType ;
380
409
}
381
410
}
382
411
@@ -388,7 +417,9 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
388
417
auto TryEmplaceMatcher =
389
418
cxxMemberCallExpr (callee (cxxMethodDecl (hasName (" try_emplace" ))));
390
419
auto CallMoveMatcher =
391
- callExpr (argumentCountIs (1 ), callee (functionDecl (hasName (" ::std::move" ))),
420
+ callExpr (argumentCountIs (1 ),
421
+ callee (functionDecl (hasAnyName (" ::std::move" , " ::std::forward" ))
422
+ .bind (" move-decl" )),
392
423
hasArgument (0 , declRefExpr ().bind (" arg" )),
393
424
unless (inDecltypeOrTemplateArg ()),
394
425
unless (hasParent (TryEmplaceMatcher)), expr ().bind (" call-move" ),
@@ -436,6 +467,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
436
467
const auto *CallMove = Result.Nodes .getNodeAs <CallExpr>(" call-move" );
437
468
const auto *MovingCall = Result.Nodes .getNodeAs <Expr>(" moving-call" );
438
469
const auto *Arg = Result.Nodes .getNodeAs <DeclRefExpr>(" arg" );
470
+ const auto *MoveDecl = Result.Nodes .getNodeAs <FunctionDecl>(" move-decl" );
439
471
440
472
if (!MovingCall || !MovingCall->getExprLoc ().isValid ())
441
473
MovingCall = CallMove;
@@ -470,7 +502,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
470
502
UseAfterMoveFinder Finder (Result.Context );
471
503
UseAfterMove Use;
472
504
if (Finder.find (CodeBlock, MovingCall, Arg->getDecl (), &Use))
473
- emitDiagnostic (MovingCall, Arg, Use, this , Result.Context );
505
+ emitDiagnostic (MovingCall, Arg, Use, this , Result.Context ,
506
+ determineMoveType (MoveDecl));
474
507
}
475
508
}
476
509
0 commit comments