10 #include "../utils/FixItHintUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Lex/Preprocessor.h"
15 #include "clang/Tooling/FixIt.h"
23 ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef
Name,
26 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
27 utils::IncludeSorter::IS_LLVM)) {}
30 const auto Begin = hasArgument(0, expr());
31 const auto End = hasArgument(1, expr());
32 const auto RandomFunc = hasArgument(2, expr().bind(
"randomFunc"));
35 ast_type_traits::TK_AsIs,
37 anyOf(allOf(Begin, End, argumentCountIs(2)),
38 allOf(Begin, End, RandomFunc, argumentCountIs(3))),
39 hasDeclaration(functionDecl(hasName(
"::std::random_shuffle"))),
40 has(implicitCastExpr(has(declRefExpr().bind(
"name")))))
46 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
47 IncludeInserter = std::make_unique<utils::IncludeInserter>(SM,
getLangOpts(),
49 PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks());
58 const auto *MatchedDecl = Result.Nodes.getNodeAs<DeclRefExpr>(
"name");
59 const auto *MatchedArgumentThree = Result.Nodes.getNodeAs<Expr>(
"randomFunc");
60 const auto *MatchedCallExpr = Result.Nodes.getNodeAs<CallExpr>(
"match");
62 if (MatchedCallExpr->getBeginLoc().isMacroID())
66 if (MatchedCallExpr->getNumArgs() == 3) {
68 diag(MatchedCallExpr->getBeginLoc(),
69 "'std::random_shuffle' has been removed in C++17; use "
70 "'std::shuffle' and an alternative random mechanism instead");
71 DiagL << FixItHint::CreateReplacement(
72 MatchedArgumentThree->getSourceRange(),
73 "std::mt19937(std::random_device()())");
76 auto DiagL =
diag(MatchedCallExpr->getBeginLoc(),
77 "'std::random_shuffle' has been removed in C++17; use "
78 "'std::shuffle' instead");
79 DiagL << FixItHint::CreateInsertion(
80 MatchedCallExpr->getRParenLoc(),
81 ", std::mt19937(std::random_device()())");
86 std::string NewName =
"shuffle";
87 StringRef ContainerText = Lexer::getSourceText(
88 CharSourceRange::getTokenRange(MatchedDecl->getSourceRange()),
90 if (ContainerText.startswith(
"std::"))
91 NewName =
"std::" + NewName;
93 Diag << FixItHint::CreateRemoval(MatchedDecl->getSourceRange());
94 Diag << FixItHint::CreateInsertion(MatchedDecl->getBeginLoc(), NewName);
95 Diag << IncludeInserter->CreateIncludeInsertion(
96 Result.Context->getSourceManager().getFileID(
97 MatchedCallExpr->getBeginLoc()),