diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 4be7a13dbc7..fc5e103172a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1473,6 +1473,19 @@ ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclus return std::move(values.front()); } +static bool checkDotLifetime(const Token* dot, const Token* tok) +{ + if (Token::simpleMatch(dot->astOperand1(), ".")) + return false; + if (!dot->astOperand2()) + return true; + if (dot->astOperand2()->varId() && tok->isUnaryOp("*")) + return dot->astOperand2()->variable() && dot->astOperand2()->variable()->isArray(); + if (dot->astOperand2()->valueType() && dot->astOperand2()->valueType()->reference != Reference::None) + return false; + return true; +} + template static std::vector getLifetimeTokens(const Token* tok, bool escape, @@ -1585,8 +1598,7 @@ static std::vector getLifetimeTokens(const Token* tok, if (vartok->str() == "[" || vartok->isUnaryOp("*")) vartok = vartok->astOperand1(); else if (vartok->str() == ".") { - if (!Token::simpleMatch(vartok->astOperand1(), ".") && - !(vartok->astOperand2() && vartok->astOperand2()->valueType() && vartok->astOperand2()->valueType()->reference != Reference::None)) + if (checkDotLifetime(vartok, tok)) vartok = vartok->astOperand1(); else break; diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index a2fa4168ea8..d5ab5855c32 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -4581,6 +4581,23 @@ class TestAutoVariables : public TestFixture { ASSERT_EQUALS("[test.cpp:5:11] -> [test.cpp:4:9] -> [test.cpp:5:6]: (error) Non-local variable 'g.a' will use pointer to local variable 'x'. [danglingLifetime]\n" "[test.cpp:5:11] -> [test.cpp:4:9] -> [test.cpp:6:13]: (error) Returning pointer to local variable 'x' that will be invalid when returning. [returnDanglingLifetime]\n", errout_str()); + + check("int* f() {\n" // #11168 + " auto x = get();\n" + " return &*x.a;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int a[1]; };\n" + "int& f(S s) {\n" + " return *s.a;\n" + "}\n" + "int* g(S s) {\n" + " return &*s.a;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:12]: (error) Reference to local variable returned. [returnReference]\n" + "[test.cpp:6:12] -> [test.cpp:5:10] -> [test.cpp:6:12]: (error) Returning pointer to local variable 's' that will be invalid when returning. [returnDanglingLifetime]\n", + errout_str()); } void danglingLifetimeClassMemberFunctions()