in src/checks/level2/base-class-event.cpp [29:77]
void BaseClassEvent::VisitDecl(Decl *decl)
{
auto *method = dyn_cast<CXXMethodDecl>(decl);
if (!method || !method->hasBody() || !method->isThisDeclarationADefinition()) {
return;
}
const std::string methodName = method->getNameAsString();
const bool isEvent = methodName == "event";
const bool isEventFilter = isEvent ? false : methodName == "eventFilter";
if (!isEvent && !isEventFilter) {
return;
}
CXXRecordDecl *classDecl = method->getParent();
if (!clazy::isQObject(classDecl)) {
return;
}
const std::string className = classDecl->getQualifiedNameAsString();
if (clazy::contains(std::array<StringRef, 2>({"QObject", "QWidget"}), className)) {
return;
}
CXXRecordDecl *baseClass = clazy::getQObjectBaseClass(classDecl);
const std::string baseClassName = baseClass ? baseClass->getQualifiedNameAsString() : std::string("BaseClass");
if (isEventFilter && clazy::contains(std::array<StringRef, 2>({"QObject", "QWidget"}), baseClassName)) {
// This is fine, QObject and QWidget eventFilter() don't do anything
return;
}
Stmt *body = method->getBody();
std::vector<ReturnStmt *> returns;
clazy::getChilds<ReturnStmt>(body, /*by-ref*/ returns);
for (ReturnStmt *returnStmt : returns) {
Stmt *maybeBoolExpr = clazy::childAt(returnStmt, 0);
if (!maybeBoolExpr) {
continue;
}
auto *boolExpr = dyn_cast<CXXBoolLiteralExpr>(maybeBoolExpr);
if (!boolExpr || boolExpr->getValue()) { // if getValue() is true that's a return true, which is fine
continue;
}
emitWarning(returnStmt->getBeginLoc(), "Return " + baseClassName + "::" + methodName + "() instead of false");
}
}