Fix FPs in lifetime checker
This fixes several FPs in the lifetime checker. It also fixes issue [8846](https://trac.cppcheck.net/ticket/8846): ```cpp int * f(int a[]) { return a; } ```
This commit is contained in:
parent
8e465d5963
commit
7ef119cbfc
|
@ -76,6 +76,16 @@ bool astIsPointer(const Token *tok)
|
|||
return tok && tok->valueType() && tok->valueType()->pointer;
|
||||
}
|
||||
|
||||
bool astIsIterator(const Token *tok)
|
||||
{
|
||||
return tok && tok->valueType() && tok->valueType()->type == ValueType::Type::ITERATOR;
|
||||
}
|
||||
|
||||
bool astIsContainer(const Token *tok)
|
||||
{
|
||||
return tok && tok->valueType() && tok->valueType()->type == ValueType::Type::CONTAINER;
|
||||
}
|
||||
|
||||
std::string astCanonicalType(const Token *expr)
|
||||
{
|
||||
if (!expr)
|
||||
|
|
|
@ -45,6 +45,10 @@ bool astIsBool(const Token *tok);
|
|||
|
||||
bool astIsPointer(const Token *tok);
|
||||
|
||||
bool astIsIterator(const Token *tok);
|
||||
|
||||
bool astIsContainer(const Token *tok);
|
||||
|
||||
/**
|
||||
* Get canonical type of expression. const/static/etc are not included and neither *&.
|
||||
* For example:
|
||||
|
|
|
@ -579,6 +579,13 @@ static bool isDeadScope(const Token * tok, const Scope * scope)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int getPointerDepth(const Token *tok)
|
||||
{
|
||||
if (!tok)
|
||||
return 0;
|
||||
return tok->valueType() ? tok->valueType()->pointer : 0;
|
||||
}
|
||||
|
||||
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
|
||||
{
|
||||
if (!start)
|
||||
|
@ -597,7 +604,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
|
|||
if (val.tokvalue == tok)
|
||||
continue;
|
||||
if (Token::Match(tok->astParent(), "return|throw")) {
|
||||
if (isInScope(val.tokvalue, scope)) {
|
||||
if (getPointerDepth(tok) >= getPointerDepth(val.tokvalue) && isInScope(val.tokvalue, scope)) {
|
||||
errorReturnDanglingLifetime(tok, &val);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -431,9 +431,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
|
|||
}
|
||||
|
||||
if (value.isLifetimeValue()) {
|
||||
if (value.lifetimeKind == ValueFlow::Value::Iterator && parent->isArithmeticalOp()) {
|
||||
if (value.lifetimeKind == ValueFlow::Value::Iterator && astIsIterator(parent)) {
|
||||
setTokenValue(parent,value,settings);
|
||||
} else if (astIsPointer(tok) && astIsPointer(parent) && (parent->isArithmeticalOp() || Token::Match(parent, "( %type%"))) {
|
||||
} else if (astIsPointer(tok) && astIsPointer(parent) &&
|
||||
(parent->isArithmeticalOp() || Token::Match(parent, "( %type%"))) {
|
||||
setTokenValue(parent,value,settings);
|
||||
}
|
||||
return;
|
||||
|
@ -2763,7 +2764,8 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
|
|||
const Variable * var = getLifetimeVariable(tok, errorPath);
|
||||
if (!var)
|
||||
continue;
|
||||
if (var->isArray() && tok->astParent() && (astIsPointer(tok->astParent()) || Token::Match(tok->astParent(), "%assign%|return"))) {
|
||||
if (var->isArray() && !var->isArgument() && tok->astParent() &&
|
||||
(astIsPointer(tok->astParent()) || Token::Match(tok->astParent(), "%assign%|return"))) {
|
||||
errorPath.emplace_back(tok, "Array decayed to pointer here.");
|
||||
|
||||
ValueFlow::Value value;
|
||||
|
|
|
@ -1192,6 +1192,13 @@ private:
|
|||
"}");
|
||||
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int * foo(int * y)\n"
|
||||
"{\n"
|
||||
" return y;\n"
|
||||
"}");
|
||||
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void testconstructor() { // Ticket #5478 - crash while checking a constructor
|
||||
|
@ -1359,6 +1366,27 @@ private:
|
|||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("std::vector<int>::iterator f(std::vector<int>* v) {\n"
|
||||
" return v->begin();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("std::vector<int>::iterator f(std::vector<int>* v) {\n"
|
||||
" std::vector<int>* v = new std::vector<int>();\n"
|
||||
" return v->begin();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int f(std::vector<int> v) {\n"
|
||||
" return *v.begin();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int f(std::vector<int> v) {\n"
|
||||
" return v.end() - v.begin();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("auto g() {\n"
|
||||
" std::vector<char> v;\n"
|
||||
" return {v, [v]() { return v.data(); }};\n"
|
||||
|
@ -1394,6 +1422,11 @@ private:
|
|||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int * f(int a[]) {\n"
|
||||
" return a;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Make sure we dont hang
|
||||
check("struct A;\n"
|
||||
"void f() {\n"
|
||||
|
|
Loading…
Reference in New Issue