Fix issue 10037: False positive when passing variables to functions by address (#2957)
This commit is contained in:
parent
2541b6034f
commit
626dcd0eba
|
@ -3120,6 +3120,14 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
|||
tokenlist,
|
||||
errorLogger,
|
||||
settings);
|
||||
// Cast
|
||||
} else if (parent->isCast()) {
|
||||
std::list<ValueFlow::Value> values = tok->values();
|
||||
// Only forward lifetime values
|
||||
values.remove_if(&isNotLifetimeValue);
|
||||
for(const ValueFlow::Value& value:values)
|
||||
setTokenValue(parent, value, tokenlist->getSettings());
|
||||
valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3479,6 +3479,21 @@ private:
|
|||
" return d;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// #10037
|
||||
check("struct a {\n"
|
||||
" int* p;\n"
|
||||
"};\n"
|
||||
"void g(a*);\n"
|
||||
"void f() {\n"
|
||||
" struct a b;\n"
|
||||
" uint32_t p = (uint32_t) -1;\n"
|
||||
" b.p = (void *) &p;\n"
|
||||
" int r = g(&b);\n"
|
||||
" if (r == 0)\n"
|
||||
" if (p != (uint32_t) -1) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void alwaysTrueInfer() {
|
||||
|
|
|
@ -147,6 +147,10 @@ private:
|
|||
return !val.isTokValue();
|
||||
}
|
||||
|
||||
static bool isNotLifetimeValue(const ValueFlow::Value& val) {
|
||||
return !val.isLifetimeValue();
|
||||
}
|
||||
|
||||
bool testValueOfXKnown(const char code[], unsigned int linenr, int value) {
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
@ -371,6 +375,25 @@ private:
|
|||
return values;
|
||||
}
|
||||
|
||||
std::vector<std::string> lifetimeValues(const char code[], const char tokstr[], const Settings *s = nullptr) {
|
||||
std::vector<std::string> result;
|
||||
Tokenizer tokenizer(s ? s : &settings, this);
|
||||
std::istringstream istr(code);
|
||||
errout.str("");
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
|
||||
if (!tok)
|
||||
return result;
|
||||
for(const ValueFlow::Value& value:tok->values()) {
|
||||
if (!value.isLifetimeValue())
|
||||
continue;
|
||||
if (!value.tokvalue)
|
||||
continue;
|
||||
result.push_back(value.tokvalue->expressionString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
|
||||
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
|
||||
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
||||
|
@ -451,6 +474,7 @@ private:
|
|||
|
||||
void valueFlowLifetime() {
|
||||
const char *code;
|
||||
std::vector<std::string> lifetimes;
|
||||
|
||||
LOAD_LIB_2(settings.library, "std.cfg");
|
||||
|
||||
|
@ -482,6 +506,14 @@ private:
|
|||
" auto it = x;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(true, testValueOfX(code, 4, "v . begin", ValueFlow::Value::LIFETIME));
|
||||
|
||||
code = "void f() {\n"
|
||||
" int i = 0;\n"
|
||||
" void* x = (void*)&i;\n"
|
||||
"}\n";
|
||||
lifetimes = lifetimeValues(code, "( void * )");
|
||||
ASSERT_EQUALS(true, lifetimes.size() == 1);
|
||||
ASSERT_EQUALS(true, lifetimes.front() == "i");
|
||||
}
|
||||
|
||||
void valueFlowArrayElement() {
|
||||
|
|
Loading…
Reference in New Issue