Avoid infinite recursion in getLifetimeVariable (#1634)
* Fix direct recursion * Limit depth of getLifetimeVariable
This commit is contained in:
parent
0b7414973d
commit
c176775afb
|
@ -2662,11 +2662,13 @@ std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
|
|||
return result;
|
||||
}
|
||||
|
||||
const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPath &errorPath)
|
||||
const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPath &errorPath, int depth)
|
||||
{
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
const Variable *var = tok->variable();
|
||||
if (depth < 0)
|
||||
return var;
|
||||
if (var && var->declarationId() == tok->varId()) {
|
||||
if (var->isReference() || var->isRValueReference()) {
|
||||
if (!var->declEndToken())
|
||||
|
@ -2680,7 +2682,7 @@ const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPat
|
|||
if (vartok == tok)
|
||||
return nullptr;
|
||||
if (vartok)
|
||||
return getLifetimeVariable(vartok, errorPath);
|
||||
return getLifetimeVariable(vartok, errorPath, depth-1);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2694,7 +2696,9 @@ const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPat
|
|||
const Token *returnTok = findSimpleReturn(f);
|
||||
if (!returnTok)
|
||||
return nullptr;
|
||||
const Variable *argvar = getLifetimeVariable(returnTok, errorPath);
|
||||
if (returnTok == tok)
|
||||
return var;
|
||||
const Variable *argvar = getLifetimeVariable(returnTok, errorPath, depth-1);
|
||||
if (!argvar)
|
||||
return nullptr;
|
||||
if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
|
||||
|
@ -2704,7 +2708,7 @@ const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPat
|
|||
const Token *argTok = getArguments(tok->previous()).at(n);
|
||||
errorPath.emplace_back(returnTok, "Return reference.");
|
||||
errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->str() + "'.");
|
||||
return getLifetimeVariable(argTok, errorPath);
|
||||
return getLifetimeVariable(argTok, errorPath, depth-1);
|
||||
}
|
||||
}
|
||||
return var;
|
||||
|
|
|
@ -229,7 +229,7 @@ namespace ValueFlow {
|
|||
std::string eitherTheConditionIsRedundant(const Token *condition);
|
||||
}
|
||||
|
||||
const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPath &errorPath);
|
||||
const Variable *getLifetimeVariable(const Token *tok, ValueFlow::Value::ErrorPath &errorPath, int depth=20);
|
||||
|
||||
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val);
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ private:
|
|||
TEST_CASE(returnReferenceCalculation);
|
||||
TEST_CASE(returnReferenceLambda);
|
||||
TEST_CASE(returnReferenceInnerScope);
|
||||
TEST_CASE(returnReferenceRecursive);
|
||||
|
||||
TEST_CASE(danglingReference);
|
||||
|
||||
|
@ -1246,6 +1247,15 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void returnReferenceRecursive() {
|
||||
check("int& f() { return f(); }");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int& g(int& i) { return i; }\n"
|
||||
"int& f() { return g(f()); }\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void danglingReference() {
|
||||
check("int f( int k )\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue