brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · d0577ae Raw
151 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 "ReplaceAutoPtrCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Frontend/CompilerInstance.h"13#include "clang/Lex/Lexer.h"14#include "clang/Lex/Preprocessor.h"15 16using namespace clang;17using namespace clang::ast_matchers;18 19namespace clang::tidy::modernize {20 21namespace {22static const char AutoPtrTokenId[] = "AutoPrTokenId";23static const char AutoPtrOwnershipTransferId[] = "AutoPtrOwnershipTransferId";24 25/// Matches expressions that are lvalues.26///27/// In the following example, a[0] matches expr(isLValue()):28/// \code29///   std::string a[2];30///   std::string b;31///   b = a[0];32///   b = "this string won't match";33/// \endcode34AST_MATCHER(Expr, isLValue) { return Node.getValueKind() == VK_LValue; }35 36} // namespace37 38ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef Name,39                                         ClangTidyContext *Context)40    : ClangTidyCheck(Name, Context),41      Inserter(Options.getLocalOrGlobal("IncludeStyle",42                                        utils::IncludeSorter::IS_LLVM),43               areDiagsSelfContained()) {}44 45void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {46  Options.store(Opts, "IncludeStyle", Inserter.getStyle());47}48 49void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {50  auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isInStdNamespace());51  auto AutoPtrType = hasCanonicalType(recordType(hasDeclaration(AutoPtrDecl)));52 53  //   std::auto_ptr<int> a;54  //        ^~~~~~~~~~~~~55  //56  //   typedef std::auto_ptr<int> int_ptr_t;57  //                ^~~~~~~~~~~~~58  //59  //   std::auto_ptr<int> fn(std::auto_ptr<int>);60  //        ^~~~~~~~~~~~~         ^~~~~~~~~~~~~61  Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType))).bind(AutoPtrTokenId),62                     this);63 64  //   using std::auto_ptr;65  //   ^~~~~~~~~~~~~~~~~~~66  Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(67                                   hasName("auto_ptr"), isInStdNamespace()))))68                         .bind(AutoPtrTokenId),69                     this);70 71  // Find ownership transfers via copy construction and assignment.72  // AutoPtrOwnershipTransferId is bound to the part that has to be wrapped73  // into std::move().74  //   std::auto_ptr<int> i, j;75  //   i = j;76  //   ~~~~^77  auto MovableArgumentMatcher =78      expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);79 80  Finder->addMatcher(81      cxxOperatorCallExpr(hasOverloadedOperatorName("="),82                          callee(cxxMethodDecl(ofClass(AutoPtrDecl))),83                          hasArgument(1, MovableArgumentMatcher)),84      this);85  Finder->addMatcher(86      traverse(TK_AsIs,87               cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1),88                                hasArgument(0, MovableArgumentMatcher))),89      this);90}91 92void ReplaceAutoPtrCheck::registerPPCallbacks(const SourceManager &SM,93                                              Preprocessor *PP,94                                              Preprocessor *ModuleExpanderPP) {95  Inserter.registerPreprocessor(PP);96}97 98void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) {99  const SourceManager &SM = *Result.SourceManager;100  if (const auto *E =101          Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) {102    const CharSourceRange Range = Lexer::makeFileCharRange(103        CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions());104 105    if (Range.isInvalid())106      return;107 108    auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership")109                << FixItHint::CreateInsertion(Range.getBegin(), "std::move(")110                << FixItHint::CreateInsertion(Range.getEnd(), ")")111                << Inserter.createMainFileIncludeInsertion("<utility>");112 113    return;114  }115 116  SourceLocation AutoPtrLoc;117  if (const auto *PTL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {118    auto TL = *PTL;119    if (auto QTL = TL.getAs<QualifiedTypeLoc>())120      TL = QTL.getUnqualifiedLoc();121    //   std::auto_ptr<int> i;122    //        ^123    if (auto Loc = TL.getAs<TemplateSpecializationTypeLoc>())124      AutoPtrLoc = Loc.getTemplateNameLoc();125  } else if (const auto *D =126                 Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) {127    // using std::auto_ptr;128    //            ^129    AutoPtrLoc = D->getNameInfo().getBeginLoc();130  } else {131    llvm_unreachable("Bad Callback. No node provided.");132  }133 134  if (AutoPtrLoc.isMacroID())135    AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc);136 137  // Ensure that only the 'auto_ptr' token is replaced and not the template138  // aliases.139  if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen("auto_ptr")) !=140      "auto_ptr")141    return;142 143  const SourceLocation EndLoc =144      AutoPtrLoc.getLocWithOffset(strlen("auto_ptr") - 1);145  diag(AutoPtrLoc, "auto_ptr is deprecated, use unique_ptr instead")146      << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc),147                                      "unique_ptr");148}149 150} // namespace clang::tidy::modernize151