FIx issue 9895: ValueFlow: Wrong known value below function call with reference parameter
This commit is contained in:
parent
e03a8e1dc1
commit
be900873cc
|
@ -5,19 +5,30 @@
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
void ProgramMemory::setValue(nonneg int varid, const ValueFlow::Value &value)
|
void ProgramMemory::setValue(nonneg int varid, const ValueFlow::Value &value)
|
||||||
{
|
{
|
||||||
values[varid] = value;
|
values[varid] = value;
|
||||||
}
|
}
|
||||||
|
const ValueFlow::Value* ProgramMemory::getValue(nonneg int varid) const
|
||||||
|
{
|
||||||
|
const ProgramMemory::Map::const_iterator it = values.find(varid);
|
||||||
|
const bool found = it != values.end() && !it->second.isImpossible();
|
||||||
|
if (found)
|
||||||
|
return &it->second;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool ProgramMemory::getIntValue(nonneg int varid, MathLib::bigint* result) const
|
bool ProgramMemory::getIntValue(nonneg int varid, MathLib::bigint* result) const
|
||||||
{
|
{
|
||||||
const ProgramMemory::Map::const_iterator it = values.find(varid);
|
const ValueFlow::Value* value = getValue(varid);
|
||||||
const bool found = it != values.end() && it->second.isIntValue();
|
if (value && value->isIntValue()) {
|
||||||
if (found)
|
*result = value->intvalue;
|
||||||
*result = it->second.intvalue;
|
return true;
|
||||||
return found;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value)
|
void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value)
|
||||||
|
@ -27,20 +38,22 @@ void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value)
|
||||||
|
|
||||||
bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const
|
bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const
|
||||||
{
|
{
|
||||||
const ProgramMemory::Map::const_iterator it = values.find(varid);
|
const ValueFlow::Value* value = getValue(varid);
|
||||||
const bool found = it != values.end() && it->second.isTokValue();
|
if (value && value->isTokValue()) {
|
||||||
if (found)
|
*result = value->tokvalue;
|
||||||
*result = it->second.tokvalue;
|
return true;
|
||||||
return found;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramMemory::getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const
|
bool ProgramMemory::getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const
|
||||||
{
|
{
|
||||||
const ProgramMemory::Map::const_iterator it = values.find(varid);
|
const ValueFlow::Value* value = getValue(varid);
|
||||||
const bool found = it != values.end() && it->second.isContainerSizeValue();
|
if (value && value->isContainerSizeValue()) {
|
||||||
if (found)
|
*result = value->intvalue;
|
||||||
*result = it->second.intvalue;
|
return true;
|
||||||
return found;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramMemory::setUnknown(nonneg int varid)
|
void ProgramMemory::setUnknown(nonneg int varid)
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct ProgramMemory {
|
||||||
Map values;
|
Map values;
|
||||||
|
|
||||||
void setValue(nonneg int varid, const ValueFlow::Value &value);
|
void setValue(nonneg int varid, const ValueFlow::Value &value);
|
||||||
|
const ValueFlow::Value* getValue(nonneg int varid) const;
|
||||||
|
|
||||||
bool getIntValue(nonneg int varid, MathLib::bigint* result) const;
|
bool getIntValue(nonneg int varid, MathLib::bigint* result) const;
|
||||||
void setIntValue(nonneg int varid, MathLib::bigint value);
|
void setIntValue(nonneg int varid, MathLib::bigint value);
|
||||||
|
|
|
@ -164,6 +164,24 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool testValueOfXImpossible(const char code[], unsigned int linenr, int value) {
|
||||||
|
// 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& val:tok->values()) {
|
||||||
|
if (val.isImpossible() && val.intvalue == value)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool testValueOfX(const char code[], unsigned int linenr, int value) {
|
bool testValueOfX(const char code[], unsigned int linenr, int value) {
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -2449,6 +2467,17 @@ private:
|
||||||
" return x;\n"
|
" return x;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 9U, 0));
|
ASSERT_EQUALS(true, testValueOfX(code, 9U, 0));
|
||||||
|
|
||||||
|
code = "void g(long& a);\n"
|
||||||
|
"void f(long a) {\n"
|
||||||
|
" if (a == 0)\n"
|
||||||
|
" return;\n"
|
||||||
|
" if (a > 1)\n"
|
||||||
|
" g(a);\n"
|
||||||
|
" int x = a;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(false, testValueOfXImpossible(code, 8U, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void valueFlowAfterConditionExpr() {
|
void valueFlowAfterConditionExpr() {
|
||||||
|
|
Loading…
Reference in New Issue