diff --git a/lib/checkother.cpp b/lib/checkother.cpp index c229cfed789..10ba68b819a 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1810,18 +1810,32 @@ void CheckOtherImpl::checkConstVariable() if (function && (Function::returnsReference(function) || Function::returnsPointer(function)) && !Function::returnsConst(function)) { std::vector returns = Function::findReturns(function); if (std::any_of(returns.cbegin(), returns.cend(), [&](const Token* retTok) { - if (retTok->varId() == var->declarationId()) - return true; - while (retTok && retTok->isCast()) - retTok = retTok->astOperand2() ? retTok->astOperand2() : retTok->astOperand1(); - while (Token::simpleMatch(retTok, ".")) - retTok = retTok->astOperand2(); - if (Token::simpleMatch(retTok, "&")) - retTok = retTok->astOperand1(); - ValueFlow::Value ltVal = ValueFlow::getLifetimeObjValue(retTok); - if (ltVal.isLifetimeValue() && ltVal.tokvalue->varId() == var->declarationId()) - return true; - return ValueFlow::hasLifetimeToken(getParentLifetime(retTok), var->nameToken(), mSettings); + bool result = false; + visitAstNodes(retTok, [&result, &var, this](const Token* tok) { + if (tok->varId() == var->declarationId()) { + result = true; + return ChildrenToVisit::done; + } + if (tok->isCast()) + return tok->astOperand2() ? ChildrenToVisit::op2 : ChildrenToVisit::op1; + if (tok->str() == ".") + return ChildrenToVisit::op2; + if (tok->str() == "&") + return ChildrenToVisit::op1; + if (tok->str() == "?") + return ChildrenToVisit::op2; + if (tok->str() == ":") + return ChildrenToVisit::op1_and_op2; + + ValueFlow::Value ltVal = ValueFlow::getLifetimeObjValue(tok); + if ((ltVal.isLifetimeValue() && ltVal.tokvalue->varId() == var->declarationId()) || + ValueFlow::hasLifetimeToken(getParentLifetime(tok), var->nameToken(), mSettings)) { + result = true; + return ChildrenToVisit::done; + } + return ChildrenToVisit::none; + }); + return result; })) continue; } diff --git a/test/testother.cpp b/test/testother.cpp index 0d2993d0668..27f10258559 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4201,6 +4201,14 @@ class TestOther : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" // #15087 + " int a, b;\n" + "};\n" + "int& f(S& s, bool b) {\n" + " return b ? s.a : s.b;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void constParameterCallback() {