From 715714f4dea1ffad84ade01570ba3daa830a362d Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Thu, 21 Feb 2019 23:37:02 -0600 Subject: [PATCH] Forward lifetimes in "for" loops (#1682) * Forward lifetimes in for loops * Format --- lib/valueflow.cpp | 17 ++++++++++++++++- test/testautovariables.cpp | 10 ++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index b86cc60ff..e43f73fff 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2729,7 +2729,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog if (!parent) return; // Assignment - if (parent->str() == "=" && !parent->astParent()) { + if (parent->str() == "=" && (!parent->astParent() || Token::simpleMatch(parent->astParent(), ";"))) { // Lhs should be a variable if (!parent->astOperand1() || !parent->astOperand1()->varId()) return; @@ -2768,6 +2768,21 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog tokenlist, errorLogger, settings); + + if (tok->astTop() && Token::simpleMatch(tok->astTop()->previous(), "for (") && + Token::simpleMatch(tok->astTop()->link(), ") {")) { + const Token *start = tok->astTop()->link()->next(); + valueFlowForward(const_cast(start), + start->link(), + var, + var->declarationId(), + values, + false, + false, + tokenlist, + errorLogger, + settings); + } // Function call } else if (Token::Match(parent->previous(), "%name% (")) { valueFlowLifetimeFunction(const_cast(parent->previous()), tokenlist, errorLogger, settings); diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index da9543288..449151d84 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -1538,6 +1538,16 @@ private: "[test.cpp:6] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:7]: (error) Non-local variable 'm' will use object that points to local variable 'x'.\n", errout.str()); + check("std::vector::iterator f(std::vector v) {\n" + " for(auto it = v.begin();it != v.end();it++) {\n" + " return it;\n" + " }\n" + " return {};\n" + "}\n"); + ASSERT_EQUALS( + "[test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 'v' that will be invalid when returning.\n", + errout.str()); + check("struct A {\n" " std::vector v;\n" " void f() {\n"