@@ -31,7 +31,7 @@ namespace {
3131
3232static bool astIsBool (const Token *expr)
3333{
34- return Token::Match (expr, " %comp%|%bool%|%oror%|&&" );
34+ return Token::Match (expr, " %comp%|%bool%|%oror%|&&|! " );
3535}
3636
3737// ---------------------------------------------------------------------------
@@ -357,37 +357,6 @@ void CheckBool::assignBoolToPointerError(const Token *tok)
357357 " Boolean value assigned to pointer." );
358358}
359359
360- /* *
361- * @brief Is the result of the LHS expression non-bool?
362- * @param tok last token in lhs
363- * @return true => lhs result is non-bool. false => lhs result type is unknown or bool
364- */
365- static bool isNonBoolLHSExpr (const Token *tok)
366- {
367- // return value. only return true if we "know" it's a non-bool expression
368- bool nonBoolExpr = false ;
369-
370- for (; tok; tok = tok->previous ()) {
371- if (tok->str () == " )" ) {
372- if (!Token::Match (tok->link ()->previous (), " &&|%oror%|( (" ))
373- tok = tok->link ();
374- } else if (tok->str () == " (" || tok->str () == " [" )
375- break ;
376- else if (tok->isNumber ())
377- nonBoolExpr = true ;
378- else if (tok->isArithmeticalOp ()) {
379- return true ;
380- } else if (tok->isComparisonOp () || (tok->str () == " !" && tok->previous ()->str ()==" (" ))
381- return false ;
382- else if (Token::Match (tok," [;{}=?:&|^,]" ))
383- break ;
384- else if (Token::Match (tok, " &&|%oror%|and|or" ))
385- break ;
386- }
387-
388- return nonBoolExpr;
389- }
390-
391360// -----------------------------------------------------------------------------
392361// -----------------------------------------------------------------------------
393362void CheckBool::checkComparisonOfBoolExpressionWithInt ()
@@ -401,101 +370,50 @@ void CheckBool::checkComparisonOfBoolExpressionWithInt()
401370 for (std::size_t i = 0 ; i < functions; ++i) {
402371 const Scope * scope = symbolDatabase->functionScopes [i];
403372 for (const Token* tok = scope->classStart ->next (); tok != scope->classEnd ; tok = tok->next ()) {
373+ if (!tok->isComparisonOp ())
374+ continue ;
375+
404376 // Skip template parameters
405377 if (tok->str () == " <" && tok->link ()) {
406378 tok = tok->link ();
407379 continue ;
408380 }
409381
410382 const Token* numTok = 0 ;
411- const Token* opTok = 0 ;
412- char op = 0 ;
413- if (Token::Match (tok, " &&|%oror% %any% ) %comp% %any%" )) {
414- numTok = tok->tokAt (4 );
415- opTok = tok->tokAt (3 );
416- if (Token::Match (opTok, " <|>" ))
417- op = opTok->str ()[0 ];
418- } else if (Token::Match (tok, " %any% %comp% ( %any% &&|%oror%" )) {
419- numTok = tok;
420- opTok = tok->next ();
421- if (Token::Match (opTok, " <|>" ))
422- op = opTok->str ()[0 ]==' >' ?' <' :' >' ;
423- }
424-
425- else if (Token::Match (tok, " ! %var% %comp% %any%" ) && !isNonBoolLHSExpr (tok)) {
426- numTok = tok->tokAt (3 );
427- opTok = tok->tokAt (2 );
428- if (Token::Match (opTok, " <|>" ))
429- op = opTok->str ()[0 ];
430- } else if (Token::Match (tok->previous (), " (|&&|%oror% %num% %comp% !" )) {
431- const Token *rhs = tok->tokAt (3 );
432- while (rhs) {
433- if (rhs->str () == " !" ) {
434- if (Token::simpleMatch (rhs, " ! (" ))
435- rhs = rhs->next ()->link ();
436- rhs = rhs->next ();
437- } else if (rhs->isName () || rhs->isNumber ())
438- rhs = rhs->next ();
439- else
440- break ;
441- }
442- if (Token::Match (rhs, " &&|%oror%|)" )) {
443- numTok = tok;
444- opTok = tok->next ();
445- if (Token::Match (opTok, " <|>" ))
446- op = opTok->str ()[0 ]==' >' ?' <' :' >' ;
447- }
383+ const Token* boolExpr = 0 ;
384+ bool numInRhs;
385+ if (astIsBool (tok->astOperand1 ())) {
386+ boolExpr = tok->astOperand1 ();
387+ numTok = tok->astOperand2 ();
388+ numInRhs = true ;
389+ } else if (astIsBool (tok->astOperand2 ())) {
390+ boolExpr = tok->astOperand2 ();
391+ numTok = tok->astOperand1 ();
392+ numInRhs = false ;
393+ } else {
394+ continue ;
448395 }
449396
450- // boolean result in lhs compared with <|<=|>|>=
451- else if (tok->isComparisonOp () && !Token::Match (tok," ==|!=" ) && !isNonBoolLHSExpr (tok->previous ())) {
452- const Token *lhs = tok;
453- while (nullptr != (lhs = lhs->previous ())) {
454- if ((lhs->isName () && !Token::Match (lhs," or|and" )) || lhs->isNumber ())
455- continue ;
456- if (lhs->isArithmeticalOp ())
457- continue ;
458- if (Token::Match (lhs, " )|]" )) {
459- if (Token::Match (lhs->link ()->previous (), " %var% (" ))
460- lhs = lhs->link ();
461- continue ;
462- }
463- break ;
464- }
465- if (lhs && (lhs->isComparisonOp () || lhs->str () == " !" )) {
466- if (_tokenizer->isCPP () && tok->str () == " >" &&
467- (Token::Match (lhs->previous (), " %var% <" ) || lhs->str () == " >" ))
468- continue ;
469- while (nullptr != (lhs = lhs->previous ())) {
470- if ((lhs->isName () && lhs->str () != " return" ) || lhs->isNumber ())
471- continue ;
472- if (Token::Match (lhs," [+-*/.]" ))
473- continue ;
474- if (Token::Match (lhs, " )|]" )) {
475- lhs = lhs->previous ();
476- continue ;
477- }
478- break ;
479- }
397+ if (Token::Match (boolExpr," %bool%" ))
398+ // The CheckBool::checkComparisonOfBoolWithInt warns about this.
399+ continue ;
480400
481- std::string expression;
482- for (const Token *t = lhs ? lhs->next () : _tokenizer->tokens (); t != tok; t = t->next ()) {
483- if (!expression.empty ())
484- expression += ' ' ;
485- expression += t->str ();
486- }
401+ if (!numTok || !boolExpr)
402+ continue ;
487403
488- comparisonOfBoolWithInvalidComparator (tok, expression);
489- }
490- }
404+ if (boolExpr->isOp () && numTok->isName () && Token::Match (tok, " ==|!=" ))
405+ // there is weird code such as: ((a<b)==c)
406+ // but it is probably written this way by design.
407+ continue ;
491408
492- if (numTok && opTok) {
493- if (numTok->isNumber ()) {
494- if (((numTok->str () != " 0" && numTok->str () != " 1" ) || !Token::Match (opTok, " !=|==" )) && !((op == ' <' && numTok->str () == " 1" ) || (op == ' >' && numTok->str () == " 0" )))
495- comparisonOfBoolExpressionWithIntError (tok, true );
496- } else if (isNonBoolStdType (numTok->variable ()))
497- comparisonOfBoolExpressionWithIntError (tok, false );
498- }
409+ if (numTok->isNumber ()) {
410+ if (numTok->str () == " 0" && Token::Match (tok, numInRhs ? " >|==|!=" : " <|==|!=" ))
411+ continue ;
412+ if (numTok->str () == " 1" && Token::Match (tok, numInRhs ? " <|==|!=" : " >|==|!=" ))
413+ continue ;
414+ comparisonOfBoolExpressionWithIntError (tok, true );
415+ } else if (isNonBoolStdType (numTok->variable ()))
416+ comparisonOfBoolExpressionWithIntError (tok, false );
499417 }
500418 }
501419}
0 commit comments