Merge pull request #2791 from pfultz2/known-empty-container-constructor-modified
Fix issue 9869: False positive: knownEmptyContainer when passed to constructor
This commit is contained in:
commit
43d643184e
|
@ -1386,31 +1386,33 @@ const Token * getTokenArgumentFunction(const Token * tok, int& argn)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Variable* getArgumentVar(const Token* tok, int argnr)
|
static std::vector<const Variable*> getArgumentVars(const Token* tok, int argnr)
|
||||||
{
|
{
|
||||||
|
std::vector<const Variable*> result;
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return nullptr;
|
return result;
|
||||||
if (tok->function())
|
if (tok->function())
|
||||||
return tok->function()->getArgumentVar(argnr);
|
return {tok->function()->getArgumentVar(argnr)};
|
||||||
if (Token::Match(tok->previous(), "%type% (|{") || tok->variable()) {
|
if (Token::Match(tok->previous(), "%type% (|{") || tok->variable()) {
|
||||||
|
const bool constructor = tok->variable() && tok->variable()->nameToken() == tok;
|
||||||
const Type* type = Token::typeOf(tok);
|
const Type* type = Token::typeOf(tok);
|
||||||
if (!type)
|
if (!type)
|
||||||
return nullptr;
|
return result;
|
||||||
const Scope* typeScope = type->classScope;
|
const Scope* typeScope = type->classScope;
|
||||||
if (!typeScope)
|
if (!typeScope)
|
||||||
return nullptr;
|
return result;
|
||||||
const int argCount = numberOfArguments(tok);
|
const int argCount = numberOfArguments(tok);
|
||||||
for (const Function &function : typeScope->functionList) {
|
for (const Function &function : typeScope->functionList) {
|
||||||
if (function.isConstructor())
|
|
||||||
continue;
|
|
||||||
if (function.argCount() < argCount)
|
if (function.argCount() < argCount)
|
||||||
continue;
|
continue;
|
||||||
if (!Token::simpleMatch(function.token, "operator()"))
|
if (constructor && !function.isConstructor())
|
||||||
continue;
|
continue;
|
||||||
return function.getArgumentVar(argnr);
|
if (!constructor && !Token::simpleMatch(function.token, "operator()"))
|
||||||
|
continue;
|
||||||
|
result.push_back(function.getArgumentVar(argnr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCPPCastKeyword(const Token* tok)
|
static bool isCPPCastKeyword(const Token* tok)
|
||||||
|
@ -1444,26 +1446,6 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
|
||||||
parenTok = parenTok->link()->next();
|
parenTok = parenTok->link()->next();
|
||||||
const bool possiblyPassedByReference = (parenTok->next() == tok1 || Token::Match(tok1->previous(), ", %name% [,)}]"));
|
const bool possiblyPassedByReference = (parenTok->next() == tok1 || Token::Match(tok1->previous(), ", %name% [,)}]"));
|
||||||
|
|
||||||
// Constructor call
|
|
||||||
if (tok->variable() && tok->variable()->nameToken() == tok) {
|
|
||||||
// Find constructor..
|
|
||||||
const int argCount = numberOfArguments(tok);
|
|
||||||
const Scope *typeScope = tok->variable()->typeScope();
|
|
||||||
if (typeScope) {
|
|
||||||
for (const Function &function : typeScope->functionList) {
|
|
||||||
if (!function.isConstructor() || function.argCount() < argCount)
|
|
||||||
continue;
|
|
||||||
const Variable *arg = function.getArgumentVar(argnr);
|
|
||||||
if (arg && arg->isReference() && !arg->isConst())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (inconclusive)
|
|
||||||
*inconclusive = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tok->function() && !tok->variable() && Token::Match(tok, "%name%")) {
|
if (!tok->function() && !tok->variable() && Token::Match(tok, "%name%")) {
|
||||||
// Check if direction (in, out, inout) is specified in the library configuration and use that
|
// Check if direction (in, out, inout) is specified in the library configuration and use that
|
||||||
if (!addressOf && settings) {
|
if (!addressOf && settings) {
|
||||||
|
@ -1494,22 +1476,26 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Variable *arg = getArgumentVar(tok, argnr);
|
std::vector<const Variable*> args = getArgumentVars(tok, argnr);
|
||||||
if (!arg) {
|
bool conclusive = false;
|
||||||
if (inconclusive)
|
for(const Variable *arg:args) {
|
||||||
*inconclusive = true;
|
if (!arg)
|
||||||
return false;
|
continue;
|
||||||
}
|
conclusive = true;
|
||||||
|
if (addressOf || (indirect > 0 && arg->isPointer())) {
|
||||||
if (addressOf || (indirect > 0 && arg->isPointer())) {
|
if (!arg->isConst())
|
||||||
if (!arg->isConst())
|
return true;
|
||||||
return true;
|
// If const is applied to the pointer, then the value can still be modified
|
||||||
// If const is applied to the pointer, then the value can still be modified
|
if (Token::simpleMatch(arg->typeEndToken(), "* const"))
|
||||||
if (Token::simpleMatch(arg->typeEndToken(), "* const"))
|
return true;
|
||||||
|
}
|
||||||
|
if (!arg->isConst() && arg->isReference())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!conclusive && inconclusive) {
|
||||||
return !arg->isConst() && arg->isReference();
|
*inconclusive = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, bool cpp, int depth)
|
bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, bool cpp, int depth)
|
||||||
|
|
|
@ -4701,6 +4701,18 @@ private:
|
||||||
"}\n",
|
"}\n",
|
||||||
true);
|
true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct A {\n"
|
||||||
|
" explicit A(std::vector<int>*);\n"
|
||||||
|
"};\n"
|
||||||
|
"A f() {\n"
|
||||||
|
" std::vector<int> v;\n"
|
||||||
|
" A a(&v);\n"
|
||||||
|
" for(auto&& x:v) {}\n"
|
||||||
|
" return a;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkMutexes() {
|
void checkMutexes() {
|
||||||
|
|
Loading…
Reference in New Issue