diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 96ffe32d5..9c44f595d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8086,13 +8086,13 @@ void Tokenizer::validate() const const Token * Tokenizer::findGarbageCode() const { for (const Token *tok = tokens(); tok; tok = tok->next()) { - if (Token::Match(tok, "if|while|for|switch")) { // switch (EXPR) { ... } + if (Token::Match(tok, "if|while|for|switch")) { // if|while|for|switch (EXPR) { ... } if (tok->previous() && !Token::Match(tok->previous(), ":|;|{|}|(|)|,|else|do")) return tok; + if (Token::Match(tok->previous(), "[(,]")) + continue; if (!Token::Match(tok->next(), "( !!)")) return tok; - if (tok->str() == "switch" && !Token::simpleMatch(tok->linkAt(1),") {")) - return tok->linkAt(1); if (tok->str() != "for") { if (isGarbageExpr(tok->next(), tok->linkAt(1))) return tok; diff --git a/test/testsuite.cpp b/test/testsuite.cpp index 9c4a3d836..4cc80497b 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -239,6 +239,18 @@ void TestFixture::assertThrowFail(const char *filename, unsigned int linenr) con } } +void TestFixture::assertNoThrowFail(const char *filename, unsigned int linenr) const +{ + ++fails_counter; + if (gcc_style_errors) { + errmsg << filename << ':' << linenr << " Assertion failed. " + << "Unexpected exception was thrown" << std::endl; + } else { + errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl + << "Unexpected exception was thrown" << std::endl << "_____" << std::endl; + } +} + void TestFixture::complainMissingLib(const char* libname) const { missingLibs.insert(libname); diff --git a/test/testsuite.h b/test/testsuite.h index cb3943f62..557fd6312 100644 --- a/test/testsuite.h +++ b/test/testsuite.h @@ -61,6 +61,7 @@ protected: long long current, long long actual) const; void assertThrow(const char *filename, unsigned int linenr) const; void assertThrowFail(const char *filename, unsigned int linenr) const; + void assertNoThrowFail(const char *filename, unsigned int linenr) const; void complainMissingLib(const char* libname) const; void processOptions(const options& args); @@ -85,6 +86,7 @@ extern std::ostringstream warnings; #define ASSERT_EQUALS_DOUBLE( EXPECTED , ACTUAL ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL) #define ASSERT_EQUALS_MSG( EXPECTED , ACTUAL, MSG ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL, MSG) #define ASSERT_THROW( CMD, EXCEPTION ) try { CMD ; assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&) { } catch (...) { assertThrowFail(__FILE__, __LINE__); } +#define ASSERT_NO_THROW( CMD ) try { CMD ; } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } #define TODO_ASSERT_THROW( CMD, EXCEPTION ) try { CMD ; } catch (const EXCEPTION&) { } catch (...) { assertThrow(__FILE__, __LINE__); } #define TODO_ASSERT( CONDITION ) { bool condition=CONDITION; todoAssertEquals(__FILE__, __LINE__, true, false, condition); } #define TODO_ASSERT_EQUALS( WANTED , CURRENT , ACTUAL ) todoAssertEquals(__FILE__, __LINE__, WANTED, CURRENT, ACTUAL) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 467f52335..03f574de1 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -456,6 +456,10 @@ private: TEST_CASE(removeMacroInClassDef); // #6058 TEST_CASE(sizeofAddParentheses); + + // Make sure the Tokenizer::findGarbageCode() does not have false positives + // The TestGarbage ensures that there are true positives + TEST_CASE(findGarbageCode); } std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { @@ -8379,6 +8383,17 @@ private: ASSERT_EQUALS("sizeof ( a [ 2 ] . b ) + 3 ;", tokenizeAndStringify("sizeof a[2].b+3;")); ASSERT_EQUALS("f ( 0 , sizeof ( ptr . bar ) ) ;", tokenizeAndStringify("f(0, sizeof ptr->bar );")); } + + void findGarbageCode() { // Make sure the Tokenizer::findGarbageCode() does not have FPs + // before if|for|while|switch + ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }")) + ASSERT_NO_THROW(tokenizeAndStringify("void f() { label: switch (a) {} }")); + + // TODO ASSERT_NO_THROW(tokenizeAndStringify("void f() { MACRO(switch); }")); + // TODO ASSERT_NO_THROW(tokenizeAndStringify("void f() { MACRO(x,switch); }")); + + ASSERT_NO_THROW(tokenizeAndStringify("void f() { switch (a) int b; }")); + } }; REGISTER_TEST(TestTokenizer)