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;
}