brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.2 KiB · 1dff808 Raw
82 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 "UniqueptrDeleteReleaseCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Basic/Diagnostic.h"13#include "clang/Basic/SourceLocation.h"14#include "clang/Lex/Lexer.h"15 16using namespace clang::ast_matchers;17 18namespace clang::tidy::readability {19 20void UniqueptrDeleteReleaseCheck::storeOptions(21    ClangTidyOptions::OptionMap &Opts) {22  Options.store(Opts, "PreferResetCall", PreferResetCall);23}24 25UniqueptrDeleteReleaseCheck::UniqueptrDeleteReleaseCheck(26    StringRef Name, ClangTidyContext *Context)27    : ClangTidyCheck(Name, Context),28      PreferResetCall(Options.get("PreferResetCall", false)) {}29 30void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) {31  auto UniquePtrWithDefaultDelete = classTemplateSpecializationDecl(32      hasName("::std::unique_ptr"),33      hasTemplateArgument(1, refersToType(hasDeclaration(cxxRecordDecl(34                                 hasName("::std::default_delete"))))));35 36  Finder->addMatcher(37      cxxDeleteExpr(38          unless(isInTemplateInstantiation()),39          has(cxxMemberCallExpr(40                  callee(memberExpr(hasObjectExpression(anyOf(41                                        hasType(UniquePtrWithDefaultDelete),42                                        hasType(pointsTo(43                                            UniquePtrWithDefaultDelete)))),44                                    member(cxxMethodDecl(hasName("release"))))45                             .bind("release_expr")))46                  .bind("release_call")))47          .bind("delete"),48      this);49}50 51void UniqueptrDeleteReleaseCheck::check(52    const MatchFinder::MatchResult &Result) {53  const auto *DeleteExpr = Result.Nodes.getNodeAs<CXXDeleteExpr>("delete");54  const auto *ReleaseExpr = Result.Nodes.getNodeAs<MemberExpr>("release_expr");55  const auto *ReleaseCallExpr =56      Result.Nodes.getNodeAs<CXXMemberCallExpr>("release_call");57 58  if (ReleaseExpr->getBeginLoc().isMacroID())59    return;60 61  auto D =62      diag(DeleteExpr->getBeginLoc(), "prefer '%select{= nullptr|reset()}0' "63                                      "to reset 'unique_ptr<>' objects");64  D << PreferResetCall << DeleteExpr->getSourceRange()65    << FixItHint::CreateRemoval(CharSourceRange::getCharRange(66           DeleteExpr->getBeginLoc(),67           DeleteExpr->getArgument()->getBeginLoc()));68  if (PreferResetCall) {69    D << FixItHint::CreateReplacement(ReleaseExpr->getMemberLoc(), "reset");70  } else {71    if (ReleaseExpr->isArrow())72      D << FixItHint::CreateInsertion(ReleaseExpr->getBase()->getBeginLoc(),73                                      "*");74    D << FixItHint::CreateReplacement(75        CharSourceRange::getTokenRange(ReleaseExpr->getOperatorLoc(),76                                       ReleaseCallExpr->getEndLoc()),77        " = nullptr");78  }79}80 81} // namespace clang::tidy::readability82