brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · cfc546a Raw
96 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ReplaceRandomShuffleCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Frontend/CompilerInstance.h"13#include "clang/Lex/Preprocessor.h"14 15using namespace clang::ast_matchers;16 17namespace clang::tidy::modernize {18 19ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name,20                                                     ClangTidyContext *Context)21    : ClangTidyCheck(Name, Context),22      IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",23                                               utils::IncludeSorter::IS_LLVM),24                      areDiagsSelfContained()) {}25 26void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {27  const auto Begin = hasArgument(0, expr());28  const auto End = hasArgument(1, expr());29  const auto RandomFunc = hasArgument(2, expr().bind("randomFunc"));30  Finder->addMatcher(31      traverse(32          TK_AsIs,33          callExpr(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")))))38              .bind("match")),39      this);40}41 42void ReplaceRandomShuffleCheck::registerPPCallbacks(43    const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {44  IncludeInserter.registerPreprocessor(PP);45}46 47void ReplaceRandomShuffleCheck::storeOptions(48    ClangTidyOptions::OptionMap &Opts) {49  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());50}51 52void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) {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");56 57  if (MatchedCallExpr->getBeginLoc().isMacroID())58    return;59 60  auto Diag = [&] {61    if (MatchedCallExpr->getNumArgs() == 3) {62      auto DiagL =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()())");69      return DiagL;70    }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()())");77    return DiagL;78  }();79 80  std::string NewName = "shuffle";81  const StringRef ContainerText = Lexer::getSourceText(82      CharSourceRange::getTokenRange(MatchedDecl->getSourceRange()),83      *Result.SourceManager, getLangOpts());84  if (ContainerText.starts_with("std::"))85    NewName = "std::" + NewName;86 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()),92      "<random>");93}94 95} // namespace clang::tidy::modernize96