diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d61b06f21..b2dd2a65d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1675,6 +1675,8 @@ bool Tokenizer::tokenize(std::istream &code, if (!simplifyAddBraces()) return false; + sizeofAddParentheses(); + // Combine tokens.. combineOperators(); @@ -3207,6 +3209,42 @@ void Tokenizer::createLinks2() } } +void Tokenizer::sizeofAddParentheses() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "sizeof %var%")) { + Token *tempToken = tok->next(); + while (Token::Match(tempToken, "%var%")) { + while (tempToken && tempToken->next() && tempToken->next()->str() == "[") + tempToken = tempToken->next()->link(); + if (!tempToken || !tempToken->next()) + break; + + if (Token::Match(tempToken->next(), ". %var%")) { + // We are checking a class or struct, search next varname + tempToken = tempToken->tokAt(2); + continue; + } else if (tempToken->next()->type() == Token::eIncDecOp) { + // We have variable++ or variable--, the sizeof argument + // ends after the op + tempToken = tempToken->next(); + } else if (Token::Match(tempToken->next(), "[),;}]")) { + ; + } else { + break; + } + + // Ok. Add ( after sizeof and ) after tempToken + tok->insertToken("("); + tempToken->insertToken(")"); + Token::createMutualLinks(tok->next(), tempToken->next()); + break; + } + } + } + +} + bool Tokenizer::simplifySizeof() { // Locate variable declarations and calculate the size diff --git a/lib/tokenize.h b/lib/tokenize.h index 9842012b4..a98bc8e1b 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -196,6 +196,9 @@ public: */ void simplifyRealloc(); + /** Add parentheses for sizeof: sizeof x => sizeof(x) */ + void sizeofAddParentheses(); + /** * Replace sizeof() to appropriate size. * @return true if modifications to token-list are done. diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 5e45039d2..404082962 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -803,6 +803,13 @@ private: "}", true, "test.cpp", false); ASSERT_EQUALS("", errout.str()); + check("void f(type* p) {\n" // #4983 + " x(sizeof p[0]);\n" + " if (!p)\n" + " ;\n" + "}", false, "test.cpp", false); + ASSERT_EQUALS("", errout.str()); + // #3023 - checked deref check("void f(struct ABC *abc) {\n" " WARN_ON(!abc || abc->x == 0);\n" diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 327a8bf37..83580a3c5 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -579,7 +579,7 @@ private: void tokenize2() { const std::string code("{ sizeof a, sizeof b }"); - ASSERT_EQUALS("{ sizeof a , sizeof b }", tokenizeAndStringify(code.c_str())); + ASSERT_EQUALS("{ sizeof ( a ) , sizeof ( b ) }", tokenizeAndStringify(code.c_str())); } void tokenize3() {