@@ -2022,7 +2022,7 @@ static bool isConstant(const Token* tok) {
20222022 return tok && (tok->isEnumerator () || Token::Match (tok, " %bool%|%num%|%str%|%char%|nullptr|NULL" ));
20232023}
20242024
2025- static bool isConstStatement (const Token *tok, bool isNestedBracket = false )
2025+ static bool isConstStatement (const Token *tok, const Library& library, bool isNestedBracket = false )
20262026{
20272027 if (!tok)
20282028 return false ;
@@ -2044,45 +2044,60 @@ static bool isConstStatement(const Token *tok, bool isNestedBracket = false)
20442044 tok2 = tok2->astParent ();
20452045 }
20462046 if (Token::Match (tok, " &&|%oror%" ))
2047- return isConstStatement (tok->astOperand1 ()) && isConstStatement (tok->astOperand2 ());
2047+ return isConstStatement (tok->astOperand1 (), library ) && isConstStatement (tok->astOperand2 (), library );
20482048 if (Token::Match (tok, " !|~|%cop%" ) && (tok->astOperand1 () || tok->astOperand2 ()))
20492049 return true ;
20502050 if (Token::simpleMatch (tok->previous (), " sizeof (" ))
20512051 return true ;
20522052 if (isCPPCast (tok)) {
20532053 if (Token::simpleMatch (tok->astOperand1 (), " dynamic_cast" ) && Token::simpleMatch (tok->astOperand1 ()->linkAt (1 )->previous (), " & >" ))
20542054 return false ;
2055- return isWithoutSideEffects (tok) && isConstStatement (tok->astOperand2 ());
2055+ return isWithoutSideEffects (tok) && isConstStatement (tok->astOperand2 (), library );
20562056 }
20572057 if (tok->isCast () && tok->next () && tok->next ()->isStandardType ())
2058- return isWithoutSideEffects (tok->astOperand1 ()) && isConstStatement (tok->astOperand1 ());
2058+ return isWithoutSideEffects (tok->astOperand1 ()) && isConstStatement (tok->astOperand1 (), library );
20592059 if (Token::simpleMatch (tok, " ." ))
2060- return isConstStatement (tok->astOperand2 ());
2060+ return isConstStatement (tok->astOperand2 (), library );
20612061 if (Token::simpleMatch (tok, " ," )) {
20622062 if (tok->astParent ()) // warn about const statement on rhs at the top level
2063- return isConstStatement (tok->astOperand1 ()) && isConstStatement (tok->astOperand2 ());
2063+ return isConstStatement (tok->astOperand1 (), library ) && isConstStatement (tok->astOperand2 (), library );
20642064
20652065 const Token* lml = previousBeforeAstLeftmostLeaf (tok); // don't warn about matrix/vector assignment (e.g. Eigen)
20662066 if (lml)
20672067 lml = lml->next ();
20682068 const Token* stream = lml;
20692069 while (stream && Token::Match (stream->astParent (), " .|[|(|*" ))
20702070 stream = stream->astParent ();
2071- return (!stream || !isLikelyStream (stream)) && isConstStatement (tok->astOperand2 ());
2071+ return (!stream || !isLikelyStream (stream)) && isConstStatement (tok->astOperand2 (), library );
20722072 }
20732073 if (Token::simpleMatch (tok, " ?" ) && Token::simpleMatch (tok->astOperand2 (), " :" )) // ternary operator
2074- return isConstStatement (tok->astOperand1 ()) && isConstStatement (tok->astOperand2 ()->astOperand1 ()) && isConstStatement (tok->astOperand2 ()->astOperand2 ());
2074+ return isConstStatement (tok->astOperand1 (), library ) && isConstStatement (tok->astOperand2 ()->astOperand1 (), library ) && isConstStatement (tok->astOperand2 ()->astOperand2 (), library );
20752075 if (isBracketAccess (tok) && isWithoutSideEffects (tok->astOperand1 (), /* checkArrayAccess*/ true , /* checkReference*/ false )) {
20762076 const bool isChained = succeeds (tok->astParent (), tok);
20772077 if (Token::simpleMatch (tok->astParent (), " [" )) {
20782078 if (isChained)
2079- return isConstStatement (tok->astOperand2 ()) && isConstStatement (tok->astParent ());
2080- return isNestedBracket && isConstStatement (tok->astOperand2 ());
2079+ return isConstStatement (tok->astOperand2 (), library ) && isConstStatement (tok->astParent (), library );
2080+ return isNestedBracket && isConstStatement (tok->astOperand2 (), library );
20812081 }
2082- return isConstStatement (tok->astOperand2 (), /* isNestedBracket*/ !isChained);
2082+ return isConstStatement (tok->astOperand2 (), library, /* isNestedBracket*/ !isChained);
20832083 }
20842084 if (!tok->astParent () && findLambdaEndToken (tok))
20852085 return true ;
2086+
2087+ tok2 = tok;
2088+ if (tok2->str () == " ::" )
2089+ tok2 = tok2->next ();
2090+ if (Token::Match (tok2, " %name% ;" )) {
2091+ if (tok2->function ())
2092+ return true ;
2093+ std::string funcStr = tok2->str ();
2094+ while (tok2->index () > 1 && Token::Match (tok2->tokAt (-2 ), " %name% ::" )) {
2095+ funcStr.insert (0 , tok2->strAt (-2 ) + " ::" );
2096+ tok2 = tok2->tokAt (-2 );
2097+ }
2098+ if (library.functions ().count (funcStr) > 0 )
2099+ return true ;
2100+ }
20862101 return false ;
20872102}
20882103
@@ -2174,7 +2189,7 @@ void CheckOther::checkIncompleteStatement()
21742189 // Skip statement expressions
21752190 if (Token::simpleMatch (rtok, " ; } )" ))
21762191 continue ;
2177- if (!isConstStatement (tok))
2192+ if (!isConstStatement (tok, mSettings -> library ))
21782193 continue ;
21792194 if (isVoidStmt (tok))
21802195 continue ;
@@ -2228,6 +2243,8 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type,
22282243 msg = " Redundant code: Found unused array access." ;
22292244 else if (tok->str () == " [" && !tok->astParent ())
22302245 msg = " Redundant code: Found unused lambda." ;
2246+ else if (Token::Match (tok, " %name%|::" ))
2247+ msg = " Redundant code: Found unused function." ;
22312248 else if (mSettings ->debugwarnings ) {
22322249 reportError (tok, Severity::debug, " debug" , " constStatementError not handled." );
22332250 return ;
@@ -2365,7 +2382,7 @@ void CheckOther::checkMisusedScopedObject()
23652382 if (Token::simpleMatch (parTok, " <" ) && parTok->link ())
23662383 parTok = parTok->link ()->next ();
23672384 if (const Token* arg = parTok->astOperand2 ()) {
2368- if (!isConstStatement (arg))
2385+ if (!isConstStatement (arg, mSettings -> library ))
23692386 continue ;
23702387 if (parTok->str () == " (" ) {
23712388 if (arg->varId () && !(arg->variable () && arg->variable ()->nameToken () != arg))
@@ -2826,7 +2843,7 @@ void CheckOther::checkDuplicateExpression()
28262843 } else if (tok->astOperand1 () && tok->astOperand2 () && tok->str () == " :" && tok->astParent () && tok->astParent ()->str () == " ?" ) {
28272844 if (!tok->astOperand1 ()->values ().empty () && !tok->astOperand2 ()->values ().empty () && isEqualKnownValue (tok->astOperand1 (), tok->astOperand2 ()) &&
28282845 !isVariableChanged (tok->astParent (), /* indirect*/ 0 , *mSettings ) &&
2829- isConstStatement (tok->astOperand1 ()) && isConstStatement (tok->astOperand2 ()))
2846+ isConstStatement (tok->astOperand1 (), mSettings -> library ) && isConstStatement (tok->astOperand2 (), mSettings -> library ))
28302847 duplicateValueTernaryError (tok);
28312848 else if (isSameExpression (true , tok->astOperand1 (), tok->astOperand2 (), *mSettings , false , true , &errorPath))
28322849 duplicateExpressionTernaryError (tok, std::move (errorPath));
0 commit comments