in src/checks/level1/connect-3arg-lambda.cpp [31:124]
void Connect3ArgLambda::VisitStmt(clang::Stmt *stmt)
{
auto *callExpr = dyn_cast<CallExpr>(stmt);
if (!callExpr) {
return;
}
FunctionDecl *fdecl = callExpr->getDirectCallee();
if (!fdecl) {
return;
}
const uint numParams = fdecl->getNumParams();
if (numParams != 2 && numParams != 3) {
return;
}
std::string qualifiedName = fdecl->getQualifiedNameAsString();
if (qualifiedName == "QTimer::singleShot") {
processQTimer(fdecl, stmt);
return;
}
if (qualifiedName == "QMenu::addAction") {
processQMenu(fdecl, stmt);
return;
}
if (qualifiedName == "QWidget::addAction") {
processWidget(fdecl, stmt);
return;
}
if (numParams != 3 || !clazy::isConnect(fdecl)) {
return;
}
auto *arg3 = callExpr->getArg(2);
auto *lambda = clang::dyn_cast_or_null<LambdaExpr>(arg3);
if (!lambda) {
lambda = clazy::getFirstChildOfType2<LambdaExpr>(arg3);
if (!lambda) {
return;
}
}
DeclRefExpr *senderDeclRef = nullptr;
const MemberExpr *senderMemberExpr = nullptr;
Stmt *s = callExpr->getArg(0);
while (s) {
if ((senderDeclRef = dyn_cast<DeclRefExpr>(s))) {
break;
}
if ((senderMemberExpr = dyn_cast<MemberExpr>(s))) {
break;
}
s = clazy::getFirstChild(s);
}
// The sender can be: this
const auto *senderThis = clazy::unpeal<CXXThisExpr>(callExpr->getArg(0), clazy::IgnoreImplicitCasts);
// The variables used inside the lambda
auto declrefs = clazy::getStatements<DeclRefExpr>(lambda->getBody());
const ValueDecl *senderDecl = senderDeclRef ? senderDeclRef->getDecl() : nullptr;
// We'll only warn if the lambda is dereferencing another QObject (besides the sender)
bool found = false;
for (auto *declref : declrefs) {
ValueDecl *decl = declref->getDecl();
if (decl == senderDecl) {
continue; // It's the sender, continue.
}
if (clazy::isQObject(decl->getType())) {
found = true;
break;
}
}
if (!found) {
auto thisexprs = clazy::getStatements<CXXThisExpr>(lambda->getBody());
if (!thisexprs.empty() && !senderThis) {
found = true;
}
}
if (found) {
emitWarning(stmt, "Pass a context object as 3rd connect parameter");
}
}