diff --git a/src/checks/level1/README-qstring-left.md b/src/checks/level1/README-qstring-left.md index 5e60728..b4b53a9 100644 --- a/src/checks/level1/README-qstring-left.md +++ b/src/checks/level1/README-qstring-left.md @@ -1,4 +1,9 @@ # qstring-left -Finds places where you're using `QString::left(0)` instead of `QString::at(0)`. -The later form is cheaper. +Finds places where you're using `QString::left(1)` instead of `QString::at(0)`. +The later form is cheaper, as it doesn't deep-copy the string. + +There's however another difference between the two: `left(1)` will return an empty +string if the string is empty, while `QString::at(0)` will assert. So be sure +that the string can't be empty, or add a `if (!str.isEmpty()` guard, which is still +faster than calling `left()` for the cases which deep-copy. diff --git a/src/checks/level1/qstring-left.cpp b/src/checks/level1/qstring-left.cpp index 51d3f82..580d903 100644 --- a/src/checks/level1/qstring-left.cpp +++ b/src/checks/level1/qstring-left.cpp @@ -1,64 +1,64 @@ /* This file is part of the clazy static checker. Copyright (C) 2016 Sergio Martins This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "qstring-left.h" #include "Utils.h" #include "HierarchyUtils.h" #include "QtUtils.h" #include "TypeUtils.h" #include "StringUtils.h" #include "checkmanager.h" #include using namespace clang; using namespace std; QStringLeft::QStringLeft(const std::string &name, const clang::CompilerInstance &ci) : CheckBase(name, ci) { } void QStringLeft::VisitStmt(clang::Stmt *stmt) { auto memberCall = dyn_cast(stmt); if (!memberCall || StringUtils::qualifiedMethodName(memberCall) != "QString::left") return; if (memberCall->getNumArgs() == 0) // Doesn't happen return; Expr *firstArg = memberCall->getArg(0); auto lt = firstArg ? dyn_cast(firstArg) : nullptr; if (lt) { const auto value = lt->getValue(); if (value == 0) { emitWarning(stmt, "QString::left(0) returns an empty string"); } else if (value == 1){ - emitWarning(stmt, "Use QString::at(0) instead of QString::left(1)"); + emitWarning(stmt, "Use QString::at(0) instead of QString::left(1) to avoid temporary allocations (just be sure the string isn't empty)."); } } } REGISTER_CHECK_WITH_FLAGS("qstring-left", QStringLeft, CheckLevel1) diff --git a/tests/qstring-left/main.cpp.expected b/tests/qstring-left/main.cpp.expected index b1ae352..f46ff9d 100644 --- a/tests/qstring-left/main.cpp.expected +++ b/tests/qstring-left/main.cpp.expected @@ -1,2 +1,2 @@ qstring-left/main.cpp:6:14: warning: QString::left(0) returns an empty string [-Wclazy-qstring-left] -qstring-left/main.cpp:7:9: warning: Use QString::at(0) instead of QString::left(1) [-Wclazy-qstring-left] +qstring-left/main.cpp:7:9: warning: Use QString::at(0) instead of QString::left(1) to avoid temporary allocations (just be sure the string isn't empty). [-Wclazy-qstring-left]