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,
|
tokenlist,
|
||||||
errorLogger,
|
errorLogger,
|
||||||
settings);
|
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"
|
" return d;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void alwaysTrueInfer() {
|
||||||
|
|
|
@ -147,6 +147,10 @@ private:
|
||||||
return !val.isTokValue();
|
return !val.isTokValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isNotLifetimeValue(const ValueFlow::Value& val) {
|
||||||
|
return !val.isLifetimeValue();
|
||||||
|
}
|
||||||
|
|
||||||
bool testValueOfXKnown(const char code[], unsigned int linenr, int value) {
|
bool testValueOfXKnown(const char code[], unsigned int linenr, int value) {
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -371,6 +375,25 @@ private:
|
||||||
return values;
|
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[]) {
|
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
|
||||||
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
|
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
|
||||||
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
||||||
|
@ -451,6 +474,7 @@ private:
|
||||||
|
|
||||||
void valueFlowLifetime() {
|
void valueFlowLifetime() {
|
||||||
const char *code;
|
const char *code;
|
||||||
|
std::vector<std::string> lifetimes;
|
||||||
|
|
||||||
LOAD_LIB_2(settings.library, "std.cfg");
|
LOAD_LIB_2(settings.library, "std.cfg");
|
||||||
|
|
||||||
|
@ -482,6 +506,14 @@ private:
|
||||||
" auto it = x;\n"
|
" auto it = x;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 4, "v . begin", ValueFlow::Value::LIFETIME));
|
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() {
|
void valueFlowArrayElement() {
|
||||||
|
|
Loading…
Reference in New Issue