diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index ed16e6ef0..102928268 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -589,7 +589,7 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se return; if (value.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator && astIsIterator(parent)) { setTokenValue(parent,value,settings); - } else if (astIsPointer(tok) && astIsPointer(parent) && + } else if (astIsPointer(tok) && astIsPointer(parent) && !parent->isUnaryOp("*") && (parent->isArithmeticalOp() || parent->isCast())) { setTokenValue(parent,value,settings); } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 0ae2ed155..9c1de322a 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -332,6 +332,24 @@ private: return false; } + bool testLifetimeOfX(const char code[], unsigned int linenr, const char value[], ValueFlow::Value::LifetimeScope lifetimeScope = ValueFlow::Value::LifetimeScope::Local) { + // Tokenize.. + Tokenizer tokenizer(&settings, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { + if (tok->str() == "x" && tok->linenr() == linenr) { + for (const ValueFlow::Value &v : tok->values()) { + if (v.isLifetimeValue() && v.lifetimeScope == lifetimeScope && Token::simpleMatch(v.tokvalue, value, strlen(value))) + return true; + } + } + } + + return false; + } + bool testValueOfX(const char code[], unsigned int linenr, int value, ValueFlow::Value::ValueType type) { // Tokenize.. Tokenizer tokenizer(&settings, this); @@ -532,14 +550,14 @@ private: " auto x = [&]() { return a + 1; };\n" " auto b = x;\n" "}\n"; - ASSERT_EQUALS(true, testValueOfX(code, 4, "a + 1", ValueFlow::Value::ValueType::LIFETIME)); + ASSERT_EQUALS(true, testLifetimeOfX(code, 4, "a + 1")); code = "void f() {\n" " int a = 1;\n" " auto x = [=]() { return a + 1; };\n" " auto b = x;\n" "}\n"; - ASSERT_EQUALS(false, testValueOfX(code, 4, "a ;", ValueFlow::Value::ValueType::LIFETIME)); + ASSERT_EQUALS(false, testLifetimeOfX(code, 4, "a ;")); code = "void f(int v) {\n" " int a = v;\n" @@ -547,14 +565,42 @@ private: " auto x = [=]() { return p + 1; };\n" " auto b = x;\n" "}\n"; - ASSERT_EQUALS(true, testValueOfX(code, 5, "a ;", ValueFlow::Value::ValueType::LIFETIME)); + ASSERT_EQUALS(true, testLifetimeOfX(code, 5, "a ;")); code = "void f() {\n" " std::vector v;\n" " auto x = v.begin();\n" " auto it = x;\n" "}\n"; - ASSERT_EQUALS(true, testValueOfX(code, 4, "v . begin", ValueFlow::Value::ValueType::LIFETIME)); + ASSERT_EQUALS(true, testLifetimeOfX(code, 4, "v . begin")); + + code = "void f() {\n" + " std::vector v;\n" + " auto x = v.begin() + 1;\n" + " auto it = x;\n" + "}\n"; + ASSERT_EQUALS(true, testLifetimeOfX(code, 4, "v . begin")); + + code = "int* f() {\n" + " std::vector v;\n" + " int * x = v.data();\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testLifetimeOfX(code, 4, "v . data")); + + code = "int* f() {\n" + " std::vector v;\n" + " int * x = v.data() + 1;\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testLifetimeOfX(code, 4, "v . data")); + + code = "int f(int* a) {\n" + " int **p = &a;\n" + " int * x = *p;\n" + " return x; \n" + "}\n"; + ASSERT_EQUALS(false, testLifetimeOfX(code, 4, "a")); code = "void f() {\n" " int i = 0;\n"