diff --git a/lib/checkinternal.cpp b/lib/checkinternal.cpp index bbb669dbe..1a2b0ec84 100644 --- a/lib/checkinternal.cpp +++ b/lib/checkinternal.cpp @@ -77,6 +77,8 @@ void CheckInternal::checkTokenMatchPatterns() } } } + if (pattern.find("||") != std::string::npos || pattern.find(" | ") != std::string::npos || pattern[0] == '|' || (pattern[pattern.length() - 1] == '|' && pattern[pattern.length() - 2] == ' ')) + orInComplexPattern(tok, pattern, funcname); // Check for signs of complex patterns if (pattern.find_first_of("[|%") != std::string::npos) @@ -321,4 +323,10 @@ void CheckInternal::redundantNextPreviousError(const Token* tok, const std::stri "Call to 'Token::" + func1 + "()' followed by 'Token::" + func2 + "()' can be simplified."); } +void CheckInternal::orInComplexPattern(const Token* tok, const std::string& pattern, const std::string &funcname) +{ + reportError(tok, Severity::error, "orInComplexPattern", + "Token::" + funcname + "() pattern \"" + pattern + "\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\"."); +} + #endif // #ifdef CHECK_INTERNAL diff --git a/lib/checkinternal.h b/lib/checkinternal.h index 1bcba76d0..77372665d 100644 --- a/lib/checkinternal.h +++ b/lib/checkinternal.h @@ -77,6 +77,7 @@ private: void missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname); void unknownPatternError(const Token* tok, const std::string& pattern); void redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2); + void orInComplexPattern(const Token *tok, const std::string &pattern, const std::string &funcname); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { CheckInternal c(0, settings, errorLogger); @@ -86,6 +87,7 @@ private: c.missingPercentCharacterError(0, "%num", "Match"); c.unknownPatternError(0, "%typ"); c.redundantNextPreviousError(0, "previous", "next"); + c.orInComplexPattern(0, "||", "Match"); } static std::string myName() { diff --git a/test/testinternal.cpp b/test/testinternal.cpp index 1a80e60fe..07161beea 100644 --- a/test/testinternal.cpp +++ b/test/testinternal.cpp @@ -41,6 +41,7 @@ private: TEST_CASE(redundantNextPrevious) TEST_CASE(internalError) TEST_CASE(invalidMultiCompare); + TEST_CASE(orInComplexPattern); } void check(const char code[]) { @@ -342,6 +343,38 @@ private: "}"); ASSERT_EQUALS("", errout.str()); } + + void orInComplexPattern() { + check("void f() {\n" + " Token::Match(tok, \"||\");\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"||\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str()); + + check("void f() {\n" + " Token::Match(tok, \"|\");\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"|\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str()); + + check("void f() {\n" + " Token::Match(tok, \"[|+-]\");\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" + " Token::Match(tok, \"foo | bar\");\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"foo | bar\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str()); + + check("void f() {\n" + " Token::Match(tok, \"foo |\");\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"foo |\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str()); + + check("void f() {\n" + " Token::Match(tok, \"bar foo|\");\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } }; REGISTER_TEST(TestInternal)