ValueFlow: Improved value flow after for loop
This commit is contained in:
parent
75ec97ad23
commit
5cdbe0f42d
|
@ -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()))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue