diff --git a/src/token.cpp b/src/token.cpp index 3b955dd11..51635a31d 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -302,7 +302,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) if (str[0] == '%') { // Any symbolname.. - if (strcmp(str, "%var%") == 0 || strcmp(str, "%type%") == 0) + if (strcmp(str, "%var%") == 0) { if (!tok->isName()) return false; @@ -310,6 +310,18 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) patternIdentified = true; } + // Type.. + if (strcmp(str, "%type%") == 0) + { + if (!tok->isName()) + return false; + + if (tok->str() == "delete") + return false; + + patternIdentified = true; + } + // Accept any token else if (strcmp(str, "%any%") == 0) { diff --git a/src/token.h b/src/token.h index 4383e09a2..0a3995175 100644 --- a/src/token.h +++ b/src/token.h @@ -77,6 +77,7 @@ public: * Possible patterns * "%any%" any token * "%var%" any token which is a name or type e.g. "hello" or "int" + * "%type%" Anything that can be a variable type, e.g. "int", but not "delete". * "%num%" Any numeric token, e.g. "23" * "%bool%" true or false * "%str%" Any token starting with "-character (C-string). @@ -105,6 +106,7 @@ public: bool isNumber() const; bool isBoolean() const; bool isStandardType() const; + static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId = 0); /** diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 298fab1f9..d52572ef8 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -1483,6 +1483,7 @@ void Tokenizer::simplifyTokenList() modified |= simplifyQuestionMark(); } + simplifyCommaNearKeyWords(); createLinks(); if (_settings._debug) { @@ -2913,4 +2914,22 @@ void Tokenizer::syntaxError(const Token *tok, char c) } +bool Tokenizer::simplifyCommaNearKeyWords() +{ + bool ret = false; + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (tok->str() != ",") + continue; + // We must not accept just any keyword, e.g. accepting int + // would cause function parameters to corrupt. + if (!Token::Match(tok->next(), "delete")) + continue; + + tok->str(";"); + ret = true; + } + + return ret; +} diff --git a/src/tokenize.h b/src/tokenize.h index 9ebe2ea7f..f7f3bb8cf 100644 --- a/src/tokenize.h +++ b/src/tokenize.h @@ -97,6 +97,8 @@ public: /** * Simplify variable declarations + * @return true if something is modified + * false if nothing is done. */ bool simplifyVarDecl(); @@ -109,27 +111,43 @@ public: /** * Simplify question mark - colon operator * Example: 0 ? (2/0) : 0 => 0 + * @return true if something is modified + * false if nothing is done. */ bool simplifyQuestionMark(); /** * simplify if-assignments.. * Example: "if(a=b);" => "a=b;if(a);" + * @return true if something is modified + * false if nothing is done. */ bool simplifyIfAssign(); /** * simplify if-not.. * Example: "if(0==x);" => "if(!x);" + * @return true if something is modified + * false if nothing is done. */ bool simplifyIfNot(); /** * simplify the "not" keyword to "!" * Example: "if (not p)" => "if (!p)" + * @return true if something is modified + * false if nothing is done. */ bool simplifyNot(); + /** + * Simplify comma near keywords into a semicolon + * Example: "delete a, delete b" => "delete a; delete b;" + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyCommaNearKeyWords(); + protected: /** Add braces to an if-block diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index d84ca8eac..52f80e1c5 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -105,6 +105,7 @@ private: // Simplify "not" to "!" (#345) TEST_CASE(not1); + TEST_CASE(comma_keyword); } std::string tok(const char code[]) @@ -932,6 +933,15 @@ private: ASSERT_EQUALS("void foo ( not i )", simplifyNot("void foo ( not i )")); } + void comma_keyword() + { + const char code[] = "void foo()\n" + "{\n" + " char *a, *b;\n" + " delete a, delete b;\n" + "}\n"; + ASSERT_EQUALS(" void foo ( ) { char * a ; char * b ; delete a ; delete b ; }", sizeof_(code)); + } };