Fixed #4911 (segfault, assignment in do ... while, 1.61dev)
This commit is contained in:
parent
36ef34a2cf
commit
09f4d3732a
|
@ -3541,7 +3541,7 @@ bool Tokenizer::simplifyTokenList()
|
||||||
|
|
||||||
elseif();
|
elseif();
|
||||||
simplifyErrNoInWhile();
|
simplifyErrNoInWhile();
|
||||||
simplifyIfAssign();
|
simplifyIfAndWhileAssign();
|
||||||
simplifyRedundantParentheses();
|
simplifyRedundantParentheses();
|
||||||
simplifyIfNot();
|
simplifyIfNot();
|
||||||
simplifyIfNotNull();
|
simplifyIfNotNull();
|
||||||
|
@ -3551,7 +3551,7 @@ bool Tokenizer::simplifyTokenList()
|
||||||
simplifyWhile0();
|
simplifyWhile0();
|
||||||
simplifyFuncInWhile();
|
simplifyFuncInWhile();
|
||||||
|
|
||||||
simplifyIfAssign(); // could be affected by simplifyIfNot
|
simplifyIfAndWhileAssign(); // Could be affected by simplifyIfNot
|
||||||
|
|
||||||
bool modified = true;
|
bool modified = true;
|
||||||
while (modified) {
|
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()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") &&
|
if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") &&
|
||||||
!Token::Match(tok->next(), "if|while ( !| (| %var% . %var% ="))
|
!Token::Match(tok->next(), "if|while ( !| (| %var% . %var% ="))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// simplifying a "while" condition ?
|
// simplifying a "while(cond) { }" condition ?
|
||||||
const bool iswhile(tok->next()->str() == "while");
|
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();
|
tok->deleteNext();
|
||||||
|
|
||||||
// Remember if there is a "!" or not. And delete it if there are.
|
// Remember if there is a "!" or not. And delete it if there are.
|
||||||
|
@ -5641,12 +5643,22 @@ void Tokenizer::simplifyIfAssign()
|
||||||
if (isNot)
|
if (isNot)
|
||||||
tok2->next()->insertToken("!");
|
tok2->next()->insertToken("!");
|
||||||
tok2->insertToken(iswhile ? "while" : "if");
|
tok2->insertToken(iswhile ? "while" : "if");
|
||||||
|
if (isDoWhile) {
|
||||||
|
tok2->insertToken("}");
|
||||||
|
Token::createMutualLinks(openBraceTok, tok2->next());
|
||||||
|
}
|
||||||
|
|
||||||
tok2->insertToken(";");
|
tok2->insertToken(";");
|
||||||
|
|
||||||
// If it's a while loop.. insert the assignment in the loop
|
// delete the extra "}"
|
||||||
if (iswhile) {
|
if (isDoWhile)
|
||||||
|
tok->deleteThis();
|
||||||
|
|
||||||
|
// If it's a while loop, insert the assignment in the loop
|
||||||
|
if (iswhile && !isDoWhile) {
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
Token *tok3 = tok2;
|
Token *tok3 = tok2;
|
||||||
|
|
||||||
for (; tok3; tok3 = tok3->next()) {
|
for (; tok3; tok3 = tok3->next()) {
|
||||||
if (tok3->str() == "{")
|
if (tok3->str() == "{")
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
|
@ -5682,7 +5694,6 @@ void Tokenizer::simplifyIfAssign()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Tokenizer::simplifyVariableMultipleAssign()
|
void Tokenizer::simplifyVariableMultipleAssign()
|
||||||
{
|
{
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
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
|
// 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% =") &&
|
else if (Token::Match(tok, "[;{}] %var% ( %var% =") &&
|
||||||
Token::simpleMatch(tok->linkAt(2), ") ;") &&
|
Token::simpleMatch(tok->linkAt(2), ") ;") &&
|
||||||
tok->next()->str() != "assert") {
|
!Token::Match(tok->next(), "assert|while")) {
|
||||||
const std::string funcname(tok->next()->str());
|
const std::string funcname(tok->next()->str());
|
||||||
const Token * const vartok = tok->tokAt(3);
|
const Token * const vartok = tok->tokAt(3);
|
||||||
|
|
||||||
|
|
|
@ -245,10 +245,12 @@ public:
|
||||||
void simplifyCompoundAssignment();
|
void simplifyCompoundAssignment();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* simplify if-assignments
|
* Simplify assignments in "if" and "while" conditions
|
||||||
* Example: "if(a=b);" => "a=b;if(a);"
|
* 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.
|
* Simplify multiple assignments.
|
||||||
|
|
|
@ -150,6 +150,7 @@ private:
|
||||||
TEST_CASE(whileAssign1);
|
TEST_CASE(whileAssign1);
|
||||||
TEST_CASE(whileAssign2);
|
TEST_CASE(whileAssign2);
|
||||||
TEST_CASE(whileAssign3); // varid
|
TEST_CASE(whileAssign3); // varid
|
||||||
|
TEST_CASE(doWhileAssign); // varid
|
||||||
|
|
||||||
// "if(0==x)" => "if(!x)"
|
// "if(0==x)" => "if(!x)"
|
||||||
TEST_CASE(ifnot);
|
TEST_CASE(ifnot);
|
||||||
|
@ -495,7 +496,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyTokenList1() {
|
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 ( ) ; }",
|
ASSERT_EQUALS("; x = f ( ) ; while ( x == -1 ) { x = f ( ) ; }",
|
||||||
tok(";while((x=f())==-1 && errno==EINTR){}",true));
|
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("");
|
errout.str("");
|
||||||
Settings settings;
|
Settings settings;
|
||||||
// tokenize..
|
// tokenize..
|
||||||
|
@ -2541,17 +2542,17 @@ private:
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
|
||||||
tokenizer.simplifyIfAssign();
|
tokenizer.simplifyIfAndWhileAssign();
|
||||||
|
|
||||||
return tokenizer.tokens()->stringifyList(0, false);
|
return tokenizer.tokens()->stringifyList(0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifassign1() {
|
void ifassign1() {
|
||||||
ASSERT_EQUALS("; a = b ; if ( a ) { ; }", simplifyIfAssign(";if(a=b);"));
|
ASSERT_EQUALS("; a = b ; if ( a ) { ; }", simplifyIfAndWhileAssign(";if(a=b);"));
|
||||||
ASSERT_EQUALS("; a = b ( ) ; if ( a ) { ; }", simplifyIfAssign(";if((a=b()));"));
|
ASSERT_EQUALS("; a = b ( ) ; if ( a ) { ; }", simplifyIfAndWhileAssign(";if((a=b()));"));
|
||||||
ASSERT_EQUALS("; a = b ( ) ; if ( ! ( a ) ) { ; }", simplifyIfAssign(";if(!(a=b()));"));
|
ASSERT_EQUALS("; a = b ( ) ; if ( ! ( a ) ) { ; }", simplifyIfAndWhileAssign(";if(!(a=b()));"));
|
||||||
ASSERT_EQUALS("; a . x = b ( ) ; if ( ! ( a . x ) ) { ; }", simplifyIfAssign(";if(!(a->x=b()));"));
|
ASSERT_EQUALS("; a . x = b ( ) ; if ( ! ( a . x ) ) { ; }", simplifyIfAndWhileAssign(";if(!(a->x=b()));"));
|
||||||
ASSERT_EQUALS("void f ( ) { A ( ) a = b ; if ( a ) { ; } }", simplifyIfAssign("void f() { A() if(a=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);}"));
|
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 ) { ; } }",
|
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 ) { ; } }",
|
"void foo ( A a ) { a . c = b ( ) ; if ( a . c >= 0 ) { ; } }",
|
||||||
|
@ -2580,8 +2581,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void whileAssign1() {
|
void whileAssign1() {
|
||||||
ASSERT_EQUALS("; a = b ; while ( a ) { b = 0 ; a = b ; }", simplifyIfAssign(";while(a=b) { b = 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 ; }", simplifyIfAssign(";while(a.b=c) { c=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 ; "
|
ASSERT_EQUALS("struct hfs_bnode * node ; "
|
||||||
"struct hfs_btree * tree ; "
|
"struct hfs_btree * tree ; "
|
||||||
"node = tree . node_hash [ i ++ ] ; "
|
"node = tree . node_hash [ i ++ ] ; "
|
||||||
|
@ -2619,6 +2620,20 @@ private:
|
||||||
"4: }\n", tokenizeDebugListing(code, true, "test.c"));
|
"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() {
|
void ifnot() {
|
||||||
ASSERT_EQUALS("if ( ! x ) { ; }", tok("if(0==x);", false));
|
ASSERT_EQUALS("if ( ! x ) { ; }", tok("if(0==x);", false));
|
||||||
|
|
Loading…
Reference in New Issue