diff --git a/lib/checkother.cpp b/lib/checkother.cpp index d2a0bbde8..690094586 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1739,7 +1739,7 @@ static bool isVarDeclOp(const Token* tok) return isType(typetok, Token::Match(vartok, "%var%")); } -static bool isConstStatement(const Token *tok) +static bool isConstStatement(const Token *tok, bool cpp) { if (!tok) return false; @@ -1759,11 +1759,13 @@ static bool isConstStatement(const Token *tok) if (Token::simpleMatch(tok->previous(), "sizeof (")) return true; if (isCPPCast(tok)) - return isConstStatement(tok->astOperand2()); + return isWithoutSideEffects(cpp, tok) && isConstStatement(tok->astOperand2(), cpp); + else if (tok->isCast()) + return isWithoutSideEffects(cpp, tok->astOperand1()) && isConstStatement(tok->astOperand1(), cpp); if (Token::Match(tok, "( %type%")) - return isConstStatement(tok->astOperand1()); + return isConstStatement(tok->astOperand1(), cpp); if (Token::simpleMatch(tok, ",")) - return isConstStatement(tok->astOperand2()); + return isConstStatement(tok->astOperand2(), cpp); return false; } @@ -1771,6 +1773,8 @@ static bool isVoidStmt(const Token *tok) { if (Token::simpleMatch(tok, "( void")) return true; + if (isCPPCast(tok) && tok->astOperand1() && Token::Match(tok->astOperand1()->next(), "< void *| >")) + return true; const Token *tok2 = tok; while (tok2->astOperand1()) tok2 = tok2->astOperand1(); @@ -1838,7 +1842,7 @@ void CheckOther::checkIncompleteStatement() // Skip statement expressions if (Token::simpleMatch(rtok, "; } )")) continue; - if (!isConstStatement(tok)) + if (!isConstStatement(tok, mTokenizer->isCPP())) continue; if (isVoidStmt(tok)) continue; @@ -1864,8 +1868,14 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type, msg = "Found suspicious operator '" + tok->str() + "'"; else if (Token::Match(tok, "%var%")) msg = "Unused variable value '" + tok->str() + "'"; - else if (Token::Match(valueTok, "%str%|%num%")) - msg = "Redundant code: Found a statement that begins with " + std::string(valueTok->isNumber() ? "numeric" : "string") + " constant."; + else if (Token::Match(valueTok, "%str%|%num%|%bool%")) { + std::string typeStr("string"); + if (valueTok->isNumber()) + typeStr = "numeric"; + else if (valueTok->isBoolean()) + typeStr = "bool"; + msg = "Redundant code: Found a statement that begins with " + typeStr + " constant."; + } else if (!tok) msg = "Redundant code: Found a statement that begins with " + type + " constant."; else if (tok->isCast() && tok->tokType() == Token::Type::eExtendedOp) { diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index 8a816c891..a6f1ab3de 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -386,6 +386,36 @@ private: check("void f(int x) { static_cast(x); }"); ASSERT_EQUALS("[test.cpp:1]: (warning) Found unused cast of expression 'x'.\n", errout.str()); + + check("void f(int x, int* p) {\n" + " static_cast(x);\n" + " (void)x;\n" + " static_cast(p);\n" + " (void*)p;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f() { false; }"); // #10856 + ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant code: Found a statement that begins with bool constant.\n", errout.str()); + + check("void f(int i) {\n" + " (float)(char)i;\n" + " static_cast((char)i);\n" + " (char)static_cast(i);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Found unused cast of expression 'i'.\n" + "[test.cpp:3]: (warning) Found unused cast of expression 'i'.\n" + "[test.cpp:4]: (warning) Found unused cast of expression 'i'.\n", + errout.str()); + + check("struct S; struct T; struct U;\n" + "void f() {\n" + " T t;\n" + " (S)(U)t;\n" + " (S)static_cast(t);\n" + " static_cast((U)t);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void vardecl() {