1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
13 #include <unordered_map>
14 #include <unordered_set>
18 #include "config_clang.h"
19 #include "clang/AST/CXXInheritance.h"
20 #include "clang/AST/StmtVisitor.h"
22 // Look for explicit destructors that can be trivial (and therefore don't need to be declared)
26 class TrivialDestructor
: public loplugin::FilteringPlugin
<TrivialDestructor
>
29 explicit TrivialDestructor(loplugin::InstantiationData
const& data
)
30 : FilteringPlugin(data
)
34 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
36 bool VisitCXXDestructorDecl(CXXDestructorDecl
const*);
39 bool HasTrivialDestructorBody(const CXXRecordDecl
* ClassDecl
);
40 bool FieldHasTrivialDestructor(const FieldDecl
* Field
);
43 bool TrivialDestructor::VisitCXXDestructorDecl(CXXDestructorDecl
const* destructorDecl
)
45 if (ignoreLocation(destructorDecl
))
47 if (!destructorDecl
->isThisDeclarationADefinition())
49 if (!destructorDecl
->hasTrivialBody())
51 if (destructorDecl
->isVirtual())
53 if (destructorDecl
->getExceptionSpecType() != EST_None
)
55 if (destructorDecl
->getAccess() != AS_public
)
57 if (isInUnoIncludeFile(
58 compiler
.getSourceManager().getSpellingLoc(destructorDecl
->getLocation())))
60 if (!HasTrivialDestructorBody(destructorDecl
->getParent()))
63 report(DiagnosticsEngine::Warning
, "no need for explicit destructor decl",
64 destructorDecl
->getLocation())
65 << destructorDecl
->getSourceRange();
66 for (FunctionDecl
const* d2
= destructorDecl
;;)
68 d2
= d2
->getPreviousDecl();
73 report(DiagnosticsEngine::Note
, "previous declaration is here", d2
->getLocation())
74 << d2
->getSourceRange();
79 bool TrivialDestructor::HasTrivialDestructorBody(const CXXRecordDecl
* ClassDecl
)
82 for (const auto* field
: ClassDecl
->fields())
83 if (!FieldHasTrivialDestructor(field
))
87 for (const auto& I
: ClassDecl
->bases())
89 const CXXRecordDecl
* Base
= I
.getType()->getAsCXXRecordDecl();
90 if (!Base
->hasTrivialDestructor())
97 bool TrivialDestructor::FieldHasTrivialDestructor(const FieldDecl
* Field
)
99 QualType FieldBaseElementType
= compiler
.getASTContext().getBaseElementType(Field
->getType());
101 const RecordType
* RT
= FieldBaseElementType
->getAs
<RecordType
>();
105 CXXRecordDecl
* FieldClassDecl
= cast
<CXXRecordDecl
>(RT
->getDecl());
107 return FieldClassDecl
->hasTrivialDestructor();
110 loplugin::Plugin::Registration
<TrivialDestructor
> X("trivialdestructor", true);
113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */