blob: 3ad346cdd9db9a1bedd2a5b62439492cf252a3ce [file] [log] [blame]
Samuel Benzaquendaef1632015-10-19 21:49:51 +00001//===--- UniqueptrDeleteReleaseCheck.cpp - clang-tidy----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "UniqueptrDeleteReleaseCheck.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/Lex/Lexer.h"
14
15using namespace clang::ast_matchers;
16
17namespace clang {
18namespace tidy {
Etienne Bergeron456177b2016-05-02 18:00:29 +000019namespace readability {
Samuel Benzaquendaef1632015-10-19 21:49:51 +000020
21void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) {
22 auto IsSusbstituted = qualType(anyOf(
23 substTemplateTypeParmType(), hasDescendant(substTemplateTypeParmType())));
24
25 auto UniquePtrWithDefaultDelete = classTemplateSpecializationDecl(
26 hasName("std::unique_ptr"),
27 hasTemplateArgument(1, refersToType(qualType(hasDeclaration(cxxRecordDecl(
28 hasName("std::default_delete")))))));
29
30 Finder->addMatcher(
Piotr Padlewskie93a73f2016-05-31 15:26:56 +000031 cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
32 on(expr(hasType(UniquePtrWithDefaultDelete),
33 unless(hasType(IsSusbstituted)))
34 .bind("uptr")),
35 callee(cxxMethodDecl(hasName("release")))))))
Samuel Benzaquendaef1632015-10-19 21:49:51 +000036 .bind("delete"),
37 this);
38}
39
40void UniqueptrDeleteReleaseCheck::check(
41 const MatchFinder::MatchResult &Result) {
42 const auto *PtrExpr = Result.Nodes.getNodeAs<Expr>("uptr");
43 const auto *DeleteExpr = Result.Nodes.getNodeAs<Expr>("delete");
44
45 if (PtrExpr->getLocStart().isMacroID())
46 return;
47
48 // Ignore dependent types.
49 // It can give us false positives, so we go with false negatives instead to
50 // be safe.
51 if (PtrExpr->getType()->isDependentType())
52 return;
53
Gabor Horvathafad84c2016-09-24 02:13:45 +000054 SourceLocation AfterPtr = Lexer::getLocForEndOfToken(
55 PtrExpr->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
Samuel Benzaquendaef1632015-10-19 21:49:51 +000056
57 diag(DeleteExpr->getLocStart(),
58 "prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> "
59 "objects")
60 << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
61 DeleteExpr->getLocStart(), PtrExpr->getLocStart()))
62 << FixItHint::CreateReplacement(
63 CharSourceRange::getTokenRange(AfterPtr, DeleteExpr->getLocEnd()),
64 " = nullptr");
65}
66
Etienne Bergeron456177b2016-05-02 18:00:29 +000067} // namespace readability
Samuel Benzaquendaef1632015-10-19 21:49:51 +000068} // namespace tidy
69} // namespace clang