ValueFlow: Improved value flow after for loop

This commit is contained in:
Daniel Marjamäki 2014-08-17 10:40:22 +02:00
parent 75ec97ad23
commit 5cdbe0f42d
4 changed files with 71 additions and 79 deletions

View File

@ -6388,16 +6388,13 @@ bool Tokenizer::simplifyKnownVariables()
// parse the block of code..
int indentlevel = 0;
Token *tok2 = tok;
bool forhead = false;
for (; tok2; tok2 = tok2->next()) {
if (Token::Match(tok2, "[;{}] float|double %var% ;")) {
floatvars.insert(tok2->tokAt(2)->varId());
}
if (tok2->str() == "{") {
forhead = false;
if (tok2->str() == "{")
++indentlevel;
}
else if (tok2->str() == "}") {
--indentlevel;
@ -6406,7 +6403,7 @@ bool Tokenizer::simplifyKnownVariables()
}
else if (Token::simpleMatch(tok2, "for ("))
forhead = true;
tok2 = tok2->next()->link();
else if (tok2->previous()->str() != "*" && !Token::Match(tok2->tokAt(-2), "* --|++") &&
(Token::Match(tok2, "%var% = %bool%|%char%|%num%|%str%|%var% ;") ||
@ -6441,8 +6438,6 @@ bool Tokenizer::simplifyKnownVariables()
if (Token::Match(tok3->tokAt(-2), "for ( %type%"))
continue;
}
if (forhead && Token::Match(tok2->previous(), ", %var% ="))
continue;
// struct name..
if (Token::Match(tok2, "%varid% = &| %varid%", tok2->varId()))

View File

@ -1160,7 +1160,7 @@ static void execute(const Token *expr,
*error = true;
}
static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, MathLib::bigint * const num1, MathLib::bigint * const num2)
static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, MathLib::bigint * const num1, MathLib::bigint * const num2, MathLib::bigint * const numAfter)
{
tok = tok->tokAt(2);
if (!Token::Match(tok,"%type%| %var% ="))
@ -1190,6 +1190,7 @@ static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, Math
if (!num2tok)
return false;
*num2 = MathLib::toLongNumber(num2tok->str()) - ((tok->str()=="<=") ? 0 : 1);
*numAfter = MathLib::toLongNumber(num2tok->str()) + ((tok->str()=="<=") ? 1 : 0);
if (!num1tok)
*num1 = *num2;
while (tok && tok->str() != ";")
@ -1201,7 +1202,8 @@ static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, Math
static bool valueFlowForLoop2(const Token *tok,
std::map<unsigned int, MathLib::bigint> *memory1,
std::map<unsigned int, MathLib::bigint> *memory2)
std::map<unsigned int, MathLib::bigint> *memory2,
std::map<unsigned int, MathLib::bigint> *memoryAfter)
{
const Token *firstExpression = tok->next()->astOperand2()->astOperand1();
const Token *secondExpression = tok->next()->astOperand2()->astOperand2()->astOperand1();
@ -1243,8 +1245,10 @@ static bool valueFlowForLoop2(const Token *tok,
}
memory1->swap(startMemory);
if (!error)
if (!error) {
memory2->swap(endMemory);
memoryAfter->swap(programMemory);
}
return true;
}
@ -1326,6 +1330,39 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int
}
}
static void valueFlowForLoopSimplifyAfter(Token *fortok, unsigned int varid, const MathLib::bigint num, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
{
const Token *vartok = nullptr;
for (const Token *tok = fortok; tok; tok = tok->next()) {
if (tok->varId() == varid) {
vartok = tok;
break;
}
}
if (!vartok || !vartok->variable())
return;
const Variable *var = vartok->variable();
const Token *endToken = nullptr;
if (var->isLocal())
endToken = var->typeStartToken()->scope()->classEnd;
else
endToken = fortok->scope()->classEnd;
std::list<ValueFlow::Value> values;
values.push_back(num);
valueFlowForward(fortok->linkAt(1)->linkAt(1),
endToken,
var,
varid,
values,
false,
tokenlist,
errorLogger,
settings);
}
static void valueFlowForLoop(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
{
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
@ -1337,19 +1374,22 @@ static void valueFlowForLoop(TokenList *tokenlist, ErrorLogger *errorLogger, con
Token * const bodyStart = tok->linkAt(1)->next();
unsigned int varid(0);
MathLib::bigint num1(0), num2(0);
MathLib::bigint num1(0), num2(0), numAfter(0);
if (valueFlowForLoop1(tok, &varid, &num1, &num2)) {
if (valueFlowForLoop1(tok, &varid, &num1, &num2, &numAfter)) {
valueFlowForLoopSimplify(bodyStart, varid, num1, tokenlist, errorLogger, settings);
valueFlowForLoopSimplify(bodyStart, varid, num2, tokenlist, errorLogger, settings);
valueFlowForLoopSimplifyAfter(tok, varid, numAfter, tokenlist, errorLogger, settings);
} else {
std::map<unsigned int, MathLib::bigint> mem1, mem2;
if (valueFlowForLoop2(tok, &mem1, &mem2)) {
std::map<unsigned int, MathLib::bigint> mem1, mem2, memAfter;
if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {
std::map<unsigned int, MathLib::bigint>::const_iterator it;
for (it = mem1.begin(); it != mem1.end(); ++it)
valueFlowForLoopSimplify(bodyStart, it->first, it->second, tokenlist, errorLogger, settings);
for (it = mem2.begin(); it != mem2.end(); ++it)
valueFlowForLoopSimplify(bodyStart, it->first, it->second, tokenlist, errorLogger, settings);
for (it = memAfter.begin(); it != memAfter.end(); ++it)
valueFlowForLoopSimplifyAfter(tok, it->first, it->second, tokenlist, errorLogger, settings);
}
}
}

View File

@ -165,9 +165,7 @@ private:
TEST_CASE(simplifyKnownVariables21);
TEST_CASE(simplifyKnownVariables22);
TEST_CASE(simplifyKnownVariables23);
TEST_CASE(simplifyKnownVariables24);
TEST_CASE(simplifyKnownVariables25);
TEST_CASE(simplifyKnownVariables26);
TEST_CASE(simplifyKnownVariables27);
TEST_CASE(simplifyKnownVariables28);
TEST_CASE(simplifyKnownVariables29); // ticket #1811
@ -2070,51 +2068,6 @@ private:
simplifyKnownVariables(code));
}
void simplifyKnownVariables24() {
{
// This testcase is related to ticket #1596
const char code[] = "void foo()\n"
"{\n"
" int c;\n"
" for (c=0;c<10;++c) { }\n"
" a[c] = 0;\n"
"}\n";
ASSERT_EQUALS(
"void foo ( ) "
"{"
" int c ;"
" for ( c = 0 ; c < 10 ; ++ c ) { }"
" a [ 10 ] = 0 ; "
"}",
simplifyKnownVariables(code));
}
{
// #1692 - unknown counter value after for loop
const char code[] = "void foo(const char s[])\n"
"{\n"
" int x[3];\n"
" int i;\n"
" for (i = 0; i < 3; ++i) {\n"
" if (s[i]) break;\n"
" }"
" if (i < 3) x[i] = 0;\n"
"}\n";
ASSERT_EQUALS(
"void foo ( const char s [ ] ) "
"{"
" int x [ 3 ] ;"
" int i ;"
" for ( i = 0 ; i < 3 ; ++ i ) {"
" if ( s [ i ] ) { break ; }"
" }"
" if ( i < 3 ) { x [ i ] = 0 ; } "
"}",
simplifyKnownVariables(code));
}
}
void simplifyKnownVariables25() {
{
// This testcase is related to ticket #1646
@ -2167,24 +2120,6 @@ private:
}
}
void simplifyKnownVariables26() {
// This testcase is related to ticket #887
const char code[] = "void foo()\n"
"{\n"
" int i;\n"
" for (i=0;i<10;++i) { }\n"
" int k = i++;\n"
"}\n";
ASSERT_EQUALS(
"void foo ( ) "
"{"
" int i ;"
" for ( i = 0 ; i < 10 ; ++ i ) { }"
" int k ; k = 10 ; "
"}",
simplifyKnownVariables(code));
}
void simplifyKnownVariables27() {
// This testcase is related to ticket #1633
const char code[] = "void foo()\n"

View File

@ -1123,6 +1123,28 @@ private:
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
ASSERT_EQUALS(true, testValueOfX(code, 4U, 9));
// After loop
code = "void foo() {\n"
" int x;\n"
" for (x = 0; x < 10; x++) {}\n"
" a = x;\n"
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 10));
code = "void foo() {\n"
" int x;\n"
" for (x = 0; 2 * x < 20; x++) {}\n"
" a = x;\n"
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 10));
code = "void foo() {\n" // related with #887
" int x;\n"
" for (x = 0; x < 20; x++) {}\n"
" a = x++;\n"
"}\n";
TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 20));
// hang
code = "void f() {\n"
" for(int i = 0; i < 20; i++)\n"