diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /compilerplugins/clang/trivialdestructor.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compilerplugins/clang/trivialdestructor.cxx')
-rw-r--r-- | compilerplugins/clang/trivialdestructor.cxx | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/compilerplugins/clang/trivialdestructor.cxx b/compilerplugins/clang/trivialdestructor.cxx new file mode 100644 index 0000000000..5db1bbab70 --- /dev/null +++ b/compilerplugins/clang/trivialdestructor.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cassert> +#include <string> +#include <iostream> +#include <unordered_map> +#include <unordered_set> + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Look for explicit destructors that can be trivial (and therefore don't need to be declared) + +namespace +{ +class TrivialDestructor : public loplugin::FilteringPlugin<TrivialDestructor> +{ +public: + explicit TrivialDestructor(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXDestructorDecl(CXXDestructorDecl const*); + +private: + bool HasTrivialDestructorBody(const CXXRecordDecl* ClassDecl); + bool FieldHasTrivialDestructor(const FieldDecl* Field); +}; + +bool TrivialDestructor::VisitCXXDestructorDecl(CXXDestructorDecl const* destructorDecl) +{ + if (ignoreLocation(destructorDecl)) + return true; + if (!destructorDecl->isThisDeclarationADefinition()) + return true; + if (!destructorDecl->hasTrivialBody()) + return true; + if (destructorDecl->isVirtual()) + return true; + if (destructorDecl->getExceptionSpecType() != EST_None) + return true; + if (destructorDecl->getAccess() != AS_public) + return true; + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(destructorDecl->getLocation()))) + return true; + if (!HasTrivialDestructorBody(destructorDecl->getParent())) + return true; + + report(DiagnosticsEngine::Warning, "no need for explicit destructor decl", + destructorDecl->getLocation()) + << destructorDecl->getSourceRange(); + for (FunctionDecl const* d2 = destructorDecl;;) + { + d2 = d2->getPreviousDecl(); + if (d2 == nullptr) + { + break; + } + report(DiagnosticsEngine::Note, "previous declaration is here", d2->getLocation()) + << d2->getSourceRange(); + } + return true; +} + +bool TrivialDestructor::HasTrivialDestructorBody(const CXXRecordDecl* ClassDecl) +{ + // Check fields. + for (const auto* field : ClassDecl->fields()) + if (!FieldHasTrivialDestructor(field)) + return false; + + // Check bases. + for (const auto& I : ClassDecl->bases()) + { + const CXXRecordDecl* Base = I.getType()->getAsCXXRecordDecl(); + if (!Base->hasTrivialDestructor()) + return false; + } + + return true; +} + +bool TrivialDestructor::FieldHasTrivialDestructor(const FieldDecl* Field) +{ + QualType FieldBaseElementType = compiler.getASTContext().getBaseElementType(Field->getType()); + + const RecordType* RT = FieldBaseElementType->getAs<RecordType>(); + if (!RT) + return true; + + CXXRecordDecl* FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + + return FieldClassDecl->hasTrivialDestructor(); +} + +loplugin::Plugin::Registration<TrivialDestructor> X("trivialdestructor", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |