Fix #1037 (tokenizing a nested do while, while loop fails)

http://sourceforge.net/apps/trac/cppcheck/ticket/1037
This commit is contained in:
Reijo Tomperi 2009-12-04 00:06:03 +02:00
parent 2b980f9abe
commit 54629ff221
4 changed files with 129 additions and 38 deletions

View File

@ -599,7 +599,6 @@ void Token::createMutualLinks(Token *begin, Token *end)
assert(begin != NULL);
assert(end != NULL);
assert(begin != end);
begin->link(end);
end->link(begin);
}

View File

@ -2399,46 +2399,79 @@ void Tokenizer::simplifyIfAddBraces()
}
}
bool Tokenizer::simplifyDoWhileAddBracesHelper(Token *tok)
{
if (Token::Match(tok->next(), "[),]"))
{
// fix for #988
return false;
}
Token *tok1 = tok; // token with "do"
Token *tok2 = NULL; // token with "while"
Token *tok3 = tok->next();
// skip loop body
bool result = false;
while (tok3)
{
if (tok3->str() == "{")
{
tok3 = tok3->link();
}
else if (tok3->str() == "while")
{
tok2 = tok3;
break;
}
else if (Token::Match(tok3, "do {"))
{
// Skip do{}while inside the current "do"
tok3 = tok3->next()->link();
if (Token::simpleMatch(tok3->next(), "while"))
tok3 = tok3->next();
}
else if (Token::Match(tok3, "do !!{") &&
!Token::Match(tok3->next(), "[),]"))
{
// Handle do-while inside the current "do"
// first and return true to get the outer
// "do" to be handled later.
tok1 = tok3;
result = true;
}
tok3 = tok3->next();
}
if (tok2)
{
// insert "{" after "do"
tok1->insertToken("{");
// insert "}" before "while"
tok2->previous()->insertToken("}");
Token::createMutualLinks(tok1->next(), tok2->previous());
}
else
result = false;
return result;
}
void Tokenizer::simplifyDoWhileAddBraces()
{
for (Token *tok = _tokens; tok; tok = (tok ? tok->next() : NULL))
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (! Token::Match(tok, "do !!{"))
if (Token::Match(tok, "do !!{"))
{
continue;
}
if (tok->next()->str() == ")")
{
// fix for #988
continue;
}
Token *tok1 = tok; // token with "do"
Token *tok2 = NULL; // token with "while"
Token *tok3 = tok;
// skip loop body
while (tok3)
{
if (tok3->str() == "while")
while (simplifyDoWhileAddBracesHelper(tok))
{
tok2 = tok3;
break;
// Call until the function returns false to
// handle do-while inside do-while
}
tok3 = tok3->next();
}
if (tok2)
{
// insert "{" after "do"
tok1->insertToken("{");
// insert "}" before "while"
tok2->previous()->insertToken("}");
Token::createMutualLinks(tok1->next(), tok2->previous());
}
}
}

View File

@ -360,6 +360,13 @@ private:
*/
bool validate() const;
/**
* Helper function for simplifyDoWhileAddBraces()
* @param tok This must be a "do" token, which is
* not followed by "{".
*/
bool simplifyDoWhileAddBracesHelper(Token *tok);
/** Disable assignment operator */
void operator=(const Tokenizer &);

View File

@ -589,10 +589,62 @@ private:
void doWhileAddBraces()
{
const char code[] = "do ; while (0);";
const char result[] = "do { ; } while ( false ) ;";
{
const char code[] = "do ; while (0);";
const char result[] = "do { ; } while ( false ) ;";
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
}
{
const char code[] = "UNKNOWN_MACRO ( do ) ; while ( a -- ) ;";
const char result[] = "UNKNOWN_MACRO ( do ) ; while ( a -- ) { ; }";
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
}
{
const char code[] = "UNKNOWN_MACRO ( do , foo ) ; while ( a -- ) ;";
const char result[] = "UNKNOWN_MACRO ( do , foo ) ; while ( a -- ) { ; }";
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
}
{
const char code[] = "void foo ( int c , int d ) {\n"
" do\n"
" if ( c ) {\n"
" while ( c ) { c -- ; }\n"
" }\n"
" while ( -- d > 0 ) ;\n"
" return 0 ;\n"
"}\n";
const char result[] = "void foo ( int c , int d ) {\n"
"do {\n"
"if ( c ) {\n"
"while ( c ) { c -- ; }\n"
"} }\n"
"while ( -- d > 0 ) ;\n"
"return 0 ;\n"
"}";
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
}
{
const char code[] = "void foo ( int c , int d ) {\n"
" do\n"
" do c -- ; while ( c ) ;\n"
" while ( -- d > 0 ) ;\n"
" return 0 ;\n"
"}\n";
const char result[] = "void foo ( int c , int d ) {\n"
"do {\n"
"do { c -- ; } while ( c ) ; }\n"
"while ( -- d > 0 ) ;\n"
"return 0 ;\n"
"}";
ASSERT_EQUALS(result, tokenizeAndStringify(code, true));
}
}
std::string simplifyKnownVariables(const char code[])