//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CheckBool::checkComparisonOfBoolExpressionWithInt() { if (!_settings->isEnabled("warning")) return; const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { if (!tok->isComparisonOp()) continue; const Token* numTok = 0; const Token* boolExpr = 0; bool numInRhs; if (astIsBool(tok->astOperand1())) { boolExpr = tok->astOperand1(); numTok = tok->astOperand2(); numInRhs = true; } else if (astIsBool(tok->astOperand2())) { boolExpr = tok->astOperand2(); numTok = tok->astOperand1(); numInRhs = false; } else { continue; } if (!numTok || !boolExpr) continue; if (Token::Match(boolExpr,"%bool%")) // The CheckBool::checkComparisonOfBoolWithInt warns about this. continue; if (boolExpr->isOp() && numTok->isName() && Token::Match(tok, "==|!=")) // there is weird code such as: ((a<b)==c) // but it is probably written this way by design. continue; if (numTok->isNumber()) { if (numTok->str() == "0" && (numInRhs ? Token::Match(tok, ">|==|!=") : Token::Match(tok, "<|==|!="))) continue; if (numTok->str() == "1" && (numInRhs ? Token::Match(tok, "<|==|!=") : Token::Match(tok, ">|==|!="))) continue; comparisonOfBoolExpressionWithIntError(tok, true); } else if (isNonBoolStdType(numTok->variable())) comparisonOfBoolExpressionWithIntError(tok, false); } } }
//--------------------------------------------------------------------------- // Check <valid> and <not-bool> //--------------------------------------------------------------------------- void CheckFunctions::invalidFunctionUsage() { const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { if (!Token::Match(tok, "%name% ( !!)")) continue; const Token * const functionToken = tok; const std::vector<const Token *> arguments = getArguments(tok); for (unsigned int argnr = 1; argnr <= arguments.size(); ++argnr) { const Token * const argtok = arguments[argnr-1]; // check <valid>...</valid> const ValueFlow::Value *invalidValue = argtok->getInvalidValue(functionToken,argnr,_settings); if (invalidValue) { invalidFunctionArgError(argtok, functionToken->next()->astOperand1()->expressionString(), argnr, invalidValue, _settings->library.validarg(functionToken, argnr)); } if (astIsBool(argtok)) { // check <not-bool> if (_settings->library.isboolargbad(functionToken, argnr)) invalidFunctionArgBoolError(argtok, functionToken->str(), argnr); // Are the values 0 and 1 valid? else if (!_settings->library.isargvalid(functionToken, argnr, 0)) invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, _settings->library.validarg(functionToken, argnr)); else if (!_settings->library.isargvalid(functionToken, argnr, 1)) invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, _settings->library.validarg(functionToken, argnr)); } } } } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CheckBool::checkAssignBoolToPointer() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { if (tok->str() == "=" && astIsBool(tok->astOperand2())) { const Token *lhs = tok->astOperand1(); while (lhs && (lhs->str() == "." || lhs->str() == "::")) lhs = lhs->astOperand2(); if (!lhs || !lhs->variable() || !lhs->variable()->isPointer()) continue; assignBoolToPointerError(tok); } } } }
void CheckBool::checkAssignBoolToFloat() { if (!_tokenizer->isCPP()) return; if (!_settings->isEnabled("style")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { if (Token::Match(tok, "%var% =")) { const Variable * const var = tok->variable(); if (var && var->isFloatingType() && !var->isArrayOrPointer() && astIsBool(tok->next()->astOperand2())) assignBoolToFloatError(tok->next()); } } } }
void CheckBool::checkAssignBoolToFloat() { if (!_tokenizer->isCPP()) return; if (!_settings->isEnabled("style")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { if (tok->str() == "=" && astIsBool(tok->astOperand2())) { const Token *lhs = tok->astOperand1(); while (lhs && (lhs->str() == "." || lhs->str() == "::")) lhs = lhs->astOperand2(); if (!lhs || !lhs->variable()) continue; const Variable* var = lhs->variable(); if (var && var->isFloatingType() && !var->isArrayOrPointer()) assignBoolToFloatError(tok->next()); } } } }