@@ -2340,41 +2340,69 @@ void CheckOther::checkSignOfUnsignedVariable()
23402340 for (const Scope * scope : symbolDatabase->functionScopes ) {
23412341 // check all the code in the function
23422342 for (const Token *tok = scope->bodyStart ->next (); tok != scope->bodyEnd ; tok = tok->next ()) {
2343- if (!tok->isComparisonOp () || !tok->astOperand1 () || !tok->astOperand2 ())
2344- continue ;
2345-
2346- const ValueFlow::Value *v1 = tok->astOperand1 ()->getValue (0 );
2347- const ValueFlow::Value *v2 = tok->astOperand2 ()->getValue (0 );
2348-
2349- if (Token::Match (tok, " <|<=" ) && v2 && v2->isKnown ()) {
2350- const ValueType* vt = tok->astOperand1 ()->valueType ();
2351- if (vt && vt->pointer )
2352- pointerLessThanZeroError (tok, v2);
2353- if (vt && vt->sign == ValueType::UNSIGNED)
2354- unsignedLessThanZeroError (tok, v2, tok->astOperand1 ()->expressionString ());
2355- } else if (Token::Match (tok, " >|>=" ) && v1 && v1->isKnown ()) {
2356- const ValueType* vt = tok->astOperand2 ()->valueType ();
2357- if (vt && vt->pointer )
2358- pointerLessThanZeroError (tok, v1);
2359- if (vt && vt->sign == ValueType::UNSIGNED)
2360- unsignedLessThanZeroError (tok, v1, tok->astOperand2 ()->expressionString ());
2361- } else if (Token::simpleMatch (tok, " >=" ) && v2 && v2->isKnown ()) {
2362- const ValueType* vt = tok->astOperand1 ()->valueType ();
2363- if (vt && vt->pointer )
2364- pointerPositiveError (tok, v2);
2365- if (vt && vt->sign == ValueType::UNSIGNED)
2366- unsignedPositiveError (tok, v2, tok->astOperand1 ()->expressionString ());
2367- } else if (Token::simpleMatch (tok, " <=" ) && v1 && v1->isKnown ()) {
2368- const ValueType* vt = tok->astOperand2 ()->valueType ();
2369- if (vt && vt->pointer )
2370- pointerPositiveError (tok, v1);
2371- if (vt && vt->sign == ValueType::UNSIGNED)
2372- unsignedPositiveError (tok, v1, tok->astOperand2 ()->expressionString ());
2343+ const ValueFlow::Value *zeroValue = nullptr ;
2344+ const Token *nonZeroExpr = nullptr ;
2345+ if (comparisonNonZeroExpressionLessThanZero (tok, &zeroValue, &nonZeroExpr)) {
2346+ const ValueType* vt = nonZeroExpr->valueType ();
2347+ if (vt->pointer )
2348+ pointerLessThanZeroError (tok, zeroValue);
2349+ else
2350+ unsignedLessThanZeroError (tok, zeroValue, nonZeroExpr->expressionString ());
2351+ } else if (testIfNonZeroExpressionIsPositive (tok, &zeroValue, &nonZeroExpr)) {
2352+ const ValueType* vt = nonZeroExpr->valueType ();
2353+ if (vt->pointer )
2354+ pointerPositiveError (tok, zeroValue);
2355+ else
2356+ unsignedPositiveError (tok, zeroValue, nonZeroExpr->expressionString ());
23732357 }
23742358 }
23752359 }
23762360}
23772361
2362+ bool CheckOther::comparisonNonZeroExpressionLessThanZero (const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr)
2363+ {
2364+ if (!tok->isComparisonOp () || !tok->astOperand1 () || !tok->astOperand2 ())
2365+ return false ;
2366+
2367+ const ValueFlow::Value *v1 = tok->astOperand1 ()->getValue (0 );
2368+ const ValueFlow::Value *v2 = tok->astOperand2 ()->getValue (0 );
2369+
2370+ if (Token::Match (tok, " <|<=" ) && v2 && v2->isKnown ()) {
2371+ *zeroValue = v2;
2372+ *nonZeroExpr = tok->astOperand1 ();
2373+ } else if (Token::Match (tok, " >|>=" ) && v1 && v1->isKnown ()) {
2374+ *zeroValue = v1;
2375+ *nonZeroExpr = tok->astOperand2 ();
2376+ } else {
2377+ return false ;
2378+ }
2379+
2380+ const ValueType* vt = (*nonZeroExpr)->valueType ();
2381+ return vt && (vt->pointer || vt->sign == ValueType::UNSIGNED);
2382+ }
2383+
2384+ bool CheckOther::testIfNonZeroExpressionIsPositive (const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr)
2385+ {
2386+ if (!tok->isComparisonOp () || !tok->astOperand1 () || !tok->astOperand2 ())
2387+ return false ;
2388+
2389+ const ValueFlow::Value *v1 = tok->astOperand1 ()->getValue (0 );
2390+ const ValueFlow::Value *v2 = tok->astOperand2 ()->getValue (0 );
2391+
2392+ if (Token::simpleMatch (tok, " >=" ) && v2 && v2->isKnown ()) {
2393+ *zeroValue = v2;
2394+ *nonZeroExpr = tok->astOperand1 ();
2395+ } else if (Token::simpleMatch (tok, " <=" ) && v1 && v1->isKnown ()) {
2396+ *zeroValue = v1;
2397+ *nonZeroExpr = tok->astOperand2 ();
2398+ } else {
2399+ return false ;
2400+ }
2401+
2402+ const ValueType* vt = (*nonZeroExpr)->valueType ();
2403+ return vt && (vt->pointer || vt->sign == ValueType::UNSIGNED);
2404+ }
2405+
23782406void CheckOther::unsignedLessThanZeroError (const Token *tok, const ValueFlow::Value * v, const std::string &varname)
23792407{
23802408 reportError (getErrorPath (tok, v, " Unsigned less than zero" ), Severity::style, " unsignedLessThanZero" ,
0 commit comments