diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 9422261e1..5dd32b4a1 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -578,7 +578,8 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token } } } - const bool escape = Token::Match(tok->astParent(), "return|throw"); + const bool escape = Token::simpleMatch(tok->astParent(), "throw") || + (Token::simpleMatch(tok->astParent(), "return") && !Function::returnsStandardType(scope->function)); std::unordered_set exprs; for (const ValueFlow::Value& val:tok->values()) { if (!val.isLocalLifetimeValue() && !val.isSubFunctionLifetimeValue()) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a5b81b180..82151ff48 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2931,6 +2931,13 @@ bool Function::returnsReference(const Function* function, bool unknown) }); } +bool Function::returnsStandardType(const Function* function, bool unknown) +{ + return checkReturns(function, unknown, true, [](UNUSED const Token* defStart, const Token* defEnd) { + return defEnd->previous() && defEnd->previous()->isStandardType(); + }); +} + bool Function::returnsVoid(const Function* function, bool unknown) { return checkReturns(function, unknown, true, [](UNUSED const Token* defStart, const Token* defEnd) { diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index e8ba08e83..6d0a0fa3d 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -930,6 +930,7 @@ public: static bool returnsConst(const Function* function, bool unknown = false); static bool returnsReference(const Function* function, bool unknown = false); + static bool returnsStandardType(const Function* function, bool unknown = false); static bool returnsVoid(const Function* function, bool unknown = false); diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 933b22264..781141bc4 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -2768,6 +2768,22 @@ private: ASSERT_EQUALS( "[test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'p' that will be invalid when returning.\n", errout.str()); + + check("int* f();\n" // #11406 + "bool g() {\n" + " std::unique_ptr ptr(f());\n" + " return ptr.get();\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("int* f();\n" + "int* g() {\n" + " std::unique_ptr ptr(f());\n" + " return ptr.get();\n" + "}\n"); + ASSERT_EQUALS( + "[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning object that points to local variable 'ptr' that will be invalid when returning.\n", + errout.str()); } void danglingLifetime() { check("auto f() {\n"