summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-01-08 14:09:13 +0200
committerMichael Meeks <michael.meeks@collabora.com>2015-04-09 20:03:21 +0100
commit1798a4433280a6cae38fe535fb043a8e27d7f95a (patch)
treeb08acb0329cd59ffcf18466b4efe30406ef421a0
parenta6acccc6d2e6a49691d2612af9898e4018c68861 (diff)
compilerplugin: check that necessary Window subclasses have a dispose method
i.e. the ones that declare any VclPtr fields Change-Id: I7adfc3b3b190a2ede60bfccd08f85a269fae33ca
-rw-r--r--compilerplugins/clang/vclwidgets.cxx40
-rw-r--r--include/vcl/combobox.hxx1
-rw-r--r--include/vcl/dialog.hxx1
-rw-r--r--include/vcl/layout.hxx2
-rw-r--r--vcl/source/control/combobox.cxx6
-rw-r--r--vcl/source/window/dialog.cxx7
-rw-r--r--vcl/source/window/layout.cxx6
7 files changed, 63 insertions, 0 deletions
diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index aa2af7fe5962..896cd3f38889 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -31,6 +31,8 @@ public:
virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
+ bool VisitCXXRecordDecl(const CXXRecordDecl * decl);
+
bool VisitFieldDecl(const FieldDecl * decl);
bool VisitParmVarDecl(ParmVarDecl const * decl);
@@ -76,6 +78,44 @@ bool isPointerToWindowSubclass(const QualType& pType) {
return isDerivedFromWindow(recordDecl);
}
+bool VCLWidgets::VisitCXXRecordDecl(const CXXRecordDecl * recordDecl) {
+ if (ignoreLocation(recordDecl)) {
+ return true;
+ }
+ if (!recordDecl->isCompleteDefinition())
+ return true;
+ // check if this field is derived from Window
+ if (!isDerivedFromWindow(recordDecl)) {
+ return true;
+ }
+ bool foundVclPtr = false;
+ for(auto fieldDecl : recordDecl->fields()) {
+ if (fieldDecl->getType().getAsString().find("VclPtr")==0) {
+ foundVclPtr = true;
+ break;
+ }
+ }
+ if (!foundVclPtr) {
+ return true;
+ }
+ bool foundDispose = false;
+ for(auto methodDecl : recordDecl->methods()) {
+ if (methodDecl->isInstance() && methodDecl->param_size()==0 && methodDecl->getNameAsString() == "dispose") {
+ foundDispose = true;
+ break;
+ }
+ }
+ if (!foundDispose) {
+ report(
+ DiagnosticsEngine::Warning,
+ "vcl::Window subclass with VclPtr members should declare a dispose() method.",
+ recordDecl->getLocation())
+ << recordDecl->getSourceRange();
+ }
+ return true;
+}
+
+
bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
if (ignoreLocation(fieldDecl)) {
return true;
diff --git a/include/vcl/combobox.hxx b/include/vcl/combobox.hxx
index 8842477a6c40..86e6af49d2bb 100644
--- a/include/vcl/combobox.hxx
+++ b/include/vcl/combobox.hxx
@@ -91,6 +91,7 @@ protected:
bool IsDropDownBox() const { return mpFloatWin ? true : false; }
virtual void FillLayoutData() const SAL_OVERRIDE;
+ virtual void dispose() SAL_OVERRIDE;
public:
explicit ComboBox( vcl::Window* pParent, WinBits nStyle = 0 );
explicit ComboBox( vcl::Window* pParent, const ResId& );
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index bd418e8de2d1..ab498f1183b3 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -62,6 +62,7 @@ private:
protected:
using Window::ImplInit;
SAL_DLLPRIVATE void ImplInit( vcl::Window* pParent, WinBits nStyle );
+ virtual void dispose() SAL_OVERRIDE;
public:
SAL_DLLPRIVATE bool IsInClose() const { return mbInClose; }
diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx
index d11da2cc05d0..fde760953db0 100644
--- a/include/vcl/layout.hxx
+++ b/include/vcl/layout.hxx
@@ -620,6 +620,8 @@ private:
};
VclPtr<EventBoxHelper> m_aEventBoxHelper;
+protected:
+ virtual void dispose() SAL_OVERRIDE;
public:
VclEventBox(vcl::Window* pParent)
: VclBin(pParent)
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index d84797564a68..21877ecbaf99 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -78,6 +78,12 @@ ComboBox::~ComboBox()
delete mpBtn;
}
+void ComboBox::dispose()
+{
+ mpSubEdit.disposeAndClear();
+ Edit::dispose();
+}
+
void ComboBox::ImplInitComboBoxData()
{
mpSubEdit.disposeAndClear();
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index b5f7b5361f12..60aa87618f44 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -542,6 +542,13 @@ Dialog::~Dialog()
mpDialogImpl = NULL;
}
+void Dialog::dispose()
+{
+ mpActionArea.disposeAndClear();
+ mpContentArea.disposeAndClear();
+ SystemWindow::dispose();
+}
+
IMPL_LINK_NOARG(Dialog, ImplAsyncCloseHdl)
{
Close();
diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx
index 6a6c15408fe9..5fee1f0f1bd8 100644
--- a/vcl/source/window/layout.cxx
+++ b/vcl/source/window/layout.cxx
@@ -1878,6 +1878,12 @@ void VclEventBox::Command(const CommandEvent&)
//discard events by default to block them reaching children
}
+void VclEventBox::dispose()
+{
+ m_aEventBoxHelper.disposeAndClear();
+ VclBin::dispose();
+}
+
void VclSizeGroup::trigger_queue_resize()
{
//sufficient to trigger one widget to trigger all of them