Bug hunting; better handling when assigning multidimensional array in for loop
This commit is contained in:
parent
b36c85d8fd
commit
6faad9cd90
|
@ -1929,8 +1929,13 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs
|
||||||
std::set<int> changedVariables;
|
std::set<int> changedVariables;
|
||||||
for (const Token *tok2 = tok; tok2 != bodyEnd; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok; tok2 != bodyEnd; tok2 = tok2->next()) {
|
||||||
if (Token::Match(tok2, "%assign%")) {
|
if (Token::Match(tok2, "%assign%")) {
|
||||||
if (Token::Match(tok2->astOperand1(), ". %name% =") && tok2->astOperand1()->astOperand1() && tok2->astOperand1()->astOperand1()->valueType()) {
|
const Token *lhs = tok2->astOperand1();
|
||||||
const Token *structToken = tok2->astOperand1()->astOperand1();
|
while (Token::simpleMatch(lhs, "["))
|
||||||
|
lhs = lhs->astOperand1();
|
||||||
|
if (!lhs)
|
||||||
|
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
||||||
|
if (Token::Match(lhs, ". %name% =|[") && lhs->astOperand1() && lhs->astOperand1()->valueType()) {
|
||||||
|
const Token *structToken = lhs->astOperand1();
|
||||||
if (!structToken->valueType() || !structToken->varId())
|
if (!structToken->valueType() || !structToken->varId())
|
||||||
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
||||||
const Scope *structScope = structToken->valueType()->typeScope;
|
const Scope *structScope = structToken->valueType()->typeScope;
|
||||||
|
@ -1957,30 +1962,34 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs
|
||||||
data.assignStructMember(tok2, &*structVal, memberName, memberValue);
|
data.assignStructMember(tok2, &*structVal, memberName, memberValue);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (tok2->astOperand1() && tok2->astOperand1()->isUnaryOp("*") && tok2->astOperand1()->astOperand1()->varId()) {
|
if (lhs->isUnaryOp("*") && lhs->astOperand1()->varId()) {
|
||||||
const Token *varToken = tok2->astOperand1()->astOperand1();
|
const Token *varToken = tok2->astOperand1()->astOperand1();
|
||||||
ExprEngine::ValuePtr val = data.getValue(varToken->varId(), varToken->valueType(), varToken);
|
ExprEngine::ValuePtr val = data.getValue(varToken->varId(), varToken->valueType(), varToken);
|
||||||
if (val && val->type == ExprEngine::ValueType::ArrayValue) {
|
if (val && val->type == ExprEngine::ValueType::ArrayValue) {
|
||||||
// Try to assign "any" value
|
// Try to assign "any" value
|
||||||
auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(val);
|
auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(val);
|
||||||
//ExprEngine::ValuePtr anyValue = getValueRangeFromValueType(data.getNewSymbolName(), tok2->astOperand1()->valueType(), *data.settings);
|
|
||||||
arrayValue->assign(std::make_shared<ExprEngine::IntRange>("0", 0, 0), std::make_shared<ExprEngine::BailoutValue>());
|
arrayValue->assign(std::make_shared<ExprEngine::IntRange>("0", 0, 0), std::make_shared<ExprEngine::BailoutValue>());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Token::Match(tok2->astOperand1(), "%var%"))
|
if (!lhs->variable())
|
||||||
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
|
||||||
if (!tok2->astOperand1()->variable())
|
|
||||||
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
throw BugHuntingException(tok2, "Unhandled assignment in loop");
|
||||||
// give variable "any" value
|
// give variable "any" value
|
||||||
int varid = tok2->astOperand1()->varId();
|
int varid = lhs->varId();
|
||||||
if (changedVariables.find(varid) != changedVariables.end())
|
if (changedVariables.find(varid) != changedVariables.end())
|
||||||
continue;
|
continue;
|
||||||
changedVariables.insert(varid);
|
changedVariables.insert(varid);
|
||||||
auto oldValue = data.getValue(varid, nullptr, nullptr);
|
auto oldValue = data.getValue(varid, nullptr, nullptr);
|
||||||
if (oldValue && oldValue->isUninit())
|
if (oldValue && oldValue->isUninit())
|
||||||
call(data.callbacks, tok2->astOperand1(), oldValue, &data);
|
call(data.callbacks, lhs, oldValue, &data);
|
||||||
data.assignValue(tok2, varid, getValueRangeFromValueType(data.getNewSymbolName(), tok2->astOperand1()->valueType(), *data.settings));
|
if (oldValue && oldValue->type == ExprEngine::ValueType::ArrayValue) {
|
||||||
|
// Try to assign "any" value
|
||||||
|
auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(oldValue);
|
||||||
|
arrayValue->assign(std::make_shared<ExprEngine::IntRange>(data.getNewSymbolName(), 0, ~0ULL), std::make_shared<ExprEngine::BailoutValue>());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data.assignValue(tok2, varid, getValueRangeFromValueType(data.getNewSymbolName(), lhs->valueType(), *data.settings));
|
||||||
|
continue;
|
||||||
} else if (Token::Match(tok2, "++|--") && tok2->astOperand1() && tok2->astOperand1()->variable()) {
|
} else if (Token::Match(tok2, "++|--") && tok2->astOperand1() && tok2->astOperand1()->variable()) {
|
||||||
// give variable "any" value
|
// give variable "any" value
|
||||||
const Token *vartok = tok2->astOperand1();
|
const Token *vartok = tok2->astOperand1();
|
||||||
|
|
|
@ -73,6 +73,7 @@ private:
|
||||||
TEST_CASE(arrayInit1);
|
TEST_CASE(arrayInit1);
|
||||||
TEST_CASE(arrayInit2);
|
TEST_CASE(arrayInit2);
|
||||||
TEST_CASE(arrayUninit);
|
TEST_CASE(arrayUninit);
|
||||||
|
TEST_CASE(arrayInLoop);
|
||||||
|
|
||||||
TEST_CASE(floatValue1);
|
TEST_CASE(floatValue1);
|
||||||
TEST_CASE(floatValue2);
|
TEST_CASE(floatValue2);
|
||||||
|
@ -524,6 +525,15 @@ private:
|
||||||
ASSERT_EQUALS("?", getRange("int f() { int arr[10]; return arr[4]; }", "arr[4]"));
|
ASSERT_EQUALS("?", getRange("int f() { int arr[10]; return arr[4]; }", "arr[4]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arrayInLoop() {
|
||||||
|
const char code[] = "void f() {\n"
|
||||||
|
" int arr[3][3];\n"
|
||||||
|
" for (int i = 0; i < 3; i++) arr[i][0] = arr[1][2];\n"
|
||||||
|
" return arr[0][0];"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("?", getRange(code, "arr[1]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void floatValue1() {
|
void floatValue1() {
|
||||||
ASSERT_EQUALS("-inf:inf", getRange("float f; void func() { f=f; }", "f=f"));
|
ASSERT_EQUALS("-inf:inf", getRange("float f; void func() { f=f; }", "f=f"));
|
||||||
|
|
Loading…
Reference in New Issue