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();
|
||||
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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue