Fix #1037 (tokenizing a nested do while, while loop fails)
http://sourceforge.net/apps/trac/cppcheck/ticket/1037
This commit is contained in:
parent
2b980f9abe
commit
54629ff221
|
@ -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);
|
||||
}
|
||||
|
|
101
lib/tokenize.cpp
101
lib/tokenize.cpp
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 &);
|
||||
|
||||
|
|
|
@ -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[])
|
||||
|
|
Loading…
Reference in New Issue