diff options
author | Noel Grandin <noel@peralex.com> | 2015-08-05 10:48:40 +0200 |
---|---|---|
committer | Noel Grandin <noelgrandin@gmail.com> | 2015-08-05 11:26:04 +0000 |
commit | 9c1f700aff5f7e375d3570231e6d68fe2e2c0334 (patch) | |
tree | 0d616e27ab7cf82dd5e28939b984a626adc682e0 /compilerplugins | |
parent | a5b842f3aa401352f5454edb8f47d9576dff0092 (diff) |
improve refcounting loplugin to check SvRef-based classes
Change-Id: I2b3c8eedabeaecd8dcae9fe69c951353a5686883
Reviewed-on: https://gerrit.libreoffice.org/17521
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/refcounting.cxx | 120 |
1 files changed, 119 insertions, 1 deletions
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<ClassTemplateSpecializationDecl>(pRecordDecl); + if (pTemplate) { + std::string aName = pTemplate->getQualifiedNameAsString(); + if (aName == "tools::SvRef") + return false; + for(unsigned i=0; i<pTemplate->getTemplateArgs().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<ArrayType>(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<ClassTemplateSpecializationDecl>(pRecordDecl); + if (pTemplate) { + std::string aName = pTemplate->getQualifiedNameAsString(); + if (aName == "rtl::Reference" || aName == "store::OStoreHandle") + return false; + for(unsigned i=0; i<pTemplate->getTemplateArgs().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<ArrayType>(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<ParmVarDecl>(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, |