--------------------------------------------------------------------------- Clarify calculation precedence for ternary operators. ---------------------------------------------------------------------------
| 151 | // Clarify calculation precedence for ternary operators. |
| 152 | //--------------------------------------------------------------------------- |
| 153 | void CheckOtherImpl::clarifyCalculation() |
| 154 | { |
| 155 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("clarifyCalculation")) |
| 156 | return; |
| 157 | |
| 158 | logChecker("CheckOther::clarifyCalculation"); // style |
| 159 | |
| 160 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 161 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 162 | for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { |
| 163 | // ? operator where lhs is arithmetical expression |
| 164 | if (tok->str() != "?" || !tok->astOperand1() || !tok->astOperand1()->isCalculation()) |
| 165 | continue; |
| 166 | if (!tok->astOperand1()->isArithmeticalOp() && tok->astOperand1()->tokType() != Token::eBitOp) |
| 167 | continue; |
| 168 | |
| 169 | // non-pointer calculation in lhs and pointer in rhs => no clarification is needed |
| 170 | if (tok->astOperand1()->isBinaryOp() && Token::Match(tok->astOperand1(), "%or%|&|%|*|/") && tok->astOperand2()->valueType() && tok->astOperand2()->valueType()->pointer > 0) |
| 171 | continue; |
| 172 | |
| 173 | // bit operation in lhs and char literals in rhs => probably no mistake |
| 174 | if (tok->astOperand1()->tokType() == Token::eBitOp && Token::Match(tok->astOperand2()->astOperand1(), "%char%") && Token::Match(tok->astOperand2()->astOperand2(), "%char%")) |
| 175 | continue; |
| 176 | |
| 177 | // 2nd operand in lhs has known integer value => probably no mistake |
| 178 | if (tok->astOperand1()->isBinaryOp() && tok->astOperand1()->astOperand2()->hasKnownIntValue()) { |
| 179 | const Token *op = tok->astOperand1()->astOperand2(); |
| 180 | if (op->isNumber()) |
| 181 | continue; |
| 182 | if (op->valueType() && op->valueType()->isEnum()) |
| 183 | continue; |
| 184 | } |
| 185 | |
| 186 | // Is code clarified by parentheses already? |
| 187 | const Token *tok2 = tok->astOperand1(); |
| 188 | for (; tok2; tok2 = tok2->next()) { |
| 189 | if (tok2->str() == "(") |
| 190 | tok2 = tok2->link(); |
| 191 | else if (tok2->str() == ")") |
| 192 | break; |
| 193 | else if (tok2->str() == "?") { |
| 194 | clarifyCalculationError(tok, tok->astOperand1()->str()); |
| 195 | break; |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | void CheckOtherImpl::clarifyCalculationError(const Token *tok, const std::string &op) |
| 203 | { |
no test coverage detected