summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-05-18 10:08:00 +0200
committerNoel Grandin <noel@peralex.com>2015-05-19 12:15:25 +0200
commit245142cef18d4670a52094165fb4e4aedbb75496 (patch)
tree65c9b5853a5031a1e7008a5c30a4c2ee5c961590 /compilerplugins
parent87a235ab55f2afb9999da7bcb2a508dd99b0de2a (diff)
vclwidget plugin: check for memcpy of VclPtr
Change-Id: I873d3efbb7b78d0efe5d586b378d024ee22ac77e
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/vclwidgets.cxx108
1 files changed, 108 insertions, 0 deletions
diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index 22d722cd7417..fd79241a7dcd 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");