Fix issue 9595: False positive: Using pointer to temporary doesn't account for const ref extended temporary lifetimes (#2525)

This commit is contained in:
Paul Fultz II 2020-02-10 11:01:11 -06:00 committed by GitHub
parent 125c4832cd
commit 8fa7dd0fe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 4 deletions

View File

@ -220,7 +220,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
return ret; return ret;
} }
bool isTemporary(bool cpp, const Token* tok, const Library* library) bool isTemporary(bool cpp, const Token* tok, const Library* library, bool unknown)
{ {
if (!tok) if (!tok)
return false; return false;
@ -251,7 +251,7 @@ bool isTemporary(bool cpp, const Token* tok, const Library* library)
std::string returnType = library->returnValueType(ftok); std::string returnType = library->returnValueType(ftok);
return !returnType.empty() && returnType.back() != '&'; return !returnType.empty() && returnType.back() != '&';
} else { } else {
return false; return unknown;
} }
} }
return true; return true;

View File

@ -87,7 +87,7 @@ std::string astCanonicalType(const Token *expr);
/** Is given syntax tree a variable comparison against value */ /** Is given syntax tree a variable comparison against value */
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr); const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
bool isTemporary(bool cpp, const Token* tok, const Library* library); bool isTemporary(bool cpp, const Token* tok, const Library* library, bool unknown = false);
const Token * nextAfterAstRightmostLeaf(const Token * tok); const Token * nextAfterAstRightmostLeaf(const Token * tok);

View File

@ -3231,7 +3231,7 @@ std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, ValueFlow::Value:
} else if (Token::simpleMatch(var->declEndToken(), "=")) { } else if (Token::simpleMatch(var->declEndToken(), "=")) {
errorPath.emplace_back(var->declEndToken(), "Assigned to reference."); errorPath.emplace_back(var->declEndToken(), "Assigned to reference.");
const Token *vartok = var->declEndToken()->astOperand2(); const Token *vartok = var->declEndToken()->astOperand2();
if (vartok == tok || (var->isConst() && isTemporary(true, vartok, nullptr))) if (vartok == tok || (var->isConst() && isTemporary(true, vartok, nullptr, true)))
return {{tok, true, std::move(errorPath)}}; return {{tok, true, std::move(errorPath)}};
if (vartok) if (vartok)
return getLifetimeTokens(vartok, std::move(errorPath), depth - 1); return getLifetimeTokens(vartok, std::move(errorPath), depth - 1);

View File

@ -2501,6 +2501,13 @@ private:
ASSERT_EQUALS( ASSERT_EQUALS(
"[test.cpp:3] -> [test.cpp:4]: (error) Using iterator to temporary.\n", "[test.cpp:3] -> [test.cpp:4]: (error) Using iterator to temporary.\n",
errout.str()); errout.str());
check("std::string f() {\n"
" std::stringstream tmp;\n"
" const std::string &str = tmp.str();\n"
" return std::string(str.c_str(), 1);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void invalidLifetime() { void invalidLifetime() {