@@ -3640,6 +3640,21 @@ static bool isVariableExpression(const Token* tok)
36403640 return false ;
36413641}
36423642
3643+ static bool isVariableExprHidden (const Token* tok)
3644+ {
3645+ if (!tok)
3646+ return false ;
3647+ if (!tok->astParent ())
3648+ return false ;
3649+ if (Token::simpleMatch (tok->astParent (), " *" ) && Token::simpleMatch (tok->astSibling (), " 0" ))
3650+ return true ;
3651+ if (Token::simpleMatch (tok->astParent (), " &&" ) && Token::simpleMatch (tok->astSibling (), " false" ))
3652+ return true ;
3653+ if (Token::simpleMatch (tok->astParent (), " ||" ) && Token::simpleMatch (tok->astSibling (), " true" ))
3654+ return true ;
3655+ return false ;
3656+ }
3657+
36433658void CheckOther::checkKnownArgument ()
36443659{
36453660 if (!mSettings ->severity .isEnabled (Severity::style))
@@ -3679,44 +3694,25 @@ void CheckOther::checkKnownArgument()
36793694 mTokenizer ->isCPP (), true , tok->astOperand1 (), tok->astOperand2 (), mSettings ->library , true , true ))
36803695 continue ;
36813696 // ensure that there is a integer variable in expression with unknown value
3682- std::string varexpr;
3683- bool isVariableExprHidden = false ; // Is variable expression explicitly hidden
3684- auto setVarExpr = [&varexpr, &isVariableExprHidden](const Token *child) {
3697+ const Token* vartok = findAstNode (tok, [](const Token* child) {
36853698 if (Token::Match (child, " %var%|.|[" )) {
3686- if (child->valueType () && child->valueType ()->pointer == 0 && child->valueType ()->isIntegral () && child->values ().empty ()) {
3687- varexpr = child->expressionString ();
3688- return ChildrenToVisit::done;
3689- }
3690- return ChildrenToVisit::none;
3699+ return astIsIntegral (child, false ) && !astIsPointer (child) && child->values ().empty ();
36913700 }
3692- if (Token::simpleMatch (child->previous (), " sizeof (" ))
3693- return ChildrenToVisit::none;
3694-
3695- // hide variable explicitly with 'x * 0' etc
3696- if (!isVariableExprHidden) {
3697- if (Token::simpleMatch (child, " *" ) && (Token::simpleMatch (child->astOperand1 (), " 0" ) || Token::simpleMatch (child->astOperand2 (), " 0" )))
3698- return ChildrenToVisit::none;
3699- if (Token::simpleMatch (child, " &&" ) && (Token::simpleMatch (child->astOperand1 (), " false" ) || Token::simpleMatch (child->astOperand2 (), " false" )))
3700- return ChildrenToVisit::none;
3701- if (Token::simpleMatch (child, " ||" ) && (Token::simpleMatch (child->astOperand1 (), " true" ) || Token::simpleMatch (child->astOperand2 (), " true" )))
3702- return ChildrenToVisit::none;
3703- }
3704-
3705- return ChildrenToVisit::op1_and_op2;
3706- };
3707- visitAstNodes (tok, setVarExpr);
3708- if (varexpr.empty ()) {
3709- isVariableExprHidden = true ;
3710- visitAstNodes (tok, setVarExpr);
3711- }
3712- if (varexpr.empty ())
3701+ return false ;
3702+ });
3703+ if (!vartok)
3704+ continue ;
3705+ if (vartok->astSibling () &&
3706+ findAstNode (vartok->astSibling (), [](const Token* child) {
3707+ return Token::simpleMatch (child, " sizeof" );
3708+ }))
37133709 continue ;
37143710 // ensure that function name does not contain "assert"
3715- std::string funcname = tok-> astParent ()-> previous () ->str ();
3711+ std::string funcname = ftok ->str ();
37163712 strTolower (funcname);
37173713 if (funcname.find (" assert" ) != std::string::npos)
37183714 continue ;
3719- knownArgumentError (tok, ftok, &tok->values ().front (), varexpr , isVariableExprHidden);
3715+ knownArgumentError (tok, ftok, &tok->values ().front (), vartok-> expressionString () , isVariableExprHidden (vartok) );
37203716 }
37213717 }
37223718}
@@ -3747,6 +3743,48 @@ void CheckOther::knownArgumentError(const Token *tok, const Token *ftok, const V
37473743 reportError (errorPath, Severity::style, id, errmsg, CWE570, Certainty::normal);
37483744}
37493745
3746+ void CheckOther::checkKnownPointerToBool ()
3747+ {
3748+ if (!mSettings ->severity .isEnabled (Severity::style))
3749+ return ;
3750+ const SymbolDatabase* symbolDatabase = mTokenizer ->getSymbolDatabase ();
3751+ for (const Scope* functionScope : symbolDatabase->functionScopes ) {
3752+ for (const Token* tok = functionScope->bodyStart ; tok != functionScope->bodyEnd ; tok = tok->next ()) {
3753+ if (!tok->hasKnownIntValue ())
3754+ continue ;
3755+ if (!astIsPointer (tok))
3756+ continue ;
3757+ if (Token::Match (tok->astParent (), " ?|!|&&|%oror%|%comp%" ))
3758+ continue ;
3759+ if (tok->astParent () && Token::Match (tok->astParent ()->previous (), " if|while|switch|sizeof (" ))
3760+ continue ;
3761+ if (tok->isExpandedMacro ())
3762+ continue ;
3763+ if (findParent (tok, [](const Token* parent) {
3764+ return parent->isExpandedMacro ();
3765+ }))
3766+ continue ;
3767+ if (!isUsedAsBool (tok, mSettings ))
3768+ continue ;
3769+ const ValueFlow::Value& value = tok->values ().front ();
3770+ knownPointerToBoolError (tok, &value);
3771+ }
3772+ }
3773+ }
3774+
3775+ void CheckOther::knownPointerToBoolError (const Token* tok, const ValueFlow::Value* value)
3776+ {
3777+ if (!tok) {
3778+ reportError (tok, Severity::style, " knownPointerToBool" , " Pointer expression 'p' converted to bool is always true." );
3779+ return ;
3780+ }
3781+ std::string cond = value->intvalue ? " true" : " false" ;
3782+ const std::string& expr = tok->expressionString ();
3783+ std::string errmsg = " Pointer expression '" + expr + " ' converted to bool is always " + cond + " ." ;
3784+ const ErrorPath errorPath = getErrorPath (tok, value, errmsg);
3785+ reportError (errorPath, Severity::style, " knownPointerToBool" , errmsg, CWE570, Certainty::normal);
3786+ }
3787+
37503788void CheckOther::checkComparePointers ()
37513789{
37523790 const SymbolDatabase *symbolDatabase = mTokenizer ->getSymbolDatabase ();
0 commit comments