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

Method simplifyNumericCalculations

lib/templatesimplifier.cpp:2391–2483  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2389
2390
2391bool TemplateSimplifier::simplifyNumericCalculations(Token *tok, bool isTemplate)
2392{
2393 bool ret = false;
2394 // (1-2)
2395 while (tok->tokAt(3) && tok->isNumber() && tok->tokAt(2)->isNumber()) { // %any% %num% %any% %num% %any%
2396 const Token *before = tok->previous();
2397 if (!before)
2398 break;
2399 const Token* op = tok->next();
2400 const Token* after = tok->tokAt(3);
2401 const std::string &num1 = op->strAt(-1);
2402 const std::string &num2 = op->strAt(1);
2403 if (Token::Match(before, "* %num% /") && (num2 != "0") && num1 == MathLib::multiply(num2, MathLib::divide(num1, num2))) {
2404 // Division where result is a whole number
2405 } else if (!((op->str() == "*" && (isLowerThanMulDiv(before) || before->str() == "*") && isLowerEqualThanMulDiv(after)) || // associative
2406 (Token::Match(op, "[/%]") && isLowerThanMulDiv(before) && isLowerEqualThanMulDiv(after)) || // NOT associative
2407 (Token::Match(op, "[+-]") && isLowerThanMulDiv(before) && isLowerThanMulDiv(after)) || // Only partially (+) associative, but handled later
2408 (Token::Match(op, ">>|<<") && isLowerThanShift(before) && isLowerThanPlusMinus(after)) || // NOT associative
2409 (op->str() == "&" && isLowerThanShift(before) && isLowerThanShift(after)) || // associative
2410 (op->str() == "^" && isLowerThanAnd(before) && isLowerThanAnd(after)) || // associative
2411 (op->str() == "|" && isLowerThanXor(before) && isLowerThanXor(after)) || // associative
2412 (op->str() == "&&" && isLowerThanOr(before) && isLowerThanOr(after)) ||
2413 (op->str() == "||" && isLowerThanLogicalAnd(before) && isLowerThanLogicalAnd(after))))
2414 break;
2415
2416 // Don't simplify "%num% / 0"
2417 if (Token::Match(op, "[/%] 0")) {
2418 if (isTemplate)
2419 throw InternalError(op, "Instantiation error: Divide by zero in template instantiation.", InternalError::INSTANTIATION);
2420 return ret;
2421 }
2422
2423 // Integer operations
2424 if (Token::Match(op, ">>|<<|&|^|%or%")) {
2425 // Don't simplify if operand is negative, shifting with negative
2426 // operand is UB. Bitmasking with negative operand is implementation
2427 // defined behaviour.
2428 if (MathLib::isNegative(num1) || MathLib::isNegative(num2))
2429 break;
2430
2431 const MathLib::value v1(num1);
2432 const MathLib::value v2(num2);
2433
2434 if (!v1.isInt() || !v2.isInt())
2435 break;
2436
2437 switch (op->str()[0]) {
2438 case '<':
2439 tok->str((v1 << v2).str());
2440 break;
2441 case '>':
2442 tok->str((v1 >> v2).str());
2443 break;
2444 case '&':
2445 tok->str((v1 & v2).str());
2446 break;
2447 case '|':
2448 tok->str((v1 | v2).str());

Callers

nothing calls this directly

Calls 15

isLowerThanMulDivFunction · 0.85
isLowerEqualThanMulDivFunction · 0.85
isLowerThanShiftFunction · 0.85
isLowerThanPlusMinusFunction · 0.85
isLowerThanAndFunction · 0.85
isLowerThanXorFunction · 0.85
isLowerThanOrFunction · 0.85
isLowerThanLogicalAndFunction · 0.85
isNegativeFunction · 0.85
calculateFunction · 0.85
nextMethod · 0.80
deleteNextMethod · 0.80

Tested by

no test coverage detected