Merge pull request #2798 from pfultz2/programmemory-impossible

FIx issue 9895: ValueFlow: Wrong known value below function call with reference parameter
This commit is contained in:
Daniel Marjamäki 2020-09-12 05:03:20 +02:00 committed by GitHub
commit 3880412c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 15 deletions

View File

@ -5,19 +5,30 @@
#include "symboldatabase.h"
#include <algorithm>
#include <cassert>
#include <memory>
void ProgramMemory::setValue(nonneg int varid, const ValueFlow::Value &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
{
const ProgramMemory::Map::const_iterator it = values.find(varid);
const bool found = it != values.end() && it->second.isIntValue();
if (found)
*result = it->second.intvalue;
return found;
const ValueFlow::Value* value = getValue(varid);
if (value && value->isIntValue()) {
*result = value->intvalue;
return true;
}
return false;
}
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
{
const ProgramMemory::Map::const_iterator it = values.find(varid);
const bool found = it != values.end() && it->second.isTokValue();
if (found)
*result = it->second.tokvalue;
return found;
const ValueFlow::Value* value = getValue(varid);
if (value && value->isTokValue()) {
*result = value->tokvalue;
return true;
}
return false;
}
bool ProgramMemory::getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const
{
const ProgramMemory::Map::const_iterator it = values.find(varid);
const bool found = it != values.end() && it->second.isContainerSizeValue();
if (found)
*result = it->second.intvalue;
return found;
const ValueFlow::Value* value = getValue(varid);
if (value && value->isContainerSizeValue()) {
*result = value->intvalue;
return true;
}
return false;
}
void ProgramMemory::setUnknown(nonneg int varid)

View File

@ -15,6 +15,7 @@ struct ProgramMemory {
Map values;
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;
void setIntValue(nonneg int varid, MathLib::bigint value);

View File

@ -164,6 +164,24 @@ private:
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) {
// Tokenize..
Tokenizer tokenizer(&settings, this);
@ -2449,6 +2467,17 @@ private:
" return x;\n"
"}\n";
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() {