27 const auto Begin = hasArgument(0, expr());
28 const auto End = hasArgument(1, expr());
29 const auto RandomFunc = hasArgument(2, expr().bind(
"randomFunc"));
34 anyOf(allOf(Begin, End, argumentCountIs(2)),
35 allOf(Begin, End, RandomFunc, argumentCountIs(3))),
36 hasDeclaration(functionDecl(hasName(
"::std::random_shuffle"))),
37 has(implicitCastExpr(has(declRefExpr().bind(
"name")))))
53 const auto *MatchedDecl = Result.Nodes.getNodeAs<DeclRefExpr>(
"name");
54 const auto *MatchedArgumentThree = Result.Nodes.getNodeAs<Expr>(
"randomFunc");
55 const auto *MatchedCallExpr = Result.Nodes.getNodeAs<CallExpr>(
"match");
57 if (MatchedCallExpr->getBeginLoc().isMacroID())
61 if (MatchedCallExpr->getNumArgs() == 3) {
63 diag(MatchedCallExpr->getBeginLoc(),
64 "'std::random_shuffle' has been removed in C++17; use "
65 "'std::shuffle' and an alternative random mechanism instead");
66 DiagL << FixItHint::CreateReplacement(
67 MatchedArgumentThree->getSourceRange(),
68 "std::mt19937(std::random_device()())");
71 auto DiagL = diag(MatchedCallExpr->getBeginLoc(),
72 "'std::random_shuffle' has been removed in C++17; use "
73 "'std::shuffle' instead");
74 DiagL << FixItHint::CreateInsertion(
75 MatchedCallExpr->getRParenLoc(),
76 ", std::mt19937(std::random_device()())");
80 std::string NewName =
"shuffle";
81 StringRef ContainerText = Lexer::getSourceText(
82 CharSourceRange::getTokenRange(MatchedDecl->getSourceRange()),
83 *Result.SourceManager, getLangOpts());
84 if (ContainerText.starts_with(
"std::"))
85 NewName =
"std::" + NewName;
87 Diag << FixItHint::CreateRemoval(MatchedDecl->getSourceRange());
88 Diag << FixItHint::CreateInsertion(MatchedDecl->getBeginLoc(), NewName);
89 Diag << IncludeInserter.createIncludeInsertion(
90 Result.Context->getSourceManager().getFileID(
91 MatchedCallExpr->getBeginLoc()),
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.