| 2090 | //--------------------------------------------------------------------------- |
| 2091 | |
| 2092 | void CheckOtherImpl::checkCharVariable() |
| 2093 | { |
| 2094 | const bool warning = mSettings.severity.isEnabled(Severity::warning); |
| 2095 | const bool portability = mSettings.severity.isEnabled(Severity::portability); |
| 2096 | if (!warning && !portability) |
| 2097 | return; |
| 2098 | |
| 2099 | logChecker("CheckOther::checkCharVariable"); // warning,portability |
| 2100 | |
| 2101 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 2102 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 2103 | for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 2104 | if (Token::Match(tok, "%var% [")) { |
| 2105 | if (!tok->variable()) |
| 2106 | continue; |
| 2107 | if (!tok->variable()->isArray() && !tok->variable()->isPointer()) |
| 2108 | continue; |
| 2109 | const Token *index = tok->next()->astOperand2(); |
| 2110 | if (warning && tok->variable()->isArray() && astIsSignedChar(index) && index->getValueGE(0x80, mSettings)) |
| 2111 | signedCharArrayIndexError(tok); |
| 2112 | if (portability && astIsUnknownSignChar(index) && index->getValueGE(0x80, mSettings)) |
| 2113 | unknownSignCharArrayIndexError(tok); |
| 2114 | } else if (warning && Token::Match(tok, "[&|^]") && tok->isBinaryOp()) { |
| 2115 | bool warn = false; |
| 2116 | if (astIsSignedChar(tok->astOperand1())) { |
| 2117 | const ValueFlow::Value *v1 = tok->astOperand1()->getValueLE(-1, mSettings); |
| 2118 | const ValueFlow::Value *v2 = tok->astOperand2()->getMaxValue(false); |
| 2119 | if (!v1) |
| 2120 | v1 = tok->astOperand1()->getValueGE(0x80, mSettings); |
| 2121 | if (v1 && !(tok->str() == "&" && v2 && v2->isKnown() && v2->intvalue >= 0 && v2->intvalue < 0x100)) |
| 2122 | warn = true; |
| 2123 | } else if (astIsSignedChar(tok->astOperand2())) { |
| 2124 | const ValueFlow::Value *v1 = tok->astOperand2()->getValueLE(-1, mSettings); |
| 2125 | const ValueFlow::Value *v2 = tok->astOperand1()->getMaxValue(false); |
| 2126 | if (!v1) |
| 2127 | v1 = tok->astOperand2()->getValueGE(0x80, mSettings); |
| 2128 | if (v1 && !(tok->str() == "&" && v2 && v2->isKnown() && v2->intvalue >= 0 && v2->intvalue < 0x100)) |
| 2129 | warn = true; |
| 2130 | } |
| 2131 | |
| 2132 | // is the result stored in a short|int|long? |
| 2133 | if (warn && Token::simpleMatch(tok->astParent(), "=")) { |
| 2134 | const Token *lhs = tok->astParent()->astOperand1(); |
| 2135 | if (lhs && lhs->valueType() && lhs->valueType()->type >= ValueType::Type::SHORT) |
| 2136 | charBitOpError(tok); // This is an error.. |
| 2137 | } |
| 2138 | } |
| 2139 | } |
| 2140 | } |
| 2141 | } |
| 2142 | |
| 2143 | void CheckOtherImpl::signedCharArrayIndexError(const Token *tok) |
| 2144 | { |