LCOV - code coverage report
Current view: top level - lib - checkbool.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 282 287 98.3 %
Date: 2024-04-28 12:00:40 Functions: 26 26 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Cppcheck - A tool for static C/C++ code analysis
       3             :  * Copyright (C) 2007-2024 Cppcheck team.
       4             :  *
       5             :  * This program is free software: you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation, either version 3 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : 
      20             : //---------------------------------------------------------------------------
      21             : #include "checkbool.h"
      22             : 
      23             : #include "astutils.h"
      24             : #include "errortypes.h"
      25             : #include "settings.h"
      26             : #include "symboldatabase.h"
      27             : #include "token.h"
      28             : #include "tokenize.h"
      29             : #include "vfvalue.h"
      30             : 
      31             : #include <list>
      32             : #include <vector>
      33             : //---------------------------------------------------------------------------
      34             : 
      35             : // Register this check class (by creating a static instance of it)
      36             : namespace {
      37             :     CheckBool instance;
      38             : }
      39             : 
      40             : static const CWE CWE398(398U);  // Indicator of Poor Code Quality
      41             : static const CWE CWE571(571U);  // Expression is Always True
      42             : static const CWE CWE587(587U);  // Assignment of a Fixed Address to a Pointer
      43             : static const CWE CWE704(704U);  // Incorrect Type Conversion or Cast
      44             : 
      45          87 : static bool isBool(const Variable* var)
      46             : {
      47          87 :     return (var && Token::Match(var->typeEndToken(), "bool|_Bool"));
      48             : }
      49             : 
      50             : //---------------------------------------------------------------------------
      51        2671 : void CheckBool::checkIncrementBoolean()
      52             : {
      53        2671 :     if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("incrementboolean"))
      54        2321 :         return;
      55             : 
      56         350 :     logChecker("CheckBool::checkIncrementBoolean"); // style
      57             : 
      58         350 :     const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
      59        6227 :     for (const Scope * scope : symbolDatabase->functionScopes) {
      60      210129 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
      61      204252 :             if (astIsBool(tok) && tok->astParent() && tok->astParent()->str() == "++") {
      62           4 :                 incrementBooleanError(tok);
      63             :             }
      64             :         }
      65             :     }
      66             : }
      67             : 
      68           8 : void CheckBool::incrementBooleanError(const Token *tok)
      69             : {
      70           8 :     reportError(
      71             :         tok,
      72             :         Severity::style,
      73             :         "incrementboolean",
      74             :         "Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n"
      75             :         "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true. You should assign it the value 'true' instead.",
      76             :         CWE398, Certainty::normal
      77          16 :         );
      78           8 : }
      79             : 
      80          14 : static bool isConvertedToBool(const Token* tok)
      81             : {
      82          14 :     if (!tok->astParent())
      83           0 :         return false;
      84          14 :     return astIsBool(tok->astParent()) || Token::Match(tok->astParent()->previous(), "if|while (");
      85             : }
      86             : 
      87             : //---------------------------------------------------------------------------
      88             : // if (bool & bool) -> if (bool && bool)
      89             : // if (bool | bool) -> if (bool || bool)
      90             : //---------------------------------------------------------------------------
      91        2671 : void CheckBool::checkBitwiseOnBoolean()
      92             : {
      93        2671 :     if (!mSettings->severity.isEnabled(Severity::style))
      94        2321 :         return;
      95             : 
      96             :     // danmar: this is inconclusive because I don't like that there are
      97             :     //         warnings for calculations. Example: set_flag(a & b);
      98         350 :     if (!mSettings->certainty.isEnabled(Certainty::inconclusive))
      99           1 :         return;
     100             : 
     101         349 :     logChecker("CheckBool::checkBitwiseOnBoolean"); // style,inconclusive
     102             : 
     103         349 :     const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
     104        6226 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     105      210129 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
     106      204252 :             if (tok->isBinaryOp()) {
     107       40800 :                 bool isCompound{};
     108       40800 :                 if (tok->str() == "&" || tok->str() == "|")
     109         173 :                     isCompound = false;
     110       40627 :                 else if (tok->str() == "&=" || tok->str() == "|=")
     111           6 :                     isCompound = true;
     112             :                 else
     113       40782 :                     continue;
     114         179 :                 const bool isBoolOp1 = astIsBool(tok->astOperand1());
     115         179 :                 const bool isBoolOp2 = astIsBool(tok->astOperand2());
     116         179 :                 if (!tok->astOperand1()->valueType() || !tok->astOperand2()->valueType())
     117         116 :                     continue;
     118          63 :                 if (!(isBoolOp1 || isBoolOp2))
     119          37 :                     continue;
     120          26 :                 if (isCompound && (!isBoolOp1 || isBoolOp2))
     121           3 :                     continue;
     122          23 :                 if (tok->str() == "|" && !isConvertedToBool(tok) && !(isBoolOp1 && isBoolOp2))
     123           3 :                     continue;
     124             :                 // first operand will always be evaluated
     125          20 :                 if (!isConstExpression(tok->astOperand2(), mSettings->library))
     126           2 :                     continue;
     127          18 :                 if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2())
     128           0 :                     continue;
     129          36 :                 const std::string expression = (isBoolOp1 ? tok->astOperand1() : tok->astOperand2())->expressionString();
     130          18 :                 bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||", isCompound);
     131             :             }
     132             :         }
     133             :     }
     134             : }
     135             : 
     136          22 : void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op, bool isCompound)
     137             : {
     138          44 :     std::string msg = "Boolean expression '" + expression + "' is used in bitwise operation.";
     139          22 :     if (!isCompound)
     140          20 :         msg += " Did you mean '" + op + "'?";
     141          22 :     reportError(tok,
     142             :                 Severity::style,
     143             :                 "bitwiseOnBoolean",
     144             :                 msg,
     145             :                 CWE398,
     146          44 :                 Certainty::inconclusive);
     147          22 : }
     148             : 
     149             : //---------------------------------------------------------------------------
     150             : //    if (!x==3) <- Probably meant to be "x!=3"
     151             : //---------------------------------------------------------------------------
     152             : 
     153        2671 : void CheckBool::checkComparisonOfBoolWithInt()
     154             : {
     155        2671 :     if (!mSettings->severity.isEnabled(Severity::warning) || !mTokenizer->isCPP())
     156        2402 :         return;
     157             : 
     158         269 :     logChecker("CheckBool::checkComparisonOfBoolWithInt"); // warning,c++
     159             : 
     160         269 :     const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase();
     161        3542 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     162      108729 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
     163      105456 :             if (!tok->isComparisonOp() || !tok->isBinaryOp())
     164      104999 :                 continue;
     165         457 :             const Token* const left = tok->astOperand1();
     166         457 :             const Token* const right = tok->astOperand2();
     167         457 :             if (left->isBoolean() && right->varId()) { // Comparing boolean constant with variable
     168           5 :                 if (tok->str() != "==" && tok->str() != "!=") {
     169           4 :                     comparisonOfBoolWithInvalidComparator(right, left->str());
     170             :                 }
     171         452 :             } else if (left->varId() && right->isBoolean()) { // Comparing variable with boolean constant
     172           6 :                 if (tok->str() != "==" && tok->str() != "!=") {
     173           5 :                     comparisonOfBoolWithInvalidComparator(right, left->str());
     174             :                 }
     175             :             }
     176             :         }
     177             :     }
     178             : }
     179             : 
     180          13 : void CheckBool::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression)
     181             : {
     182          13 :     reportError(tok, Severity::warning, "comparisonOfBoolWithInvalidComparator",
     183             :                 "Comparison of a boolean value using relational operator (<, >, <= or >=).\n"
     184          26 :                 "The result of the expression '" + expression + "' is of type 'bool'. "
     185             :                 "Comparing 'bool' value using relational (<, >, <= or >=)"
     186          26 :                 " operator could cause unexpected results.");
     187          13 : }
     188             : 
     189             : //-------------------------------------------------------------------------------
     190             : // Comparing functions which are returning value of type bool
     191             : //-------------------------------------------------------------------------------
     192             : 
     193         304 : static bool tokenIsFunctionReturningBool(const Token* tok)
     194             : {
     195         304 :     const Function* func = tok ? tok->function() : nullptr;
     196         304 :     if (func && Token::Match(tok, "%name% (")) {
     197          22 :         if (func->tokenDef && Token::Match(func->tokenDef->previous(), "bool|_Bool")) {
     198          17 :             return true;
     199             :         }
     200             :     }
     201         287 :     return false;
     202             : }
     203             : 
     204        2671 : void CheckBool::checkComparisonOfFuncReturningBool()
     205             : {
     206        2671 :     if (!mSettings->severity.isEnabled(Severity::style))
     207        2401 :         return;
     208             : 
     209         350 :     if (!mTokenizer->isCPP())
     210          80 :         return;
     211             : 
     212         270 :     logChecker("CheckBool::checkComparisonOfFuncReturningBool"); // style,c++
     213             : 
     214         270 :     const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase();
     215         317 :     auto getFunctionTok = [](const Token* tok) -> const Token* {
     216         317 :         while (Token::simpleMatch(tok, "!") || (tok && tok->isCast() && !isCPPCast(tok)))
     217          13 :             tok = tok->astOperand1();
     218         304 :         if (isCPPCast(tok))
     219           2 :             tok = tok->astOperand2();
     220         304 :         if (tok)
     221         304 :             return tok->previous();
     222           0 :         return nullptr;
     223             :     };
     224             : 
     225        3543 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     226      108729 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
     227      105456 :             if (!tok->isComparisonOp() || tok->str() == "==" || tok->str() == "!=")
     228      105304 :                 continue;
     229             : 
     230         152 :             const Token* firstToken = getFunctionTok(tok->astOperand1());
     231         152 :             const Token* secondToken = getFunctionTok(tok->astOperand2());
     232         152 :             if (!firstToken || !secondToken)
     233           0 :                 continue;
     234             : 
     235         152 :             const bool firstIsFunctionReturningBool = tokenIsFunctionReturningBool(firstToken);
     236         152 :             const bool secondIsFunctionReturningBool = tokenIsFunctionReturningBool(secondToken);
     237         152 :             if (firstIsFunctionReturningBool && secondIsFunctionReturningBool) {
     238           6 :                 comparisonOfTwoFuncsReturningBoolError(firstToken->next(), firstToken->str(), secondToken->str());
     239         146 :             } else if (firstIsFunctionReturningBool) {
     240           4 :                 comparisonOfFuncReturningBoolError(firstToken->next(), firstToken->str());
     241         142 :             } else if (secondIsFunctionReturningBool) {
     242           1 :                 comparisonOfFuncReturningBoolError(secondToken->previous(), secondToken->str());
     243             :             }
     244             :         }
     245             :     }
     246             : }
     247             : 
     248           9 : void CheckBool::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression)
     249             : {
     250           9 :     reportError(tok, Severity::style, "comparisonOfFuncReturningBoolError",
     251             :                 "Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n"
     252          18 :                 "The return type of function '" + expression + "' is 'bool' "
     253             :                 "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
     254          18 :                 " operator could cause unexpected results.", CWE398, Certainty::normal);
     255           9 : }
     256             : 
     257          10 : void CheckBool::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2)
     258             : {
     259          10 :     reportError(tok, Severity::style, "comparisonOfTwoFuncsReturningBoolError",
     260             :                 "Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
     261          20 :                 "The return type of function '" + expression1 + "' and function '" + expression2 + "' is 'bool' "
     262             :                 "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
     263          20 :                 " operator could cause unexpected results.", CWE398, Certainty::normal);
     264          10 : }
     265             : 
     266             : //-------------------------------------------------------------------------------
     267             : // Comparison of bool with bool
     268             : //-------------------------------------------------------------------------------
     269             : 
     270        2671 : void CheckBool::checkComparisonOfBoolWithBool()
     271             : {
     272        2671 :     if (!mSettings->severity.isEnabled(Severity::style))
     273        2321 :         return;
     274             : 
     275         350 :     if (!mTokenizer->isCPP())
     276          80 :         return;
     277             : 
     278         270 :     logChecker("CheckBool::checkComparisonOfBoolWithBool"); // style,c++
     279             : 
     280         270 :     const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase();
     281             : 
     282        3543 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     283      108729 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
     284      105456 :             if (!tok->isComparisonOp() || tok->str() == "==" || tok->str() == "!=")
     285      105304 :                 continue;
     286         152 :             bool firstTokenBool = false;
     287             : 
     288         152 :             const Token *firstToken = tok->previous();
     289         152 :             if (firstToken->varId()) {
     290          82 :                 if (isBool(firstToken->variable())) {
     291          11 :                     firstTokenBool = true;
     292             :                 }
     293             :             }
     294         152 :             if (!firstTokenBool)
     295         141 :                 continue;
     296             : 
     297          11 :             bool secondTokenBool = false;
     298          11 :             const Token *secondToken = tok->next();
     299          11 :             if (secondToken->varId()) {
     300           5 :                 if (isBool(secondToken->variable())) {
     301           5 :                     secondTokenBool = true;
     302             :                 }
     303             :             }
     304          11 :             if (secondTokenBool) {
     305           5 :                 comparisonOfBoolWithBoolError(firstToken->next(), secondToken->str());
     306             :             }
     307             :         }
     308             :     }
     309             : }
     310             : 
     311           9 : void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression)
     312             : {
     313           9 :     reportError(tok, Severity::style, "comparisonOfBoolWithBoolError",
     314             :                 "Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n"
     315          18 :                 "The variable '" + expression + "' is of type 'bool' "
     316             :                 "and comparing 'bool' value using relational (<, >, <= or >=)"
     317          18 :                 " operator could cause unexpected results.", CWE398, Certainty::normal);
     318           9 : }
     319             : 
     320             : //-----------------------------------------------------------------------------
     321        2671 : void CheckBool::checkAssignBoolToPointer()
     322             : {
     323        2671 :     logChecker("CheckBool::checkAssignBoolToPointer");
     324        2671 :     const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
     325       10859 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     326      256243 :         for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
     327      248055 :             if (tok->str() == "=" && astIsPointer(tok->astOperand1()) && astIsBool(tok->astOperand2())) {
     328           8 :                 assignBoolToPointerError(tok);
     329             :             }
     330             :         }
     331             :     }
     332        2671 : }
     333             : 
     334          12 : void CheckBool::assignBoolToPointerError(const Token *tok)
     335             : {
     336          12 :     reportError(tok, Severity::error, "assignBoolToPointer",
     337          24 :                 "Boolean value assigned to pointer.", CWE587, Certainty::normal);
     338          12 : }
     339             : 
     340             : //-----------------------------------------------------------------------------
     341             : //-----------------------------------------------------------------------------
     342        2671 : void CheckBool::checkComparisonOfBoolExpressionWithInt()
     343             : {
     344        2671 :     if (!mSettings->severity.isEnabled(Severity::warning))
     345        2322 :         return;
     346             : 
     347         349 :     logChecker("CheckBool::checkComparisonOfBoolExpressionWithInt"); // warning
     348             : 
     349         349 :     const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
     350             : 
     351        6226 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     352      210129 :         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
     353      204252 :             if (!tok->isComparisonOp())
     354      203457 :                 continue;
     355             : 
     356         795 :             const Token* numTok = nullptr;
     357         795 :             const Token* boolExpr = nullptr;
     358             :             bool numInRhs;
     359         795 :             if (astIsBool(tok->astOperand1())) {
     360          71 :                 boolExpr = tok->astOperand1();
     361          71 :                 numTok = tok->astOperand2();
     362          71 :                 numInRhs = true;
     363         724 :             } else if (astIsBool(tok->astOperand2())) {
     364          14 :                 boolExpr = tok->astOperand2();
     365          14 :                 numTok = tok->astOperand1();
     366          14 :                 numInRhs = false;
     367             :             } else {
     368         710 :                 continue;
     369             :             }
     370             : 
     371          85 :             if (!numTok || !boolExpr)
     372           0 :                 continue;
     373             : 
     374          85 :             if (boolExpr->isOp() && numTok->isName() && Token::Match(tok, "==|!="))
     375             :                 // there is weird code such as:  ((a<b)==c)
     376             :                 // but it is probably written this way by design.
     377           4 :                 continue;
     378             : 
     379          81 :             if (astIsBool(numTok))
     380          29 :                 continue;
     381             : 
     382          52 :             const ValueFlow::Value *minval = numTok->getValueLE(0, *mSettings);
     383          62 :             if (minval && minval->intvalue == 0 &&
     384           8 :                 (numInRhs ? Token::Match(tok, ">|==|!=")
     385           2 :                  : Token::Match(tok, "<|==|!=")))
     386           8 :                 minval = nullptr;
     387             : 
     388          52 :             const ValueFlow::Value *maxval = numTok->getValueGE(1, *mSettings);
     389          59 :             if (maxval && maxval->intvalue == 1 &&
     390           4 :                 (numInRhs ? Token::Match(tok, "<|==|!=")
     391           3 :                  : Token::Match(tok, ">|==|!=")))
     392           4 :                 maxval = nullptr;
     393             : 
     394          52 :             if (minval || maxval) {
     395          24 :                 const bool not0or1 = (minval && minval->intvalue < 0) || (maxval && maxval->intvalue > 1);
     396          24 :                 comparisonOfBoolExpressionWithIntError(tok, not0or1);
     397             :             }
     398             :         }
     399             :     }
     400             : }
     401             : 
     402          28 : void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1)
     403             : {
     404          28 :     if (not0or1)
     405          23 :         reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
     406          46 :                     "Comparison of a boolean expression with an integer other than 0 or 1.", CWE398, Certainty::normal);
     407             :     else
     408           5 :         reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
     409          10 :                     "Comparison of a boolean expression with an integer.", CWE398, Certainty::normal);
     410          28 : }
     411             : 
     412             : 
     413        2671 : void CheckBool::pointerArithBool()
     414             : {
     415        2671 :     logChecker("CheckBool::pointerArithBool");
     416             : 
     417        2671 :     const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
     418             : 
     419       14556 :     for (const Scope &scope : symbolDatabase->scopeList) {
     420       11885 :         if (scope.type != Scope::eIf && !scope.isLoopScope())
     421       11206 :             continue;
     422         679 :         const Token* tok = scope.classDef->next()->astOperand2();
     423         679 :         if (scope.type == Scope::eFor) {
     424          76 :             tok = Token::findsimplematch(scope.classDef->tokAt(2), ";");
     425          76 :             if (tok)
     426          76 :                 tok = tok->astOperand2();
     427          76 :             if (tok)
     428          71 :                 tok = tok->astOperand1();
     429         603 :         } else if (scope.type == Scope::eDo)
     430           3 :             tok = (scope.bodyEnd->tokAt(2)) ? scope.bodyEnd->tokAt(2)->astOperand2() : nullptr;
     431             : 
     432         679 :         pointerArithBoolCond(tok);
     433             :     }
     434        2671 : }
     435             : 
     436         755 : void CheckBool::pointerArithBoolCond(const Token *tok)
     437             : {
     438         755 :     if (!tok)
     439           7 :         return;
     440         748 :     if (Token::Match(tok, "&&|%oror%")) {
     441          38 :         pointerArithBoolCond(tok->astOperand1());
     442          38 :         pointerArithBoolCond(tok->astOperand2());
     443          38 :         return;
     444             :     }
     445         710 :     if (tok->str() != "+" && tok->str() != "-")
     446         701 :         return;
     447             : 
     448           9 :     if (tok->isBinaryOp() &&
     449          18 :         tok->astOperand1()->isName() &&
     450          18 :         tok->astOperand1()->variable() &&
     451          27 :         tok->astOperand1()->variable()->isPointer() &&
     452           6 :         tok->astOperand2()->isNumber())
     453           6 :         pointerArithBoolError(tok);
     454             : }
     455             : 
     456          10 : void CheckBool::pointerArithBoolError(const Token *tok)
     457             : {
     458          10 :     reportError(tok,
     459             :                 Severity::error,
     460             :                 "pointerArithBool",
     461             :                 "Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n"
     462          20 :                 "Converting pointer arithmetic result to bool. The boolean result is always true unless there is pointer arithmetic overflow, and overflow is undefined behaviour. Probably a dereference is forgotten.", CWE571, Certainty::normal);
     463          10 : }
     464             : 
     465        2671 : void CheckBool::checkAssignBoolToFloat()
     466             : {
     467        2671 :     if (!mTokenizer->isCPP())
     468          81 :         return;
     469        2590 :     if (!mSettings->severity.isEnabled(Severity::style))
     470        2320 :         return;
     471         270 :     logChecker("CheckBool::checkAssignBoolToFloat"); // style,c++
     472         270 :     const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
     473        3543 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     474      112002 :         for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
     475      108729 :             if (tok->str() == "=" && astIsFloat(tok->astOperand1(), false) && astIsBool(tok->astOperand2())) {
     476           5 :                 assignBoolToFloatError(tok);
     477             :             }
     478             :         }
     479             :     }
     480             : }
     481             : 
     482           9 : void CheckBool::assignBoolToFloatError(const Token *tok)
     483             : {
     484           9 :     reportError(tok, Severity::style, "assignBoolToFloat",
     485          18 :                 "Boolean value assigned to floating point variable.", CWE704, Certainty::normal);
     486           9 : }
     487             : 
     488        2671 : void CheckBool::returnValueOfFunctionReturningBool()
     489             : {
     490        2671 :     if (!mSettings->severity.isEnabled(Severity::style))
     491        2321 :         return;
     492             : 
     493         350 :     logChecker("CheckBool::returnValueOfFunctionReturningBool"); // style
     494             : 
     495         350 :     const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase();
     496             : 
     497        6227 :     for (const Scope * scope : symbolDatabase->functionScopes) {
     498        5877 :         if (!(scope->function && Token::Match(scope->function->retDef, "bool|_Bool")))
     499        5752 :             continue;
     500             : 
     501        2055 :         for (const Token* tok = scope->bodyStart->next(); tok && (tok != scope->bodyEnd); tok = tok->next()) {
     502             :             // Skip lambdas
     503        1930 :             const Token* tok2 = findLambdaEndToken(tok);
     504        1930 :             if (tok2)
     505           4 :                 tok = tok2;
     506        1926 :             else if (tok->scope() && tok->scope()->isClassOrStruct())
     507           3 :                 tok = tok->scope()->bodyEnd;
     508        2059 :             else if (Token::simpleMatch(tok, "return") && tok->astOperand1() &&
     509        2076 :                      (tok->astOperand1()->getValueGE(2, *mSettings) || tok->astOperand1()->getValueLE(-1, *mSettings)) &&
     510          17 :                      !(tok->astOperand1()->astOperand1() && Token::Match(tok->astOperand1(), "&|%or%")))
     511          12 :                 returnValueBoolError(tok);
     512             :         }
     513             :     }
     514             : }
     515             : 
     516          16 : void CheckBool::returnValueBoolError(const Token *tok)
     517             : {
     518          16 :     reportError(tok, Severity::style, "returnNonBoolInBooleanFunction", "Non-boolean value returned from function returning bool");
     519          16 : }

Generated by: LCOV version 1.14