From 9c1f700aff5f7e375d3570231e6d68fe2e2c0334 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Wed, 5 Aug 2015 10:48:40 +0200 Subject: improve refcounting loplugin to check SvRef-based classes Change-Id: I2b3c8eedabeaecd8dcae9fe69c951353a5686883 Reviewed-on: https://gerrit.libreoffice.org/17521 Tested-by: Jenkins Reviewed-by: Noel Grandin --- compilerplugins/clang/refcounting.cxx | 120 +++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'compilerplugins/clang/refcounting.cxx') diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx index 7b859ff65f22..3a6c715b6268 100644 --- a/compilerplugins/clang/refcounting.cxx +++ b/compilerplugins/clang/refcounting.cxx @@ -215,7 +215,81 @@ bool containsXInterfaceSubclass(const Type* pType0) { } } +bool containsSvRefBaseSubclass(const Type* pType0) { + if (!pType0) + return false; + const Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + pRecordDecl = pRecordDecl->getCanonicalDecl(); + } + if (pRecordDecl) { + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + std::string aName = pTemplate->getQualifiedNameAsString(); + if (aName == "tools::SvRef") + return false; + for(unsigned i=0; igetTemplateArgs().size(); ++i) { + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[i]; + if (rArg.getKind() == TemplateArgument::ArgKind::Type && + containsSvRefBaseSubclass(rArg.getAsType().getTypePtr())) + { + return true; + } + } + } + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsSvRefBaseSubclass(elementType.getTypePtr()); + } else { + return isDerivedFrom(pRecordDecl, "tools::SvRefBase"); + } +} +bool containsSalhelperReferenceObjectSubclass(const Type* pType0) { + if (!pType0) + return false; + const Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + pRecordDecl = pRecordDecl->getCanonicalDecl(); + } + if (pRecordDecl) { + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + std::string aName = pTemplate->getQualifiedNameAsString(); + if (aName == "rtl::Reference" || aName == "store::OStoreHandle") + return false; + for(unsigned i=0; igetTemplateArgs().size(); ++i) { + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[i]; + if (rArg.getKind() == TemplateArgument::ArgKind::Type && + containsSalhelperReferenceObjectSubclass(rArg.getAsType().getTypePtr())) + { + return true; + } + } + } + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsSalhelperReferenceObjectSubclass(elementType.getTypePtr()); + } else { + return isDerivedFrom(pRecordDecl, "salhelper::SimpleReferenceObject"); + } +} bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { if (ignoreLocation(fieldDecl)) { @@ -224,7 +298,29 @@ bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { if (fieldDecl->isBitField()) { return true; } + std::string aParentName = fieldDecl->getParent()->getQualifiedNameAsString(); + + 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, + fieldDecl->getLocation()) + << 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, + fieldDecl->getLocation()) + << fieldDecl->getSourceRange(); + } + if ( aParentName == "com::sun::star::uno::BaseReference" || aParentName == "cppu::detail::element_alias" // this is playing some kind of game to avoid circular references @@ -241,7 +337,6 @@ bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { + ", parent is " + aParentName, fieldDecl->getLocation()) << fieldDecl->getSourceRange(); - return true; } return true; } @@ -251,6 +346,29 @@ bool RefCounting::VisitVarDecl(const VarDecl * varDecl) { if (ignoreLocation(varDecl)) { return true; } + if (isa(varDecl)) { + return true; + } + if (containsSvRefBaseSubclass(varDecl->getType().getTypePtr())) { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass being directly stack managed, should be managed via tools::SvRef, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsSalhelperReferenceObjectSubclass(varDecl->getType().getTypePtr())) { + StringRef name { compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) }; + // this is playing games that it believes is safe + if (name == SRCDIR "/stoc/source/security/permissions.cxx") + return true; + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass being directly stack managed, should be managed via rtl::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } if (containsXInterfaceSubclass(varDecl->getType())) { report( DiagnosticsEngine::Warning, -- cgit