clang plugin: check return types for vcl::Window* that should be wrapped
Change-Id: I7121c1727d1374a955fbccb6554aede468d4977f
This commit is contained in:
committed by
Michael Meeks
parent
e1d413b132
commit
a6acccc6d2
@@ -37,6 +37,7 @@ public:
|
|||||||
|
|
||||||
bool VisitVarDecl( const VarDecl* var );
|
bool VisitVarDecl( const VarDecl* var );
|
||||||
|
|
||||||
|
bool VisitFunctionDecl( const FunctionDecl* var );
|
||||||
};
|
};
|
||||||
|
|
||||||
bool BaseCheckNotWindowSubclass(const CXXRecordDecl *BaseDefinition, void *) {
|
bool BaseCheckNotWindowSubclass(const CXXRecordDecl *BaseDefinition, void *) {
|
||||||
@@ -60,6 +61,21 @@ bool isDerivedFromWindow(const CXXRecordDecl *decl) {
|
|||||||
return false;
|
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) {
|
bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
|
||||||
if (ignoreLocation(fieldDecl)) {
|
if (ignoreLocation(fieldDecl)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -67,6 +83,15 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) {
|
|||||||
if (fieldDecl->isBitField()) {
|
if (fieldDecl->isBitField()) {
|
||||||
return true;
|
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>();
|
const RecordType *recordType = fieldDecl->getType()->getAs<RecordType>();
|
||||||
if (recordType == nullptr) {
|
if (recordType == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
@@ -92,18 +117,8 @@ bool VCLWidgets::VisitParmVarDecl(ParmVarDecl const * pvDecl) {
|
|||||||
if (ignoreLocation(pvDecl)) {
|
if (ignoreLocation(pvDecl)) {
|
||||||
return true;
|
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
|
// check if this parameter is derived from Window
|
||||||
if (isDerivedFromWindow(recordDecl)) {
|
if (isPointerToWindowSubclass(pvDecl->getType())) {
|
||||||
report(
|
report(
|
||||||
DiagnosticsEngine::Remark,
|
DiagnosticsEngine::Remark,
|
||||||
"vcl::Window subclass passed as a pointer parameter, should be wrapped in VclPtr.",
|
"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())
|
if (!varDecl->isLocalVarDecl())
|
||||||
return true;
|
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
|
// check if this variables type is derived from Window
|
||||||
if (isDerivedFromWindow(recordDecl)) {
|
if (isPointerToWindowSubclass(varDecl->getType())) {
|
||||||
report(
|
report(
|
||||||
DiagnosticsEngine::Remark,
|
DiagnosticsEngine::Remark,
|
||||||
"vcl::Window subclass declared as a pointer var, should be wrapped in VclPtr.",
|
"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;
|
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");
|
loplugin::Plugin::Registration< VCLWidgets > X("vclwidgets");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user