Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / automem.cxx
blob52bfdf43d6b30427a974fd779e8e0596c35403ad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <memory>
11 #include <cassert>
12 #include <string>
13 #include <iostream>
14 #include <fstream>
15 #include <set>
16 #include "plugin.hxx"
18 /**
19 Find calls to "delete x" where x is a field on an object.
20 Should rather be using std::unique_ptr
23 namespace {
25 class AutoMem:
26 public RecursiveASTVisitor<AutoMem>, public loplugin::Plugin
28 public:
29 explicit AutoMem(loplugin::InstantiationData const & data): Plugin(data), mbInsideDestructor(false) {}
31 virtual void run() override
33 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
36 bool TraverseCXXDestructorDecl(CXXDestructorDecl* );
37 bool VisitCXXDeleteExpr(const CXXDeleteExpr* );
38 private:
39 bool mbInsideDestructor;
42 bool AutoMem::TraverseCXXDestructorDecl(CXXDestructorDecl* expr)
44 mbInsideDestructor = true;
45 bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(expr);
46 mbInsideDestructor = false;
47 return ret;
50 bool AutoMem::VisitCXXDeleteExpr(const CXXDeleteExpr* expr)
52 if (ignoreLocation( expr ))
53 return true;
54 StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(expr->getLocStart()));
55 if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/salhelper/")
56 || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/osl/")
57 || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/salhelper/")
58 || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/store/")
59 || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sal/"))
60 return true;
62 if (mbInsideDestructor)
63 return true;
65 const ImplicitCastExpr* pCastExpr = dyn_cast<ImplicitCastExpr>(expr->getArgument());
66 if (!pCastExpr)
67 return true;
68 const MemberExpr* pMemberExpr = dyn_cast<MemberExpr>(pCastExpr->getSubExpr());
69 if (!pMemberExpr)
70 return true;
71 // ignore union games
72 const FieldDecl* pFieldDecl = dyn_cast<FieldDecl>(pMemberExpr->getMemberDecl());
73 if (!pFieldDecl)
74 return true;
75 TagDecl const * td = dyn_cast<TagDecl>(pFieldDecl->getDeclContext());
76 if (td->isUnion())
77 return true;
79 report(
80 DiagnosticsEngine::Warning,
81 "calling delete on object field, rather use std::unique_ptr or std::scoped_ptr",
82 expr->getLocStart())
83 << expr->getSourceRange();
84 return true;
87 loplugin::Plugin::Registration< AutoMem > X("automem", false);
91 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */