diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 678abeafff5..af49c65391a 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -1765,9 +1765,16 @@ static Token * createAstAtToken(Token *tok) if (Token::Match(tok, "%type% %name%|*|&|&&|::") && !Token::Match(tok, "return|new|delete")) { int typecount = 0; Token *typetok = tok; - while (Token::Match(typetok, "%type%|::|*|&|&&")) { + while (Token::Match(typetok, "%type%|::|*|&|&&|<")) { if (typetok->isName() && !Token::simpleMatch(typetok->previous(), "::")) typecount++; + if (typetok->str() == "<") { + if (Token* closing = typetok->findClosingBracket()) { + typetok = closing->next(); + continue; + } + break; + } typetok = typetok->next(); } if (Token::Match(typetok, "%var% =") && typetok->varId()) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a7198e33007..e2d2f12f465 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1948,7 +1948,12 @@ static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent) return true; if (vtParent->pointer < vt->pointer && vtParent->isIntegral()) return true; - if (vtParent->str() == vt->str()) + ValueType temp = *vtParent; + if ((temp.constness & 1) && !(vt->constness & 1)) // allow assignment to const/volatile + temp.constness &= ~1; + if ((temp.volatileness & 1) && !(vt->volatileness & 1)) + temp.volatileness &= ~1; + if (temp.str() == vt->str()) return true; } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 453fadfaf50..57fc43f80ce 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -4122,6 +4122,20 @@ class TestAutoVariables : public TestFixture { ASSERT_EQUALS("[test.cpp:9:63] -> [test.cpp:9:49] -> [test.cpp:10:11]: (error) Using iterator that is a temporary. [danglingTemporaryLifetime]\n", errout_str()); + check("struct A {\n" // #14054 + " std::map m_;\n" + "};\n" + "struct B {\n" + " A a_;\n" + "};\n" + "B func();\n" + "void f() {\n" + " const std::map::iterator m = func().a_.m_.begin();\n" + " (void)m->first;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9:62] -> [test.cpp:9:48] -> [test.cpp:10:11]: (error) Using iterator that is a temporary. [danglingTemporaryLifetime]\n", + errout_str()); + check("void f(bool b) {\n" " std::vector ints = g();\n" " auto *ptr = &ints;\n" diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index b6abf31b424..af34625ca18 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6788,6 +6788,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("unoRef:: var0(", testAst(code1)); ASSERT_EQUALS("vary=", testAst("std::string var = y;")); + ASSERT_EQUALS("vary=", testAst("std::unique_ptr var = y;")); // #14019 ASSERT_EQUALS("", testAst("void *(*var)(int);")); ASSERT_EQUALS("", testAst("void *(*var[2])(int);"));