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(begin != NULL);
assert(end != NULL); assert(end != NULL);
assert(begin != end); assert(begin != end);
begin->link(end); begin->link(end);
end->link(begin); 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() 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; while (simplifyDoWhileAddBracesHelper(tok))
}
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")
{ {
tok2 = tok3; // Call until the function returns false to
break; // 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; 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 */ /** Disable assignment operator */
void operator=(const Tokenizer &); void operator=(const Tokenizer &);

View File

@ -589,10 +589,62 @@ private:
void doWhileAddBraces() 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[]) std::string simplifyKnownVariables(const char code[])