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