static bool isQStringLiteralCandidate()

in src/checks/level2/qstring-allocations.cpp [402:465]


static bool isQStringLiteralCandidate(Stmt *s, ParentMap *map, const LangOptions &lo, const SourceManager &sm, int currentCall = 0)
{
    if (!s) {
        return false;
    }

    auto *memberExpr = dyn_cast<MemberExpr>(s);
    if (memberExpr) {
        return true;
    }

    auto *constructExpr = dyn_cast<CXXConstructExpr>(s);
    if (clazy::isOfClass(constructExpr, "QString")) {
        return true;
    }

    if (Utils::isAssignOperator(dyn_cast<CXXOperatorCallExpr>(s), "QString", "QLatin1String", lo)) {
        return true;
    }

    if (Utils::isAssignOperator(dyn_cast<CXXOperatorCallExpr>(s), "QString", "QString", lo)) {
        return true;
    }

    auto *callExpr = dyn_cast<CallExpr>(s);
    StringLiteral *literal = stringLiteralForCall(callExpr);
    auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(s);
    if (operatorCall && clazy::returnTypeName(operatorCall, lo) != "QTestData") {
        // QTest::newRow will static_assert when using QLatin1String
        // Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object
        // system");

        std::string className = clazy::classNameFor(operatorCall);
        if (className == "QString") {
            return false;
        }
        if (className.empty() && clazy::hasArgumentOfType(operatorCall->getDirectCallee(), "QString", lo)) {
            return false;
        }
    }

    // C++17 elides the QString constructor call in QString s = QString::fromLatin1("foo");
    if (currentCall > 0) {
        auto exprWithCleanups = dyn_cast<ExprWithCleanups>(s);
        if (exprWithCleanups) {
            if (auto bindTemp = dyn_cast<CXXBindTemporaryExpr>(exprWithCleanups->getSubExpr())) {
                if (dyn_cast<CallExpr>(bindTemp->getSubExpr()))
                    return true;
            }
        }
    }

    if (currentCall > 0 && callExpr) {
        auto *fDecl = callExpr->getDirectCallee();
        return !(fDecl && betterTakeQLatin1String(dyn_cast<CXXMethodDecl>(fDecl), literal));
    }

    if (currentCall == 0 || dyn_cast<ImplicitCastExpr>(s) || dyn_cast<CXXBindTemporaryExpr>(s)
        || dyn_cast<MaterializeTemporaryExpr>(s)) { // recurse over this cruft
        return isQStringLiteralCandidate(clazy::parent(map, s), map, lo, sm, currentCall + 1);
    }

    return false;
}