Fix FPs and crashes with byDerefCopy (#1503)
* Fix FP when inserting a range into a container * Formatting * Fix crash
This commit is contained in:
parent
ba564076db
commit
3e1b34dd8f
|
@ -2649,7 +2649,7 @@ struct LifetimeStore {
|
|||
const Variable *var = getLifetimeVariable(tok2, errorPath);
|
||||
if (!var)
|
||||
continue;
|
||||
for (const Token *tok3 = tok; tok != var->declEndToken(); tok3 = tok3->previous()) {
|
||||
for (const Token *tok3 = tok; tok3 && tok3 != var->declEndToken(); tok3 = tok3->previous()) {
|
||||
if (tok3->varId() == var->declarationId()) {
|
||||
LifetimeStore{tok3, message, type} .byVal(tok, tokenlist, errorLogger, settings, pred);
|
||||
break;
|
||||
|
@ -2699,8 +2699,10 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
|
|||
const bool isPointer = endTypeTok && Token::simpleMatch(endTypeTok->previous(), "*");
|
||||
Token *vartok = tok->tokAt(-2);
|
||||
std::vector<const Token *> args = getArguments(tok);
|
||||
if (args.size() == 2 && astCanonicalType(args[0]) == astCanonicalType(args[1]) &&
|
||||
(((astIsIterator(args[0]) && astIsIterator(args[1])) || (astIsPointer(args[0]) && astIsPointer(args[1]))))) {
|
||||
std::size_t n = args.size();
|
||||
if (n > 1 && astCanonicalType(args[n - 2]) == astCanonicalType(args[n - 1]) &&
|
||||
(((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
|
||||
(astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) {
|
||||
LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::Object} .byDerefCopy(
|
||||
vartok, tokenlist, errorLogger, settings);
|
||||
} else if (!args.empty() && astIsPointer(args.back()) == isPointer) {
|
||||
|
|
|
@ -1420,6 +1420,19 @@ private:
|
|||
"[test.cpp:5] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:6]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n",
|
||||
errout.str());
|
||||
|
||||
check("struct A {\n"
|
||||
" std::vector<int*> m;\n"
|
||||
" void f() {\n"
|
||||
" int x;\n"
|
||||
" std::vector<int*> v;\n"
|
||||
" v.push_back(&x);\n"
|
||||
" m.insert(m.end(), v.begin(), v.end());\n"
|
||||
" }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(
|
||||
"[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("struct A {\n"
|
||||
" std::vector<std::string> v;\n"
|
||||
" void f() {\n"
|
||||
|
@ -1483,6 +1496,27 @@ private:
|
|||
" return g([&]() { return v.data(); });\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("std::vector<int> g();\n"
|
||||
"struct A {\n"
|
||||
" std::vector<int> m;\n"
|
||||
" void f() {\n"
|
||||
" std::vector<int> v = g();\n"
|
||||
" m.insert(m.end(), v.begin(), v.end());\n"
|
||||
" }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("class A {\n"
|
||||
" int f( P p ) {\n"
|
||||
" std::vector< S > maps;\n"
|
||||
" m2.insert( m1.begin(), m1.end() );\n"
|
||||
" }\n"
|
||||
" struct B {};\n"
|
||||
" std::map< S, B > m1;\n"
|
||||
" std::map< S, B > m2;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void danglingLifetime() {
|
||||
|
|
Loading…
Reference in New Issue