From 54629ff22137cad99b3d82951e4016d90d6123f4 Mon Sep 17 00:00:00 2001 From: Reijo Tomperi Date: Fri, 4 Dec 2009 00:06:03 +0200 Subject: [PATCH] Fix #1037 (tokenizing a nested do while, while loop fails) http://sourceforge.net/apps/trac/cppcheck/ticket/1037 --- lib/token.cpp | 1 - lib/tokenize.cpp | 101 ++++++++++++++++++++++++++++-------------- lib/tokenize.h | 7 +++ test/testtokenize.cpp | 58 ++++++++++++++++++++++-- 4 files changed, 129 insertions(+), 38 deletions(-) diff --git a/lib/token.cpp b/lib/token.cpp index 090956d26..fa1f76e04 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -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); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 031afbad7..d36a10dca 100644 --- a/lib/tokenize.cpp +++ b/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()); } } } diff --git a/lib/tokenize.h b/lib/tokenize.h index 9b6d65f19..03f438956 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -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 &); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a35f5718b..e1a1f9168 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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[])