Avoid infinite recursion in getLifetimeVariable (#1634)

* Fix direct recursion

* Limit depth of getLifetimeVariable
This commit is contained in:
Paul Fultz II 2019-01-31 03:34:41 -06:00 committed by Daniel Marjamäki
parent 0b7414973d
commit c176775afb
3 changed files with 19 additions and 5 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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"