diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-06-29 08:15:20 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-06-29 09:35:30 +0200 |
commit | 497e40ad03c27837978551ba15491c3fb2a0bf53 (patch) | |
tree | baa53156ae5234b65f645e11e590c64e569c6284 /compilerplugins | |
parent | 71112060e0930fc58087c3762e836b1e12b60f75 (diff) |
improve refcounting loplugin
to find ref-counted classes being managed via other smart pointer
classes.
Hopefully prevent needing fixes like
642ae256ea5b8083ba0b3c097ca8ea52304b9cdb
"ChangedUIEventListener is refcounted, mustn't be helt by unique_ptr"
Change-Id: I6b0c5f8f87ce3546a8a1104ce1000470c09459bd
Reviewed-on: https://gerrit.libreoffice.org/39378
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/refcounting.cxx | 78 | ||||
-rw-r--r-- | compilerplugins/clang/test/refcounting.cxx | 19 |
2 files changed, 84 insertions, 13 deletions
diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx index e008a9e501dd..65520d589a8f 100644 --- a/compilerplugins/clang/refcounting.cxx +++ b/compilerplugins/clang/refcounting.cxx @@ -386,28 +386,67 @@ bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { return true; } - std::string aParentName = fieldDecl->getParent()->getQualifiedNameAsString(); + // check for dodgy code managing ref-counted stuff with shared_ptr or unique_ptr or similar stuff + QualType firstTemplateParamType; + if (auto recordType = fieldDecl->getType()->getUnqualifiedDesugaredType()->getAs<RecordType>()) { + auto recordDeclName = recordType->getDecl()->getName(); + if (recordDeclName.find("unique_ptr") != StringRef::npos + || recordDeclName.find("shared_ptr") != StringRef::npos + || recordDeclName.find("intrusive_ptr") != StringRef::npos) // boost + { + auto templateDecl = dyn_cast<ClassTemplateSpecializationDecl>(recordType->getDecl()); + if (templateDecl && templateDecl->getTemplateArgs().size() > 0) + firstTemplateParamType = templateDecl->getTemplateArgs()[0].getAsType(); + } + } if (containsSvRefBaseSubclass(fieldDecl->getType().getTypePtr())) { report( DiagnosticsEngine::Warning, - "SvRefBase subclass being directly heap managed, should be managed via tools::SvRef, " - + fieldDecl->getType().getAsString() - + ", parent is " + aParentName, + "SvRefBase subclass %0 being directly heap managed, should be managed via tools::SvRef, " + ", parent is %1", fieldDecl->getLocation()) - << fieldDecl->getSourceRange(); + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + if (!firstTemplateParamType.isNull() && containsSvRefBaseSubclass(firstTemplateParamType.getTypePtr())) + { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass %0 being managed via smart pointer, should be managed via tools::SvRef, " + "parent is %1", + fieldDecl->getLocation()) + << firstTemplateParamType + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); } if (containsSalhelperReferenceObjectSubclass(fieldDecl->getType().getTypePtr())) { report( DiagnosticsEngine::Warning, - "salhelper::SimpleReferenceObject subclass being directly heap managed, should be managed via rtl::Reference, " - + fieldDecl->getType().getAsString() - + ", parent is " + aParentName, + "salhelper::SimpleReferenceObject subclass %0 being directly heap managed, should be managed via rtl::Reference, " + "parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + if (!firstTemplateParamType.isNull() && containsSalhelperReferenceObjectSubclass(firstTemplateParamType.getTypePtr())) + { + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass %0 being managed via smart pointer, should be managed via rtl::Reference, " + "parent is %1", fieldDecl->getLocation()) - << fieldDecl->getSourceRange(); + << firstTemplateParamType + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); } + std::string aParentName = fieldDecl->getParent()->getQualifiedNameAsString(); if ( aParentName == "com::sun::star::uno::BaseReference" || aParentName == "cppu::detail::element_alias" // this is playing some kind of game to avoid circular references @@ -419,11 +458,24 @@ bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { if (containsXInterfaceSubclass(fieldDecl->getType())) { report( DiagnosticsEngine::Warning, - "XInterface subclass being directly heap managed, should be managed via uno::Reference, " - + fieldDecl->getType().getAsString() - + ", parent is " + aParentName, + "XInterface subclass %0 being directly heap managed, should be managed via uno::Reference, " + "parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + if (!firstTemplateParamType.isNull() && containsXInterfaceSubclass(firstTemplateParamType)) + { + report( + DiagnosticsEngine::Warning, + "XInterface subclass %0 being managed via smart pointer, should be managed via uno::Reference, " + "parent is %1", fieldDecl->getLocation()) - << fieldDecl->getSourceRange(); + << firstTemplateParamType + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); } checkUnoReference(fieldDecl->getType(), fieldDecl, aParentName, "field"); diff --git a/compilerplugins/clang/test/refcounting.cxx b/compilerplugins/clang/test/refcounting.cxx new file mode 100644 index 000000000000..9ee403c55946 --- /dev/null +++ b/compilerplugins/clang/test/refcounting.cxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <memory> +#include <com/sun/star/uno/XInterface.hpp> + +struct Foo +{ + std::unique_ptr<css::uno::XInterface> m_foo1; // expected-error {{XInterface subclass 'com::sun::star::uno::XInterface' being managed via smart pointer, should be managed via uno::Reference, parent is 'Foo' [loplugin:refcounting]}} + std::shared_ptr<css::uno::XInterface> m_foo2; // expected-error {{XInterface subclass 'com::sun::star::uno::XInterface' being managed via smart pointer, should be managed via uno::Reference, parent is 'Foo' [loplugin:refcounting]}} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |