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>
This commit is contained in:
Noel Grandin
2015-08-05 10:48:40 +02:00
committed by Noel Grandin
parent a5b842f3aa
commit 9c1f700aff
21 changed files with 189 additions and 68 deletions

View File

@@ -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,