@@ -1846,6 +1846,42 @@ void CheckConditionImpl::pointerAdditionResultNotNullError(const Token *tok, con
18461846 reportError (tok, Severity::warning, " pointerAdditionResultNotNull" , " Comparison is wrong. Result of '" + s + " ' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour." );
18471847}
18481848
1849+ static bool checkBoolConditionalAssign (const Token* condTok, const Token* assignTok, bool & isRedundant)
1850+ {
1851+ bool isNegation = false ;
1852+ const Token* varTok = condTok;
1853+ if (condTok->isUnaryOp (" !" )) {
1854+ isNegation = true ;
1855+ varTok = varTok->astOperand1 ();
1856+ } else if (condTok->isBinaryOp ()) {
1857+ varTok = condTok->astOperand1 ();
1858+ if (varTok->hasKnownIntValue ())
1859+ varTok = condTok->astOperand2 ();
1860+ }
1861+
1862+ const ValueType* vt = varTok->variable () ? varTok->variable ()->valueType () : nullptr ;
1863+ if (!(vt && vt->type == ValueType::Type::BOOL && !vt->pointer ))
1864+ return false ;
1865+
1866+ if (!(assignTok->astOperand1 () && assignTok->astOperand1 ()->varId () == varTok->varId ()))
1867+ return false ;
1868+ if (!(assignTok->astOperand2 () && assignTok->astOperand2 ()->hasKnownIntValue ()))
1869+ return false ;
1870+ const MathLib::bigint val = assignTok->astOperand2 ()->getKnownIntValue ();
1871+ if (val < 0 || val > 1 )
1872+ return false ;
1873+ if (condTok->isBinaryOp ()) {
1874+ if (!varTok->astSibling ()->hasKnownIntValue ())
1875+ return false ;
1876+ const MathLib::bigint compVal = varTok->astSibling ()->getKnownIntValue ();
1877+ if (compVal < 0 || compVal > 1 )
1878+ return false ;
1879+ isNegation = (condTok->str () == " !=" ) == (compVal == 1 );
1880+ }
1881+ isRedundant = (isNegation && val == 0 ) || (!isNegation && val == 1 );
1882+ return true ;
1883+ }
1884+
18491885void CheckConditionImpl::checkDuplicateConditionalAssign ()
18501886{
18511887 if (!mSettings .severity .isEnabled (Severity::style) && !mSettings .isPremiumEnabled (" duplicateConditionalAssign" ))
@@ -1862,7 +1898,7 @@ void CheckConditionImpl::checkDuplicateConditionalAssign()
18621898 continue ;
18631899 const Token *blockTok = tok->linkAt (1 )->next ();
18641900 const Token *condTok = tok->next ()->astOperand2 ();
1865- const bool isBoolVar = Token::Match (condTok, " !| %var%" );
1901+ bool isBoolVar = Token::Match (condTok, " !| %var%" );
18661902 if (!isBoolVar && !Token::Match (condTok, " ==|!=" ))
18671903 continue ;
18681904 if ((isBoolVar || condTok->str () == " !=" ) && Token::simpleMatch (blockTok->link (), " } else {" ))
@@ -1875,21 +1911,8 @@ void CheckConditionImpl::checkDuplicateConditionalAssign()
18751911 if (nextAfterAstRightmostLeaf (assignTok) != blockTok->link ()->previous ())
18761912 continue ;
18771913 bool isRedundant = false ;
1878- if (isBoolVar) {
1879- const bool isNegation = condTok->str () == " !" ;
1880- const Token* const varTok = isNegation ? condTok->next () : condTok;
1881- const ValueType* vt = varTok->variable () ? varTok->variable ()->valueType () : nullptr ;
1882- if (!(vt && vt->type == ValueType::Type::BOOL && !vt->pointer ))
1883- continue ;
1884-
1885- if (!(assignTok->astOperand1 () && assignTok->astOperand1 ()->varId () == varTok->varId ()))
1886- continue ;
1887- if (!(assignTok->astOperand2 () && assignTok->astOperand2 ()->hasKnownIntValue ()))
1888- continue ;
1889- const MathLib::bigint val = assignTok->astOperand2 ()->getKnownIntValue ();
1890- if (val < 0 || val > 1 )
1891- continue ;
1892- isRedundant = (isNegation && val == 0 ) || (!isNegation && val == 1 );
1914+ if (checkBoolConditionalAssign (condTok, assignTok, isRedundant)) {
1915+ isBoolVar = true ;
18931916 } else { // comparison
18941917 if (!isSameExpression (
18951918 true , condTok->astOperand1 (), assignTok->astOperand1 (), mSettings , true , true ))
@@ -1898,17 +1921,17 @@ void CheckConditionImpl::checkDuplicateConditionalAssign()
18981921 true , condTok->astOperand2 (), assignTok->astOperand2 (), mSettings , true , true ))
18991922 continue ;
19001923 }
1901- duplicateConditionalAssignError (condTok, assignTok, isRedundant);
1924+ duplicateConditionalAssignError (condTok, assignTok, isRedundant, isBoolVar );
19021925 }
19031926 }
19041927}
19051928
1906- void CheckConditionImpl::duplicateConditionalAssignError (const Token *condTok, const Token* assignTok, bool isRedundant)
1929+ void CheckConditionImpl::duplicateConditionalAssignError (const Token *condTok, const Token* assignTok, bool isRedundant, bool isBoolVar )
19071930{
19081931 ErrorPath errors;
19091932 std::string msg = " Duplicate expression for the condition and assignment." ;
19101933 if (condTok && assignTok) {
1911- if (condTok->str () == " ==" ) {
1934+ if (condTok->str () == " ==" && !isBoolVar ) {
19121935 msg = " Assignment '" + assignTok->expressionString () + " ' is redundant with condition '" + condTok->expressionString () + " '." ;
19131936 errors.emplace_back (condTok, " Condition '" + condTok->expressionString () + " '" );
19141937 errors.emplace_back (assignTok, " Assignment '" + assignTok->expressionString () + " ' is redundant" );
@@ -1924,7 +1947,6 @@ void CheckConditionImpl::duplicateConditionalAssignError(const Token *condTok, c
19241947 std::move (errors), Severity::style, " duplicateConditionalAssign" , msg, CWE398 , Certainty::normal);
19251948}
19261949
1927-
19281950void CheckConditionImpl::checkAssignmentInCondition ()
19291951{
19301952 if (!mSettings .severity .isEnabled (Severity::style) && !mSettings .isPremiumEnabled (" assignmentInCondition" ))
0 commit comments