Fixed #4911 (segfault, assignment in do ... while, 1.61dev)

This commit is contained in:
Lucas Manuel Rodriguez 2013-07-28 11:58:14 +02:00 committed by Daniel Marjamäki
parent 36ef34a2cf
commit 09f4d3732a
3 changed files with 51 additions and 23 deletions

View File

@ -3541,7 +3541,7 @@ bool Tokenizer::simplifyTokenList()
elseif();
simplifyErrNoInWhile();
simplifyIfAssign();
simplifyIfAndWhileAssign();
simplifyRedundantParentheses();
simplifyIfNot();
simplifyIfNotNull();
@ -3551,7 +3551,7 @@ bool Tokenizer::simplifyTokenList()
simplifyWhile0();
simplifyFuncInWhile();
simplifyIfAssign(); // could be affected by simplifyIfNot
simplifyIfAndWhileAssign(); // Could be affected by simplifyIfNot
bool modified = true;
while (modified) {
@ -5585,19 +5585,21 @@ void Tokenizer::simplifyStdType()
}
}
void Tokenizer::simplifyIfAssign()
void Tokenizer::simplifyIfAndWhileAssign()
{
// See also simplifyFunctionAssign
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") &&
!Token::Match(tok->next(), "if|while ( !| (| %var% . %var% ="))
continue;
// simplifying a "while" condition ?
// simplifying a "while(cond) { }" condition ?
const bool iswhile(tok->next()->str() == "while");
// delete the "if"
// simplifying a "do { } while(cond);" condition ?
const bool isDoWhile = iswhile && Token::Match(tok, "}") && Token::Match(tok->link()->previous(), "do");
Token* openBraceTok = tok->link();
// delete the "if|while"
tok->deleteNext();
// Remember if there is a "!" or not. And delete it if there are.
@ -5641,12 +5643,22 @@ void Tokenizer::simplifyIfAssign()
if (isNot)
tok2->next()->insertToken("!");
tok2->insertToken(iswhile ? "while" : "if");
if (isDoWhile) {
tok2->insertToken("}");
Token::createMutualLinks(openBraceTok, tok2->next());
}
tok2->insertToken(";");
// If it's a while loop.. insert the assignment in the loop
if (iswhile) {
// delete the extra "}"
if (isDoWhile)
tok->deleteThis();
// If it's a while loop, insert the assignment in the loop
if (iswhile && !isDoWhile) {
unsigned int indentlevel = 0;
Token *tok3 = tok2;
for (; tok3; tok3 = tok3->next()) {
if (tok3->str() == "{")
++indentlevel;
@ -5682,7 +5694,6 @@ void Tokenizer::simplifyIfAssign()
}
}
void Tokenizer::simplifyVariableMultipleAssign()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
@ -8856,7 +8867,7 @@ void Tokenizer::simplifyAssignmentInFunctionCall()
// Find 'foo(var='. Exclude 'assert(var=' to allow tests to check that assert(...) does not contain side-effects
else if (Token::Match(tok, "[;{}] %var% ( %var% =") &&
Token::simpleMatch(tok->linkAt(2), ") ;") &&
tok->next()->str() != "assert") {
!Token::Match(tok->next(), "assert|while")) {
const std::string funcname(tok->next()->str());
const Token * const vartok = tok->tokAt(3);

View File

@ -245,10 +245,12 @@ public:
void simplifyCompoundAssignment();
/**
* simplify if-assignments
* Simplify assignments in "if" and "while" conditions
* Example: "if(a=b);" => "a=b;if(a);"
* Example: "while(a=b) { f(a); }" => "a = b; while(a){ f(a); a = b; }"
* Example: "do { f(a); } while(a=b);" => "do { f(a); a = b; } while(a);"
*/
void simplifyIfAssign();
void simplifyIfAndWhileAssign();
/**
* Simplify multiple assignments.

View File

@ -150,6 +150,7 @@ private:
TEST_CASE(whileAssign1);
TEST_CASE(whileAssign2);
TEST_CASE(whileAssign3); // varid
TEST_CASE(doWhileAssign); // varid
// "if(0==x)" => "if(!x)"
TEST_CASE(ifnot);
@ -495,7 +496,7 @@ private:
}
void simplifyTokenList1() {
// #1717 : The simplifyErrNoInWhile needs to be used before simplifyIfAssign..
// #1717 : The simplifyErrNoInWhile needs to be used before simplifyIfAndWhileAssign..
ASSERT_EQUALS("; x = f ( ) ; while ( x == -1 ) { x = f ( ) ; }",
tok(";while((x=f())==-1 && errno==EINTR){}",true));
}
@ -2533,7 +2534,7 @@ private:
}
std::string simplifyIfAssign(const char code[]) {
std::string simplifyIfAndWhileAssign(const char code[]) {
errout.str("");
Settings settings;
// tokenize..
@ -2541,17 +2542,17 @@ private:
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.simplifyIfAssign();
tokenizer.simplifyIfAndWhileAssign();
return tokenizer.tokens()->stringifyList(0, false);
}
void ifassign1() {
ASSERT_EQUALS("; a = b ; if ( a ) { ; }", simplifyIfAssign(";if(a=b);"));
ASSERT_EQUALS("; a = b ( ) ; if ( a ) { ; }", simplifyIfAssign(";if((a=b()));"));
ASSERT_EQUALS("; a = b ( ) ; if ( ! ( a ) ) { ; }", simplifyIfAssign(";if(!(a=b()));"));
ASSERT_EQUALS("; a . x = b ( ) ; if ( ! ( a . x ) ) { ; }", simplifyIfAssign(";if(!(a->x=b()));"));
ASSERT_EQUALS("void f ( ) { A ( ) a = b ; if ( a ) { ; } }", simplifyIfAssign("void f() { A() if(a=b); }"));
ASSERT_EQUALS("; a = b ; if ( a ) { ; }", simplifyIfAndWhileAssign(";if(a=b);"));
ASSERT_EQUALS("; a = b ( ) ; if ( a ) { ; }", simplifyIfAndWhileAssign(";if((a=b()));"));
ASSERT_EQUALS("; a = b ( ) ; if ( ! ( a ) ) { ; }", simplifyIfAndWhileAssign(";if(!(a=b()));"));
ASSERT_EQUALS("; a . x = b ( ) ; if ( ! ( a . x ) ) { ; }", simplifyIfAndWhileAssign(";if(!(a->x=b()));"));
ASSERT_EQUALS("void f ( ) { A ( ) a = b ; if ( a ) { ; } }", simplifyIfAndWhileAssign("void f() { A() if(a=b); }"));
ASSERT_EQUALS("void foo ( int a ) { a = b ( ) ; if ( 0 <= a ) { ; } }", tok("void foo(int a) {if((a=b())>=0);}"));
TODO_ASSERT_EQUALS("void foo ( A a ) { a . c = b ( ) ; if ( 0 <= a . c ) { ; } }",
"void foo ( A a ) { a . c = b ( ) ; if ( a . c >= 0 ) { ; } }",
@ -2580,8 +2581,8 @@ private:
}
void whileAssign1() {
ASSERT_EQUALS("; a = b ; while ( a ) { b = 0 ; a = b ; }", simplifyIfAssign(";while(a=b) { b = 0; }"));
ASSERT_EQUALS("; a . b = c ; while ( a . b ) { c = 0 ; a . b = c ; }", simplifyIfAssign(";while(a.b=c) { c=0; }"));
ASSERT_EQUALS("; a = b ; while ( a ) { b = 0 ; a = b ; }", simplifyIfAndWhileAssign(";while(a=b) { b = 0; }"));
ASSERT_EQUALS("; a . b = c ; while ( a . b ) { c = 0 ; a . b = c ; }", simplifyIfAndWhileAssign(";while(a.b=c) { c=0; }"));
ASSERT_EQUALS("struct hfs_bnode * node ; "
"struct hfs_btree * tree ; "
"node = tree . node_hash [ i ++ ] ; "
@ -2619,6 +2620,20 @@ private:
"4: }\n", tokenizeDebugListing(code, true, "test.c"));
}
void doWhileAssign() {
ASSERT_EQUALS("; do { a = b ; } while ( a ) ;", simplifyIfAndWhileAssign(";do { } while(a=b);"));
ASSERT_EQUALS("; do { a . a = 0 ; a . b = c ; } while ( a . b ) ;", simplifyIfAndWhileAssign(";do { a.a = 0; } while(a.b=c);"));
ASSERT_EQUALS("struct hfs_bnode * node ; "
"struct hfs_btree * tree ; "
"do { node = tree . node_hash [ i ++ ] ; } while ( node ) ;",
tok("struct hfs_bnode *node;"
"struct hfs_btree *tree;"
"do { } while((node = tree->node_hash[i++]));"));
ASSERT_EQUALS("char * s ; do { s = new char [ 10 ] ; } while ( ! s ) ;",
tok("char *s; do { } while (0 == (s=new char[10]));"));
// #4911
ASSERT_EQUALS("; do { current = f ( ) ; } while ( current ) ;", simplifyIfAndWhileAssign(";do { } while((current=f()) != NULL);"));
}
void ifnot() {
ASSERT_EQUALS("if ( ! x ) { ; }", tok("if(0==x);", false));