update vclwidgets loplugin to handle VclReferenceBase

Change-Id: I447cdb8c65d880b3c5ff28b35cefdc56ff784852
This commit is contained in:
Noel Grandin
2016-05-18 12:25:54 +02:00
parent ceaa06bc71
commit 27fd3c4e66
2 changed files with 22 additions and 18 deletions

View File

@@ -57,6 +57,8 @@ static bool startsWith(const std::string& s, const char* other)
return s.compare(0, strlen(other), other) == 0; return s.compare(0, strlen(other), other) == 0;
} }
#define BASE_REF_COUNTED_CLASS "VclReferenceBase"
bool BaseCheckNotWindowSubclass( bool BaseCheckNotWindowSubclass(
const CXXRecordDecl *BaseDefinition const CXXRecordDecl *BaseDefinition
#if CLANG_VERSION < 30800 #if CLANG_VERSION < 30800
@@ -64,7 +66,7 @@ bool BaseCheckNotWindowSubclass(
#endif #endif
) )
{ {
if (BaseDefinition && BaseDefinition->getQualifiedNameAsString() == "OutputDevice") { if (BaseDefinition && BaseDefinition->getQualifiedNameAsString() == BASE_REF_COUNTED_CLASS) {
return false; return false;
} }
return true; return true;
@@ -73,7 +75,7 @@ bool BaseCheckNotWindowSubclass(
bool isDerivedFromWindow(const CXXRecordDecl *decl) { bool isDerivedFromWindow(const CXXRecordDecl *decl) {
if (!decl) if (!decl)
return false; return false;
if (decl->getQualifiedNameAsString() == "OutputDevice") if (decl->getQualifiedNameAsString() == BASE_REF_COUNTED_CLASS)
return true; return true;
if (!decl->hasDefinition()) { if (!decl->hasDefinition()) {
return false; return false;
@@ -155,8 +157,8 @@ bool VCLWidgets::VisitCXXDestructorDecl(const CXXDestructorDecl* pCXXDestructorD
return true; return true;
} }
const CXXRecordDecl * pRecordDecl = pCXXDestructorDecl->getParent(); const CXXRecordDecl * pRecordDecl = pCXXDestructorDecl->getParent();
// ignore OutputDevice class // ignore
if (pRecordDecl->getQualifiedNameAsString() == "OutputDevice") { if (pRecordDecl->getQualifiedNameAsString() == BASE_REF_COUNTED_CLASS) {
return true; return true;
} }
// check if this class is derived from Window // check if this class is derived from Window
@@ -193,12 +195,12 @@ bool VCLWidgets::VisitCXXDestructorDecl(const CXXDestructorDecl* pCXXDestructorD
if (bFoundVclPtrField && pCompoundStatement && pCompoundStatement->size() == 0) { if (bFoundVclPtrField && pCompoundStatement && pCompoundStatement->size() == 0) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass with VclPtr field must call disposeOnce() from its destructor", BASE_REF_COUNTED_CLASS " subclass with VclPtr field must call disposeOnce() from its destructor",
pCXXDestructorDecl->getLocStart()) pCXXDestructorDecl->getLocStart())
<< pCXXDestructorDecl->getSourceRange(); << pCXXDestructorDecl->getSourceRange();
return true; return true;
} }
// check that the destructor for a OutputDevice subclass does nothing except call into the disposeOnce() method // check that the destructor for a BASE_REF_COUNTED_CLASS subclass does nothing except call into the disposeOnce() method
bool bOk = false; bool bOk = false;
if (pCompoundStatement) { if (pCompoundStatement) {
bool bFoundDisposeOnce = false; bool bFoundDisposeOnce = false;
@@ -229,7 +231,7 @@ bool VCLWidgets::VisitCXXDestructorDecl(const CXXDestructorDecl* pCXXDestructorD
{ {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass should have nothing in its destructor but a call to disposeOnce()", BASE_REF_COUNTED_CLASS " subclass should have nothing in its destructor but a call to disposeOnce()",
pCXXDestructorDecl->getLocStart()) pCXXDestructorDecl->getLocStart())
<< pCXXDestructorDecl->getSourceRange(); << pCXXDestructorDecl->getSourceRange();
} }
@@ -249,7 +251,7 @@ bool VCLWidgets::VisitVarDecl(const VarDecl * pVarDecl) {
if (containsWindowSubclass(pVarDecl->getType())) { if (containsWindowSubclass(pVarDecl->getType())) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass %0 should be wrapped in VclPtr", BASE_REF_COUNTED_CLASS " subclass %0 should be wrapped in VclPtr",
pVarDecl->getLocation()) pVarDecl->getLocation())
<< pVarDecl->getType() << pVarDecl->getSourceRange(); << pVarDecl->getType() << pVarDecl->getSourceRange();
return true; return true;
@@ -267,7 +269,7 @@ bool VCLWidgets::VisitVarDecl(const VarDecl * pVarDecl) {
if (isDerivedFromWindow(recordDecl)) { if (isDerivedFromWindow(recordDecl)) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass allocated on stack, should be allocated via VclPtr or via *", BASE_REF_COUNTED_CLASS " subclass allocated on stack, should be allocated via VclPtr or via *",
pVarDecl->getLocation()) pVarDecl->getLocation())
<< pVarDecl->getSourceRange(); << pVarDecl->getSourceRange();
} }
@@ -289,7 +291,7 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
pParentRecordDecl->getQualifiedNameAsString() == "ScHFEditPage"))) { pParentRecordDecl->getQualifiedNameAsString() == "ScHFEditPage"))) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass %0 declared as a pointer member, should be wrapped in VclPtr", BASE_REF_COUNTED_CLASS " subclass %0 declared as a pointer member, should be wrapped in VclPtr",
fieldDecl->getLocation()) fieldDecl->getLocation())
<< fieldDecl->getType() << fieldDecl->getSourceRange(); << fieldDecl->getType() << fieldDecl->getSourceRange();
return true; return true;
@@ -308,7 +310,7 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
if (isDerivedFromWindow(recordDecl)) { if (isDerivedFromWindow(recordDecl)) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass allocated as a class member, should be allocated via VclPtr", BASE_REF_COUNTED_CLASS " subclass allocated as a class member, should be allocated via VclPtr",
fieldDecl->getLocation()) fieldDecl->getLocation())
<< fieldDecl->getSourceRange(); << fieldDecl->getSourceRange();
} }
@@ -329,14 +331,14 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
if (!bFoundDispose) { if (!bFoundDispose) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass with a VclPtr field MUST override dispose() (and call its superclass dispose() as the last thing it does)", BASE_REF_COUNTED_CLASS " subclass with a VclPtr field MUST override dispose() (and call its superclass dispose() as the last thing it does)",
fieldDecl->getLocation()) fieldDecl->getLocation())
<< fieldDecl->getSourceRange(); << fieldDecl->getSourceRange();
} }
if (!pParentRecordDecl->hasUserDeclaredDestructor()) { if (!pParentRecordDecl->hasUserDeclaredDestructor()) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass with a VclPtr field MUST have a user-provided destructor (that calls disposeOnce())", BASE_REF_COUNTED_CLASS " subclass with a VclPtr field MUST have a user-provided destructor (that calls disposeOnce())",
fieldDecl->getLocation()) fieldDecl->getLocation())
<< fieldDecl->getSourceRange(); << fieldDecl->getSourceRange();
} }
@@ -378,9 +380,9 @@ bool VCLWidgets::VisitFunctionDecl( const FunctionDecl* functionDecl )
&& pMethodDecl->getParent()->getQualifiedNameAsString() == "VclPtr") { && pMethodDecl->getParent()->getQualifiedNameAsString() == "VclPtr") {
return true; return true;
} }
// ignore the OutputDevice::dispose() method // ignore the BASE_REF_COUNTED_CLASS::dispose() method
if (pMethodDecl if (pMethodDecl
&& pMethodDecl->getParent()->getQualifiedNameAsString() == "OutputDevice") { && pMethodDecl->getParent()->getQualifiedNameAsString() == BASE_REF_COUNTED_CLASS) {
return true; return true;
} }
if (functionDecl->hasBody() && pMethodDecl && isDerivedFromWindow(pMethodDecl->getParent())) { if (functionDecl->hasBody() && pMethodDecl && isDerivedFromWindow(pMethodDecl->getParent())) {
@@ -389,7 +391,7 @@ bool VCLWidgets::VisitFunctionDecl( const FunctionDecl* functionDecl )
if (!isDisposeCallingSuperclassDispose(pMethodDecl)) { if (!isDisposeCallingSuperclassDispose(pMethodDecl)) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"OutputDevice subclass dispose() function MUST call dispose() of its superclass as the last thing it does", BASE_REF_COUNTED_CLASS " subclass dispose() function MUST call dispose() of its superclass as the last thing it does",
functionDecl->getLocStart()) functionDecl->getLocStart())
<< functionDecl->getSourceRange(); << functionDecl->getSourceRange();
} }
@@ -409,11 +411,11 @@ bool VCLWidgets::VisitCXXDeleteExpr(const CXXDeleteExpr *pCXXDeleteExpr)
SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
pCXXDeleteExpr->getLocStart()); pCXXDeleteExpr->getLocStart());
StringRef filename = compiler.getSourceManager().getFilename(spellingLocation); StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
if ( !(filename.startswith(SRCDIR "/include/vcl/outdev.hxx"))) if ( !(filename.startswith(SRCDIR "/include/vcl/vclreferencebase.hxx")))
{ {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
"calling delete on instance of OutputDevice subclass, must rather call disposeAndClear()", "calling delete on instance of " BASE_REF_COUNTED_CLASS " subclass, must rather call disposeAndClear()",
pCXXDeleteExpr->getLocStart()) pCXXDeleteExpr->getLocStart())
<< pCXXDeleteExpr->getSourceRange(); << pCXXDeleteExpr->getSourceRange();
} }

View File

@@ -226,6 +226,8 @@ void OutputDevice::dispose()
} }
mpAlphaVDev.disposeAndClear(); mpAlphaVDev.disposeAndClear();
VclReferenceBase::dispose();
} }
SalGraphics* OutputDevice::GetGraphics() SalGraphics* OutputDevice::GetGraphics()