vclwidget plugin: check for memcpy of VclPtr
Change-Id: I873d3efbb7b78d0efe5d586b378d024ee22ac77e
This commit is contained in:
@@ -44,8 +44,11 @@ public:
|
|||||||
|
|
||||||
bool VisitCXXDeleteExpr(const CXXDeleteExpr *);
|
bool VisitCXXDeleteExpr(const CXXDeleteExpr *);
|
||||||
|
|
||||||
|
bool VisitCallExpr(const CallExpr *);
|
||||||
|
bool VisitDeclRefExpr(const DeclRefExpr* pDeclRefExpr);
|
||||||
private:
|
private:
|
||||||
bool isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodDecl);
|
bool isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodDecl);
|
||||||
|
bool mbCheckingMemcpy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool startsWith(const std::string& s, const char* other)
|
static bool startsWith(const std::string& s, const char* other)
|
||||||
@@ -472,6 +475,111 @@ bool VCLWidgets::isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodD
|
|||||||
return true;
|
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");
|
loplugin::Plugin::Registration< VCLWidgets > X("vclwidgets");
|
||||||
|
Reference in New Issue
Block a user