Fix issue 9712: False positive: Returning pointer to local variable when return line implicitly cast to return type (#2662)
This commit is contained in:
parent
084529575f
commit
bbe6157e16
|
@ -2977,11 +2977,47 @@ static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
|
||||||
return true;
|
return true;
|
||||||
if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
|
if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
|
||||||
return true;
|
return true;
|
||||||
|
if (vtParent->str() == vt->str())
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const Token* skipCVRefs(const Token* tok, const Token* endTok)
|
||||||
|
{
|
||||||
|
while(tok != endTok && Token::Match(tok, "const|volatile|auto|&|&&"))
|
||||||
|
tok = tok->next();
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const Token*, const Token*> y)
|
||||||
|
{
|
||||||
|
const Token* start1 = x.first;
|
||||||
|
const Token* start2 = y.first;
|
||||||
|
if (start1 == nullptr || start2 == nullptr)
|
||||||
|
return false;
|
||||||
|
while(start1 != x.second && start2 != y.second) {
|
||||||
|
const Token* tok1 = skipCVRefs(start1, x.second);
|
||||||
|
if (tok1 != start1) {
|
||||||
|
start1 = tok1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const Token* tok2 = skipCVRefs(start2, y.second);
|
||||||
|
if (tok2 != start2) {
|
||||||
|
start2 = tok2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (start1->str() != start2->str())
|
||||||
|
return true;
|
||||||
|
start1 = start1->next();
|
||||||
|
start2 = start2->next();
|
||||||
|
}
|
||||||
|
start1 = skipCVRefs(start1, x.second);
|
||||||
|
start2 = skipCVRefs(start2, y.second);
|
||||||
|
return !(start1 == x.second && start2 == y.second);
|
||||||
|
}
|
||||||
|
|
||||||
bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
|
bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
@ -2999,10 +3035,18 @@ bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
|
||||||
if (isLifetimeOwned(vt, vtParent))
|
if (isLifetimeOwned(vt, vtParent))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const Type *t = Token::typeOf(tok);
|
if (Token::Match(tok->astParent(), "return|(|{|%assign%")) {
|
||||||
const Type *parentT = Token::typeOf(tok->astParent());
|
const Type *t = Token::typeOf(tok);
|
||||||
if (t && parentT && t->classDef && parentT->classDef && t->classDef != parentT->classDef) {
|
const Type *parentT = Token::typeOf(tok->astParent());
|
||||||
return false;
|
if (t && parentT) {
|
||||||
|
if (t->classDef && parentT->classDef && t->classDef != parentT->classDef)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
std::pair<const Token*, const Token*> decl = Token::typeDecl(tok);
|
||||||
|
std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(tok->astParent());
|
||||||
|
if (isNotEqual(decl, parentdecl))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok->astParent()->tokAt(-3), "%var% . push_back|push_front|insert|push (") &&
|
} else if (Token::Match(tok->astParent()->tokAt(-3), "%var% . push_back|push_front|insert|push (") &&
|
||||||
astIsContainer(tok->astParent()->tokAt(-3))) {
|
astIsContainer(tok->astParent()->tokAt(-3))) {
|
||||||
|
|
|
@ -2320,6 +2320,13 @@ private:
|
||||||
" return &y.x[i];\n"
|
" return &y.x[i];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #9712
|
||||||
|
check("std::string f(const char *str) {\n"
|
||||||
|
" char value[256];\n"
|
||||||
|
" return value;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void danglingLifetimeFunction() {
|
void danglingLifetimeFunction() {
|
||||||
|
|
Loading…
Reference in New Issue