Fix #11881 FP returnStdMoveLocal / Fix FP incorrectStringBooleanError / Support std::string::starts/ends_with() (#5347)
This commit is contained in:
parent
03b952d5eb
commit
725c431ecc
12
cfg/std.cfg
12
cfg/std.cfg
|
@ -6884,6 +6884,18 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- constexpr bool std::string::starts_with( std::basic_string_view<CharT,Traits> sv ) const noexcept; // since C++20 -->
|
||||
<!-- constexpr bool starts_with( CharT ch ) const noexcept; // since C++20 -->
|
||||
<!-- constexpr bool starts_with( const CharT* s ) const; // since C++20 -->
|
||||
<function name="std::string::starts_with,std::wstring::starts_with,std::string::ends_with,std::wstring::ends_with">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<returnValue type="bool"/>
|
||||
<const/>
|
||||
<arg nr="1" direction="in">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- size_type std::string::copy( CharT* dest, size_type count, size_type pos = 0) const; -->
|
||||
<!-- size_type std::wstring::copy( CharT* dest, size_type count, size_type pos = 0) const; -->
|
||||
<function name="std::string::copy,std::wstring::copy">
|
||||
|
|
|
@ -1477,19 +1477,6 @@ static bool astIsBoolLike(const Token* tok)
|
|||
return astIsBool(tok) || isUsedAsBool(tok);
|
||||
}
|
||||
|
||||
bool isBooleanFuncArg(const Token* tok) {
|
||||
if (tok->variable() && tok->variable()->valueType() && tok->variable()->valueType()->type == ValueType::BOOL) // skip trivial case: bool passed as bool
|
||||
return false;
|
||||
int argn{};
|
||||
const Token* ftok = getTokenArgumentFunction(tok, argn);
|
||||
if (!ftok)
|
||||
return false;
|
||||
std::vector<const Variable*> argvars = getArgumentVars(ftok, argn);
|
||||
if (argvars.size() != 1)
|
||||
return false;
|
||||
return !argvars[0]->isReference() && argvars[0]->valueType() && argvars[0]->valueType()->type == ValueType::BOOL;
|
||||
}
|
||||
|
||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
|
||||
{
|
||||
if (tok1 == nullptr && tok2 == nullptr)
|
||||
|
|
|
@ -256,11 +256,6 @@ const Token* isInLoopCondition(const Token* tok);
|
|||
*/
|
||||
CPPCHECKLIB bool isUsedAsBool(const Token* const tok, const Settings* settings = nullptr);
|
||||
|
||||
/**
|
||||
* Is token passed to a function taking a bool argument
|
||||
*/
|
||||
CPPCHECKLIB bool isBooleanFuncArg(const Token* tok);
|
||||
|
||||
/**
|
||||
* Are two conditions opposite
|
||||
* @param isNot do you want to know if cond1 is !cond2 or if cond1 and cond2 are non-overlapping. true: cond1==!cond2 false: cond1==true => cond2==false
|
||||
|
|
|
@ -673,7 +673,7 @@ void CheckFunctions::returnLocalStdMove()
|
|||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||
for (const Scope *scope : symbolDatabase->functionScopes) {
|
||||
// Expect return by-value
|
||||
if (Function::returnsReference(scope->function, true))
|
||||
if (Function::returnsReference(scope->function, /*unknown*/ true, /*includeRValueRef*/ true))
|
||||
continue;
|
||||
const auto rets = Function::findReturns(scope->function);
|
||||
for (const Token* ret : rets) {
|
||||
|
|
|
@ -288,13 +288,7 @@ void CheckString::checkIncorrectStringCompare()
|
|||
incorrectStringCompareError(tok->next(), "substr", end->strAt(1));
|
||||
}
|
||||
}
|
||||
} else if (Token::Match(tok, "&&|%oror%|( %str%|%char% &&|%oror%|)") && !Token::Match(tok, "( %str%|%char% )")) {
|
||||
incorrectStringBooleanError(tok->next(), tok->strAt(1));
|
||||
} else if (Token::Match(tok, "if|while ( %str%|%char% )") && !tok->tokAt(2)->getValue(0)) {
|
||||
incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2));
|
||||
} else if (tok->str() == "?" && Token::Match(tok->astOperand1(), "%str%|%char%")) {
|
||||
incorrectStringBooleanError(tok->astOperand1(), tok->astOperand1()->str());
|
||||
} else if (Token::Match(tok, "%str%") && isBooleanFuncArg(tok))
|
||||
} else if (Token::Match(tok, "%str%|%char%") && isUsedAsBool(tok))
|
||||
incorrectStringBooleanError(tok, tok->str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4503,6 +4503,11 @@ void stdstring()
|
|||
|
||||
// valid
|
||||
s.assign("a");
|
||||
|
||||
#ifdef __cpp_lib_starts_ends_with
|
||||
// cppcheck-suppress ignoredReturnValue
|
||||
s.starts_with("abc");
|
||||
#endif
|
||||
}
|
||||
|
||||
void stdvector()
|
||||
|
|
|
@ -1808,6 +1808,12 @@ private:
|
|||
" std::cout << p->msg;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("std::string&& f() {\n" // #11881
|
||||
" std::string s;\n"
|
||||
" return std::move(s);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void negativeMemoryAllocationSizeError() { // #389
|
||||
|
|
|
@ -735,7 +735,9 @@ private:
|
|||
" if('\\0'){}\n"
|
||||
" if(L'\\0'){}\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Conversion of char literal '\\0' to bool always evaluates to false.\n"
|
||||
"[test.cpp:3]: (warning) Conversion of char literal L'\\0' to bool always evaluates to false.\n",
|
||||
errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" if('\\0' || cond){}\n"
|
||||
|
@ -750,6 +752,22 @@ private:
|
|||
" f(\"abc\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) Conversion of string literal \"abc\" to bool always evaluates to true.\n", errout.str());
|
||||
|
||||
check("void g(bool);\n"
|
||||
" void f(std::map<std::string, std::vector<int>>&m) {\n"
|
||||
" if (m.count(\"abc\"))\n"
|
||||
" g(m[\"abc\"][0] ? true : false);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void g(bool b);\n"
|
||||
"void f() {\n"
|
||||
" g('\\0');\n"
|
||||
" g('a');\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Conversion of char literal '\\0' to bool always evaluates to false.\n"
|
||||
"[test.cpp:4]: (warning) Conversion of char literal 'a' to bool always evaluates to true.\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
void deadStrcmp() {
|
||||
|
|
Loading…
Reference in New Issue