[Libreoffice-commits] core.git: compilerplugins/clang

Noel Grandin noel at peralex.com
Tue May 19 03:16:18 PDT 2015


 compilerplugins/clang/vclwidgets.cxx |  108 +++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

New commits:
commit 245142cef18d4670a52094165fb4e4aedbb75496
Author: Noel Grandin <noel at peralex.com>
Date:   Mon May 18 10:08:00 2015 +0200

    vclwidget plugin: check for memcpy of VclPtr
    
    Change-Id: I873d3efbb7b78d0efe5d586b378d024ee22ac77e

diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index 22d722c..fd79241 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -44,8 +44,11 @@ public:
 
     bool VisitCXXDeleteExpr(const CXXDeleteExpr *);
 
+    bool VisitCallExpr(const CallExpr *);
+    bool VisitDeclRefExpr(const DeclRefExpr* pDeclRefExpr);
 private:
     bool isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodDecl);
+    bool mbCheckingMemcpy = false;
 };
 
 static bool startsWith(const std::string& s, const char* other)
@@ -472,6 +475,111 @@ bool VCLWidgets::isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodD
     return true;
 }
 
+bool containsVclPtr(const Type* pType0);
+
+bool containsVclPtr(const QualType& qType) {
+    auto t = qType->getAs<RecordType>();
+    if (t != nullptr) {
+        auto d = dyn_cast<ClassTemplateSpecializationDecl>(t->getDecl());
+        if (d != nullptr) {
+            std::string name(d->getQualifiedNameAsString());
+            if (name == "ScopedVclPtr" || name == "ScopedVclPtrInstance"
+                || name == "VclPtr" || name == "VclPtrInstance")
+            {
+                return true;
+            }
+        }
+    }
+    return containsVclPtr(qType.getTypePtr());
+}
+
+bool containsVclPtr(const Type* pType0) {
+    if (!pType0)
+        return false;
+    const Type* pType = pType0->getUnqualifiedDesugaredType();
+    if (!pType)
+        return false;
+    if (pType->isPointerType()) {
+        return false;
+    } else if (pType->isArrayType()) {
+        const ArrayType* pArrayType = dyn_cast<ArrayType>(pType);
+        QualType elementType = pArrayType->getElementType();
+        return containsVclPtr(elementType);
+    } else {
+        const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl();
+        if (pRecordDecl)
+        {
+            std::string name(pRecordDecl->getQualifiedNameAsString());
+            if (name == "ScopedVclPtr" || name == "ScopedVclPtrInstance"
+                || name == "VclPtr" || name == "VclPtrInstance")
+            {
+                return true;
+            }
+            for(auto fieldDecl = pRecordDecl->field_begin();
+                fieldDecl != pRecordDecl->field_end(); ++fieldDecl)
+            {
+                const RecordType *pFieldRecordType = fieldDecl->getType()->getAs<RecordType>();
+                if (pFieldRecordType && containsVclPtr(pFieldRecordType)) {
+                    return true;
+                }
+            }
+            for(auto baseSpecifier = pRecordDecl->bases_begin();
+                baseSpecifier != pRecordDecl->bases_end(); ++baseSpecifier)
+            {
+                const RecordType *pFieldRecordType = baseSpecifier->getType()->getAs<RecordType>();
+                if (pFieldRecordType && containsVclPtr(pFieldRecordType)) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool VCLWidgets::VisitCallExpr(const CallExpr* pCallExpr)
+{
+    if (ignoreLocation(pCallExpr)) {
+        return true;
+    }
+    FunctionDecl const * fdecl = pCallExpr->getDirectCallee();
+    if (fdecl == nullptr) {
+        return true;
+    }
+    std::string qname { fdecl->getQualifiedNameAsString() };
+    if (qname.find("memcpy") == std::string::npos
+         && qname.find("bcopy") == std::string::npos
+         && qname.find("memmove") == std::string::npos
+         && qname.find("rtl_copy") == std::string::npos) {
+        return true;
+    }
+    mbCheckingMemcpy = true;
+    Stmt * pStmt = const_cast<Stmt*>(static_cast<const Stmt*>(pCallExpr->getArg(0)));
+    TraverseStmt(pStmt);
+    mbCheckingMemcpy = false;
+    return true;
+}
+
+bool VCLWidgets::VisitDeclRefExpr(const DeclRefExpr* pDeclRefExpr)
+{
+    if (!mbCheckingMemcpy) {
+        return true;
+    }
+    if (ignoreLocation(pDeclRefExpr)) {
+        return true;
+    }
+    QualType pType = pDeclRefExpr->getDecl()->getType();
+    if (pType->isPointerType()) {
+        pType = pType->getPointeeType();
+    }
+    if (!containsVclPtr(pType)) {
+        return true;
+    }
+    report(
+        DiagnosticsEngine::Warning,
+        "Calling memcpy on a type which contains a VclPtr",
+        pDeclRefExpr->getExprLoc());
+    return true;
+}
 
 
 loplugin::Plugin::Registration< VCLWidgets > X("vclwidgets");


More information about the Libreoffice-commits mailing list