in src/checks/level2/qstring-allocations.cpp [644:700]
void QStringAllocations::VisitFromLatin1OrUtf8(Stmt *stmt)
{
auto *callExpr = dyn_cast<CallExpr>(stmt);
if (!callExpr) {
return;
}
FunctionDecl *functionDecl = callExpr->getDirectCallee();
if (!clazy::functionIsOneOf(functionDecl, {"fromLatin1", "fromUtf8"})) {
return;
}
auto *methodDecl = dyn_cast<CXXMethodDecl>(functionDecl);
if (!clazy::isOfClass(methodDecl, "QString")) {
return;
}
bool isKnownLiteralOverload = false;
for (auto e : Utils::functionParameters(functionDecl)) {
if (e->getType().getAsString(lo()) == "QByteArrayView") {
isKnownLiteralOverload = true;
}
}
if (!isKnownLiteralOverload && (!Utils::callHasDefaultArguments(callExpr) || !hasCharPtrArgument(functionDecl, 2))) { // QString::fromLatin1("foo", 1) is ok
return;
}
if (!containsStringLiteralNoCallExpr(callExpr)) {
return;
}
if (!isOptionSet("no-msvc-compat")) {
StringLiteral *lt = stringLiteralForCall(callExpr);
if (lt && lt->getNumConcatenated() > 1) {
return; // Nothing to do here, MSVC doesn't like it
}
}
std::vector<ConditionalOperator *> ternaries;
clazy::getChilds(callExpr, ternaries); // In Qt5 it is always 2 levels down, but in Qt6 more
if (!ternaries.empty()) {
auto *ternary = ternaries[0];
if (Utils::ternaryOperatorIsOfStringLiteral(ternary)) {
maybeEmitWarning(stmt->getBeginLoc(), std::string("QString::fromLatin1() being passed a literal"));
}
return;
}
const FromFunction fromFunction = clazy::name(functionDecl) == "fromLatin1" ? FromLatin1 : FromUtf8;
const std::vector<FixItHint> fixits = fixItReplaceFromLatin1OrFromUtf8(callExpr, fromFunction);
if (clazy::name(functionDecl) == "fromLatin1") {
maybeEmitWarning(stmt->getBeginLoc(), std::string("QString::fromLatin1() being passed a literal"), fixits);
} else {
maybeEmitWarning(stmt->getBeginLoc(), std::string("QString::fromUtf8() being passed a literal"), fixits);
}
}