MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / checkMathFunctions

Method checkMathFunctions

lib/checkfunctions.cpp:442–501  ·  view source on GitHub ↗

--------------------------------------------------------------------------- Detect passing wrong values to functions like atan(0, x); ---------------------------------------------------------------------------

Source from the content-addressed store, hash-verified

440// Detect passing wrong values to <cmath> functions like atan(0, x);
441//---------------------------------------------------------------------------
442void CheckFunctionsImpl::checkMathFunctions()
443{
444 const bool styleC99 = mSettings.severity.isEnabled(Severity::style) && ((mTokenizer->isC() && mSettings.standards.c != Standards::C89) || (mTokenizer->isCPP() && mSettings.standards.cpp != Standards::CPP03));
445 const bool printWarnings = mSettings.severity.isEnabled(Severity::warning);
446
447 if (!styleC99 && !printWarnings && !mSettings.isPremiumEnabled("wrongmathcall"))
448 return;
449
450 logChecker("CheckFunctions::checkMathFunctions"); // style,warning,c99,c++11
451
452 const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
453 for (const Scope *scope : symbolDatabase->functionScopes) {
454 for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
455 if (tok->varId())
456 continue;
457 if (printWarnings && Token::Match(tok, "%name% ( !!)")) {
458 if (tok->strAt(-1) != "."
459 && Token::Match(tok, "log|logf|logl|log10|log10f|log10l|log2|log2f|log2l ( %num% )")) {
460 const std::string& number = tok->strAt(2);
461 if ((MathLib::isInt(number) && MathLib::toBigNumber(number) <= 0) ||
462 (MathLib::isFloat(number) && MathLib::toDoubleNumber(number) <= 0.))
463 mathfunctionCallWarning(tok);
464 } else if (Token::Match(tok, "log1p|log1pf|log1pl ( %num% )")) {
465 const std::string& number = tok->strAt(2);
466 if ((MathLib::isInt(number) && MathLib::toBigNumber(number) <= -1) ||
467 (MathLib::isFloat(number) && MathLib::toDoubleNumber(number) <= -1.))
468 mathfunctionCallWarning(tok);
469 }
470 // atan2 ( x , y): x and y can not be zero, because this is mathematically not defined
471 else if (Token::Match(tok, "atan2|atan2f|atan2l ( %num% , %num% )")) {
472 if (MathLib::isNullValue(tok->strAt(2)) && MathLib::isNullValue(tok->strAt(4)))
473 mathfunctionCallWarning(tok, 2);
474 }
475 // fmod ( x , y) If y is zero, then either a range error will occur or the function will return zero (implementation-defined).
476 else if (Token::Match(tok, "fmod|fmodf|fmodl (")) {
477 const Token* nextArg = tok->tokAt(2)->nextArgument();
478 if (nextArg && MathLib::isNullValue(nextArg->str()))
479 mathfunctionCallWarning(tok, 2);
480 }
481 // pow ( x , y) If x is zero, and y is negative --> division by zero
482 else if (Token::Match(tok, "pow|powf|powl ( %num% , %num% )")) {
483 if (MathLib::isNullValue(tok->strAt(2)) && MathLib::isNegative(tok->strAt(4)))
484 mathfunctionCallWarning(tok, 2);
485 }
486 }
487
488 if (styleC99) {
489 if (Token::Match(tok, "%num% - erf (") && Tokenizer::isOneNumber(tok->str()) && tok->next()->astOperand2() == tok->tokAt(3)) {
490 mathfunctionCallWarning(tok, "1 - erf(x)", "erfc(x)");
491 } else if (Token::simpleMatch(tok, "exp (") && Token::Match(tok->linkAt(1), ") - %num%") && Tokenizer::isOneNumber(tok->linkAt(1)->strAt(2)) && tok->linkAt(1)->next()->astOperand1() == tok->next()) {
492 mathfunctionCallWarning(tok, "exp(x) - 1", "expm1(x)");
493 } else if (Token::simpleMatch(tok, "log (") && tok->next()->astOperand2()) {
494 const Token* plus = tok->next()->astOperand2();
495 if (plus->str() == "+" && ((plus->astOperand1() && Tokenizer::isOneNumber(plus->astOperand1()->str())) || (plus->astOperand2() && Tokenizer::isOneNumber(plus->astOperand2()->str()))))
496 mathfunctionCallWarning(tok, "log(1 + x)", "log1p(x)");
497 }
498 }
499 }

Callers 1

runChecksMethod · 0.80

Calls 14

isFloatFunction · 0.85
isNegativeFunction · 0.85
isCMethod · 0.80
isCPPMethod · 0.80
isPremiumEnabledMethod · 0.80
nextMethod · 0.80
astOperand2Method · 0.80
linkAtMethod · 0.80
astOperand1Method · 0.80
simpleMatchFunction · 0.70
isEnabledMethod · 0.45
nextArgumentMethod · 0.45

Tested by

no test coverage detected