FIx issue 9895: ValueFlow: Wrong known value below function call with reference parameter

This commit is contained in:
Paul 2020-09-11 16:03:57 -05:00
parent e03a8e1dc1
commit be900873cc
3 changed files with 58 additions and 15 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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() {