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(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);
|
||||||
}
|
}
|
||||||
|
|
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()
|
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 &);
|
||||||
|
|
||||||
|
|
|
@ -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[])
|
||||||
|
|
Loading…
Reference in New Issue