forked from OSchip/llvm-project
[clang-tidy] New check: modernize-replace-random-shuffle.
This check will find occurrences of ``std::random_shuffle`` and replace it with ``std::shuffle``. In C++17 ``std::random_shuffle`` will no longer be available and thus we need to replace it. Example of case that it fixes ``` std::vector<int> v; // First example std::random_shuffle(vec.begin(), vec.end()); ``` Reviewers: hokein, aaron.ballman, alexfh, malcolm.parsons, mclow.lists Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D30158 llvm-svn: 301167
This commit is contained in:
parent
f53865daa4
commit
a301498783
|
@ -13,6 +13,7 @@ add_clang_library(clangTidyModernizeModule
|
|||
RawStringLiteralCheck.cpp
|
||||
RedundantVoidArgCheck.cpp
|
||||
ReplaceAutoPtrCheck.cpp
|
||||
ReplaceRandomShuffleCheck.cpp
|
||||
ReturnBracedInitListCheck.cpp
|
||||
ShrinkToFitCheck.cpp
|
||||
UseAutoCheck.cpp
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "RawStringLiteralCheck.h"
|
||||
#include "RedundantVoidArgCheck.h"
|
||||
#include "ReplaceAutoPtrCheck.h"
|
||||
#include "ReplaceRandomShuffleCheck.h"
|
||||
#include "ReturnBracedInitListCheck.h"
|
||||
#include "ShrinkToFitCheck.h"
|
||||
#include "UseAutoCheck.h"
|
||||
|
@ -54,6 +55,8 @@ public:
|
|||
"modernize-redundant-void-arg");
|
||||
CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
|
||||
"modernize-replace-auto-ptr");
|
||||
CheckFactories.registerCheck<ReplaceRandomShuffleCheck>(
|
||||
"modernize-replace-random-shuffle");
|
||||
CheckFactories.registerCheck<ReturnBracedInitListCheck>(
|
||||
"modernize-return-braced-init-list");
|
||||
CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
//===--- ReplaceRandomShuffleCheck.cpp - clang-tidy------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ReplaceRandomShuffleCheck.h"
|
||||
#include "../utils/FixItHintUtils.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Tooling/FixIt.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace modernize {
|
||||
|
||||
ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name,
|
||||
ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context),
|
||||
IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
|
||||
Options.get("IncludeStyle", "llvm"))) {}
|
||||
|
||||
void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {
|
||||
if (!getLangOpts().CPlusPlus11)
|
||||
return;
|
||||
|
||||
const auto Begin = hasArgument(0, expr());
|
||||
const auto End = hasArgument(1, expr());
|
||||
const auto RandomFunc = hasArgument(2, expr().bind("randomFunc"));
|
||||
Finder->addMatcher(
|
||||
callExpr(anyOf(allOf(Begin, End, argumentCountIs(2)),
|
||||
allOf(Begin, End, RandomFunc, argumentCountIs(3))),
|
||||
hasDeclaration(functionDecl(hasName("::std::random_shuffle"))),
|
||||
has(implicitCastExpr(has(declRefExpr().bind("name")))))
|
||||
.bind("match"),
|
||||
this);
|
||||
}
|
||||
|
||||
void ReplaceRandomShuffleCheck::registerPPCallbacks(
|
||||
CompilerInstance &Compiler) {
|
||||
IncludeInserter = llvm::make_unique<utils::IncludeInserter>(
|
||||
Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
|
||||
Compiler.getPreprocessor().addPPCallbacks(
|
||||
IncludeInserter->CreatePPCallbacks());
|
||||
}
|
||||
|
||||
void ReplaceRandomShuffleCheck::storeOptions(
|
||||
ClangTidyOptions::OptionMap &Opts) {
|
||||
Options.store(Opts, "IncludeStyle",
|
||||
utils::IncludeSorter::toString(IncludeStyle));
|
||||
}
|
||||
|
||||
void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
const auto *MatchedDecl = Result.Nodes.getNodeAs<DeclRefExpr>("name");
|
||||
const auto *MatchedArgumentThree = Result.Nodes.getNodeAs<Expr>("randomFunc");
|
||||
const auto *MatchedCallExpr = Result.Nodes.getNodeAs<CallExpr>("match");
|
||||
|
||||
if (MatchedCallExpr->getLocStart().isMacroID())
|
||||
return;
|
||||
|
||||
auto Diag = [&] {
|
||||
if (MatchedCallExpr->getNumArgs() == 3) {
|
||||
auto DiagL =
|
||||
diag(MatchedCallExpr->getLocStart(),
|
||||
"'std::random_shuffle' has been removed in C++17; use "
|
||||
"'std::shuffle' and an alternative random mechanism instead");
|
||||
DiagL << FixItHint::CreateReplacement(
|
||||
MatchedArgumentThree->getSourceRange(),
|
||||
"std::mt19937(std::random_device()())");
|
||||
return DiagL;
|
||||
} else {
|
||||
auto DiagL = diag(MatchedCallExpr->getLocStart(),
|
||||
"'std::random_shuffle' has been removed in C++17; use "
|
||||
"'std::shuffle' instead");
|
||||
DiagL << FixItHint::CreateInsertion(
|
||||
MatchedCallExpr->getRParenLoc(),
|
||||
", std::mt19937(std::random_device()())");
|
||||
return DiagL;
|
||||
}
|
||||
}();
|
||||
|
||||
std::string NewName = "shuffle";
|
||||
StringRef ContainerText = Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(MatchedDecl->getSourceRange()),
|
||||
*Result.SourceManager, getLangOpts());
|
||||
if (ContainerText.startswith("std::"))
|
||||
NewName = "std::" + NewName;
|
||||
|
||||
Diag << FixItHint::CreateRemoval(MatchedDecl->getSourceRange());
|
||||
Diag << FixItHint::CreateInsertion(MatchedDecl->getLocStart(), NewName);
|
||||
|
||||
if (Optional<FixItHint> IncludeFixit =
|
||||
IncludeInserter->CreateIncludeInsertion(
|
||||
Result.Context->getSourceManager().getFileID(
|
||||
MatchedCallExpr->getLocStart()),
|
||||
"random", /*IsAngled=*/true))
|
||||
Diag << IncludeFixit.getValue();
|
||||
}
|
||||
|
||||
} // namespace modernize
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,42 @@
|
|||
//===--- ReplaceRandomShuffleCheck.h - clang-tidy----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
#include "../utils/IncludeInserter.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace modernize {
|
||||
|
||||
/// std::random_shuffle will be removed as of C++17. This check will find and
|
||||
/// replace all occurrences of std::random_shuffle with std::shuffle.
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-replace-random-shuffle.html
|
||||
class ReplaceRandomShuffleCheck : public ClangTidyCheck {
|
||||
public:
|
||||
ReplaceRandomShuffleCheck(StringRef Name, ClangTidyContext *Context);
|
||||
void registerPPCallbacks(CompilerInstance &Compiler) override;
|
||||
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<utils::IncludeInserter> IncludeInserter;
|
||||
const utils::IncludeSorter::IncludeStyle IncludeStyle;
|
||||
};
|
||||
|
||||
} // namespace modernize
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
|
|
@ -81,6 +81,11 @@ Improvements to clang-tidy
|
|||
Adds checks that implement the `High Integrity C++ Coding Standard <http://www.codingstandard.com/section/index/>`_ and other safety
|
||||
standards. Many checks are aliased to other modules.
|
||||
|
||||
- New `modernize-replace-random-shuffle
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-replace-random-shuffle.html>`_ check
|
||||
|
||||
Finds and fixes usage of ``std::random_shuffle`` as the function has been removed from C++17.
|
||||
|
||||
- New `modernize-return-braced-init-list
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-return-braced-init-list.html>`_ check
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ Clang-Tidy Checks
|
|||
modernize-raw-string-literal
|
||||
modernize-redundant-void-arg
|
||||
modernize-replace-auto-ptr
|
||||
modernize-replace-random-shuffle
|
||||
modernize-return-braced-init-list
|
||||
modernize-shrink-to-fit
|
||||
modernize-use-auto
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
.. title:: clang-tidy - modernize-replace-random-shuffle
|
||||
|
||||
modernize-replace-random-shuffle
|
||||
================================
|
||||
|
||||
This check will find occurrences of ``std::random_shuffle`` and replace it with ``std::shuffle``. In C++17 ``std::random_shuffle`` will no longer be available and thus we need to replace it.
|
||||
|
||||
Below are two examples of what kind of occurrences will be found and two examples of what it will be replaced with.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::vector<int> v;
|
||||
|
||||
// First example
|
||||
std::random_shuffle(vec.begin(), vec.end());
|
||||
|
||||
// Second example
|
||||
std::random_shuffle(vec.begin(), vec.end(), randomFun);
|
||||
|
||||
Both of these examples will be replaced with:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
|
||||
|
||||
The second example will also receive a warning that ``randomFunc`` is no longer supported in the same way as before so if the user wants the same functionality, the user will need to change the implementation of the ``randomFunc``.
|
||||
|
||||
One thing to be aware of here is that ``std::random_device`` is quite expensive to initialize. So if you are using the code in a performance critical place, you probably want to initialize it elsewhere.
|
|
@ -0,0 +1,57 @@
|
|||
// RUN: %check_clang_tidy %s modernize-replace-random-shuffle %t -- -- -std=c++11
|
||||
|
||||
//CHECK-FIXES: #include <random>
|
||||
|
||||
namespace std {
|
||||
template <typename T> struct vec_iterator {
|
||||
T *ptr;
|
||||
vec_iterator operator++(int);
|
||||
};
|
||||
|
||||
template <typename T> struct vector {
|
||||
typedef vec_iterator<T> iterator;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
};
|
||||
|
||||
template <typename FwIt>
|
||||
void random_shuffle(FwIt begin, FwIt end);
|
||||
|
||||
template <typename FwIt, typename randomFunc>
|
||||
void random_shuffle(FwIt begin, FwIt end, randomFunc& randomfunc);
|
||||
|
||||
template <typename FwIt>
|
||||
void shuffle(FwIt begin, FwIt end);
|
||||
} // namespace std
|
||||
|
||||
// Random Func
|
||||
int myrandom (int i) { return i;}
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
std::vector<int> vec;
|
||||
|
||||
std::random_shuffle(vec.begin(), vec.end());
|
||||
// CHECK-MESSAGE: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
|
||||
// CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
|
||||
|
||||
std::shuffle(vec.begin(), vec.end());
|
||||
|
||||
random_shuffle(vec.begin(), vec.end());
|
||||
// CHECK-MESSAGE: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' instead
|
||||
// CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
|
||||
|
||||
std::random_shuffle(vec.begin(), vec.end(), myrandom);
|
||||
// CHECK-MESSAGE: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
|
||||
// CHECK-FIXES: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
|
||||
|
||||
random_shuffle(vec.begin(), vec.end(), myrandom);
|
||||
// CHECK-MESSAGE: [[@LINE-1]]:3: warning: 'std::random_shuffle' has been removed in C++17; use 'std::shuffle' and an alternative random mechanism instead
|
||||
// CHECK-FIXES: shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()()));
|
||||
|
||||
shuffle(vec.begin(), vec.end());
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue