void ReturningDataFromTemporary::handleMemberCall()

in src/checks/level1/returning-data-from-temporary.cpp [74:137]


void ReturningDataFromTemporary::handleMemberCall(CXXMemberCallExpr *memberCall, bool onlyTemporaries)
{
    if (!memberCall) {
        return;
    }

    CXXMethodDecl *method = memberCall->getMethodDecl();
    if (!method) {
        return;
    }
    const auto methodName = method->getQualifiedNameAsString();

    if (methodName != "QByteArray::data" && methodName != "QByteArray::operator const char *" && methodName != "QByteArray::constData") {
        return;
    }

    Expr *obj = memberCall->getImplicitObjectArgument();
    Stmt *t = obj;
    DeclRefExpr *declRef = nullptr;
    CXXBindTemporaryExpr *temporaryExpr = nullptr;

    while (t) {
        if (dyn_cast<ImplicitCastExpr>(t) || dyn_cast<MaterializeTemporaryExpr>(t) || dyn_cast<CXXFunctionalCastExpr>(t)) {
            t = clazy::getFirstChild(t);
            continue;
        }

        if (!onlyTemporaries) {
            declRef = dyn_cast<DeclRefExpr>(t);
            if (declRef) {
                break;
            }
        }

        temporaryExpr = dyn_cast<CXXBindTemporaryExpr>(t);
        if (temporaryExpr) {
            break;
        }

        break;
    }

    if (!temporaryExpr && !declRef) {
        return;
    }

    if (declRef) {
        auto *varDecl = dyn_cast<VarDecl>(declRef->getDecl());
        if (!varDecl || varDecl->isStaticLocal() || clazy::valueIsConst(varDecl->getType())) {
            return;
        }

        QualType qt = varDecl->getType();
        if (qt.isNull() || qt->isReferenceType()) {
            return;
        }
    } else if (temporaryExpr) {
        if (clazy::valueIsConst(temporaryExpr->getType())) {
            return;
        }
    }

    emitWarning(memberCall, "Returning data of temporary QByteArray");
}