summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/refcounting.cxx
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-08-05 10:48:40 +0200
committerNoel Grandin <noelgrandin@gmail.com>2015-08-05 11:26:04 +0000
commit9c1f700aff5f7e375d3570231e6d68fe2e2c0334 (patch)
tree0d616e27ab7cf82dd5e28939b984a626adc682e0 /compilerplugins/clang/refcounting.cxx
parenta5b842f3aa401352f5454edb8f47d9576dff0092 (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/clang/refcounting.cxx')
-rw-r--r--compilerplugins/clang/refcounting.cxx120
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,