[Libreoffice-commits] core.git: Branch 'feature/vclref' - 2 commits - compilerplugins/clang include/vcl vcl/source

Noel Grandin noel at peralex.com
Thu Jan 8 04:11:09 PST 2015


 compilerplugins/clang/vclwidgets.cxx |  106 ++++++++++++++++++++++++++++-------
 include/vcl/combobox.hxx             |    1 
 include/vcl/dialog.hxx               |    1 
 include/vcl/layout.hxx               |    2 
 vcl/source/control/combobox.cxx      |    6 +
 vcl/source/window/dialog.cxx         |    7 ++
 vcl/source/window/layout.cxx         |    6 +
 7 files changed, 108 insertions(+), 21 deletions(-)

New commits:
commit 398470ef5de2d88147ce3226890cee9809e4bb82
Author: Noel Grandin <noel at peralex.com>
Date:   Thu Jan 8 14:09:13 2015 +0200

    compilerplugin: check that necessary Window subclasses have a dispose method
    
    i.e. the ones that declare any VclPtr fields
    
    Change-Id: I7adfc3b3b190a2ede60bfccd08f85a269fae33ca

diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index aa2af7f..896cd3f 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 99db232..62f0326 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 832c239..cf1c6ff 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -63,6 +63,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 7df6fe0..8f57140 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 bba84b6..39a3164 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 6375621..4526f8a 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -545,6 +545,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 64688e5..85694cb 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
commit eb427a03a1cc1596786dcc03ef4e723da2dee0b2
Author: Noel Grandin <noel at peralex.com>
Date:   Thu Jan 8 13:30:36 2015 +0200

    clang plugin: check return types for vcl::Window* that should be wrapped
    
    Change-Id: I7121c1727d1374a955fbccb6554aede468d4977f

diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index db4093f..aa2af7f 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -37,6 +37,7 @@ public:
 
     bool VisitVarDecl( const VarDecl* var );
 
+    bool VisitFunctionDecl( const FunctionDecl* var );
 };
 
 bool BaseCheckNotWindowSubclass(const CXXRecordDecl *BaseDefinition, void *) {
@@ -60,6 +61,21 @@ bool isDerivedFromWindow(const CXXRecordDecl *decl) {
     return false;
 }
 
+bool isPointerToWindowSubclass(const QualType& pType) {
+    if (!pType->isPointerType())
+        return false;
+    QualType pointeeType = pType->getPointeeType();
+    const RecordType *recordType = pointeeType->getAs<RecordType>();
+    if (recordType == nullptr) {
+        return false;
+    }
+    const CXXRecordDecl *recordDecl = dyn_cast<CXXRecordDecl>(recordType->getDecl());
+    if (recordDecl == nullptr) {
+        return false;
+    }
+    return isDerivedFromWindow(recordDecl);
+}
+
 bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
     if (ignoreLocation(fieldDecl)) {
         return true;
@@ -67,6 +83,15 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
     if (fieldDecl->isBitField()) {
         return true;
     }
+    if (isPointerToWindowSubclass(fieldDecl->getType())) {
+        report(
+            DiagnosticsEngine::Remark,
+            "vcl::Window subclass declared as a pointer field, should be wrapped in VclPtr.",
+            fieldDecl->getLocation())
+          << fieldDecl->getSourceRange();
+        return true;
+    }
+
     const RecordType *recordType = fieldDecl->getType()->getAs<RecordType>();
     if (recordType == nullptr) {
         return true;
@@ -92,18 +117,8 @@ bool VCLWidgets::VisitParmVarDecl(ParmVarDecl const * pvDecl) {
     if (ignoreLocation(pvDecl)) {
         return true;
     }
-    if (!pvDecl->getType()->isPointerType())
-        return true;
-    QualType pointeeType = pvDecl->getType()->getPointeeType();
-    const RecordType *recordType = pointeeType->getAs<RecordType>();
-    if (recordType == nullptr)
-        return true;
-    const CXXRecordDecl *recordDecl = dyn_cast<CXXRecordDecl>(recordType->getDecl());
-    if (recordDecl == nullptr)
-        return true;
-
     // check if this parameter is derived from Window
-    if (isDerivedFromWindow(recordDecl)) {
+    if (isPointerToWindowSubclass(pvDecl->getType())) {
         report(
             DiagnosticsEngine::Remark,
             "vcl::Window subclass passed as a pointer parameter, should be wrapped in VclPtr.",
@@ -120,18 +135,9 @@ bool VCLWidgets::VisitVarDecl( const VarDecl* varDecl )
     }
     if (!varDecl->isLocalVarDecl())
         return true;
-    if (!varDecl->getType()->isPointerType())
-        return true;
-    QualType pointeeType = varDecl->getType()->getPointeeType();
-    const RecordType *recordType = pointeeType->getAs<RecordType>();
-    if (recordType == nullptr)
-        return true;
-    const CXXRecordDecl *recordDecl = dyn_cast<CXXRecordDecl>(recordType->getDecl());
-    if (recordDecl == nullptr)
-        return true;
 
     // check if this variables type is derived from Window
-    if (isDerivedFromWindow(recordDecl)) {
+    if (isPointerToWindowSubclass(varDecl->getType())) {
         report(
             DiagnosticsEngine::Remark,
             "vcl::Window subclass declared as a pointer var, should be wrapped in VclPtr.",
@@ -142,6 +148,24 @@ bool VCLWidgets::VisitVarDecl( const VarDecl* varDecl )
     return true;
 }
 
+bool VCLWidgets::VisitFunctionDecl( const FunctionDecl* functionDecl )
+{
+    if (ignoreLocation(functionDecl)) {
+        return true;
+    }
+    QualType t1 { compat::getReturnType(*functionDecl) };
+    // check if this variables type is derived from Window
+    if (isPointerToWindowSubclass(t1)) {
+        report(
+            DiagnosticsEngine::Remark,
+            "vcl::Window subclass declared as a return type from a method/function, should be wrapped in VclPtr.",
+            functionDecl->getLocation())
+          << functionDecl->getSourceRange();
+    }
+    return true;
+}
+
+
 loplugin::Plugin::Registration< VCLWidgets > X("vclwidgets");
 
 }


More information about the Libreoffice-commits mailing list