Fix FPs
This commit is contained in:
parent
264c0cae8b
commit
c7a5d3c5f1
|
@ -473,6 +473,25 @@ static bool isEscapedReference(const Variable* var)
|
||||||
return !isTemporary(true, vartok, nullptr, false);
|
return !isTemporary(true, vartok, nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isDanglingSubFunction(const Token* tokvalue, const Token* tok)
|
||||||
|
{
|
||||||
|
if (!tokvalue)
|
||||||
|
return false;
|
||||||
|
const Variable* var = tokvalue->variable();
|
||||||
|
if (!var->isLocal())
|
||||||
|
return false;
|
||||||
|
Function* f = Scope::nestedInFunction(tok->scope());
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
const Token* parent = tokvalue->astParent();
|
||||||
|
while(parent && !Token::Match(parent->previous(), "%name% (")) {
|
||||||
|
parent = parent->astParent();
|
||||||
|
}
|
||||||
|
if (!Token::simpleMatch(parent, "("))
|
||||||
|
return false;
|
||||||
|
return exprDependsOnThis(parent);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
|
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
|
||||||
{
|
{
|
||||||
if (!start)
|
if (!start)
|
||||||
|
@ -537,7 +556,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tokvalue->variable() && (isInScope(tokvalue->variable()->nameToken(), tok->scope()) ||
|
if (tokvalue->variable() && (isInScope(tokvalue->variable()->nameToken(), tok->scope()) ||
|
||||||
(val.isSubFunctionLifetimeValue() && tokvalue->variable()->isLocal()))) {
|
(val.isSubFunctionLifetimeValue() && isDanglingSubFunction(tokvalue, tok)))) {
|
||||||
const Variable * var = nullptr;
|
const Variable * var = nullptr;
|
||||||
const Token * tok2 = tok;
|
const Token * tok2 = tok;
|
||||||
if (Token::simpleMatch(tok->astParent(), "=")) {
|
if (Token::simpleMatch(tok->astParent(), "=")) {
|
||||||
|
|
|
@ -1040,6 +1040,17 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Function* nestedInFunction(const Scope* scope) {
|
||||||
|
while(scope) {
|
||||||
|
if (scope->type == Scope::eFunction)
|
||||||
|
break;
|
||||||
|
scope = scope->nestedIn;
|
||||||
|
}
|
||||||
|
if (!scope)
|
||||||
|
return nullptr;
|
||||||
|
return scope->function;
|
||||||
|
}
|
||||||
|
|
||||||
bool isClassOrStruct() const {
|
bool isClassOrStruct() const {
|
||||||
return (type == eClass || type == eStruct);
|
return (type == eClass || type == eStruct);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2170,6 +2170,32 @@ private:
|
||||||
ASSERT_EQUALS(
|
ASSERT_EQUALS(
|
||||||
"[test.cpp:8] -> [test.cpp:8] -> [test.cpp:4] -> [test.cpp:7] -> [test.cpp:4]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n",
|
"[test.cpp:8] -> [test.cpp:8] -> [test.cpp:4] -> [test.cpp:7] -> [test.cpp:4]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n",
|
||||||
errout.str());
|
errout.str());
|
||||||
|
|
||||||
|
check("struct A {\n"
|
||||||
|
" std::vector<int*> v;\n"
|
||||||
|
" void add(int* i) {\n"
|
||||||
|
" v.push_back(i);\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" A a;\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" a.add(&i);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct A {\n"
|
||||||
|
" std::vector<int*> v;\n"
|
||||||
|
" void add(int* i) {\n"
|
||||||
|
" v.push_back(i);\n"
|
||||||
|
" }\n"
|
||||||
|
" void f() {\n"
|
||||||
|
" A a;\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" a.add(&i);\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void danglingLifetime() {
|
void danglingLifetime() {
|
||||||
|
|
Loading…
Reference in New Issue