|
22 | 22 | #include "symboldatabase.h" |
23 | 23 | #include <algorithm> |
24 | 24 | #include <cctype> |
| 25 | +#include <stack> |
25 | 26 | //--------------------------------------------------------------------------- |
26 | 27 |
|
27 | 28 | // Register this check class (by creating a static instance of it) |
@@ -219,23 +220,50 @@ void CheckSizeof::sizeofsizeofError(const Token *tok) |
219 | 220 |
|
220 | 221 | //----------------------------------------------------------------------------- |
221 | 222 | //----------------------------------------------------------------------------- |
| 223 | +static bool isCalculation(const Token *op) |
| 224 | +{ |
| 225 | + if (!op) |
| 226 | + return false; |
| 227 | + |
| 228 | + if (!Token::Match(op, "%cop%|++|--")) |
| 229 | + return false; |
| 230 | + |
| 231 | + if (Token::Match(op, "*|&")) { |
| 232 | + // dereference or address-of? |
| 233 | + if (!op->astOperand2()) |
| 234 | + return false; |
| 235 | + |
| 236 | + // type specification? |
| 237 | + std::stack<const Token *> operands; |
| 238 | + operands.push(op); |
| 239 | + while (!operands.empty()) { |
| 240 | + const Token *item = operands.top(); |
| 241 | + operands.pop(); |
| 242 | + if (item->isNumber() || item->varId() > 0) |
| 243 | + return true; |
| 244 | + if (item->astOperand1()) |
| 245 | + operands.push(item->astOperand1()); |
| 246 | + if (item->astOperand2()) |
| 247 | + operands.push(item->astOperand2()); |
| 248 | + } |
| 249 | + |
| 250 | + // type specification => return false |
| 251 | + return false; |
| 252 | + } |
| 253 | + |
| 254 | + return true; |
| 255 | +} |
| 256 | + |
222 | 257 | void CheckSizeof::sizeofCalculation() |
223 | 258 | { |
224 | 259 | if (!_settings->isEnabled("warning")) |
225 | 260 | return; |
226 | 261 |
|
227 | 262 | for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { |
228 | 263 | if (Token::simpleMatch(tok, "sizeof (")) { |
229 | | - const Token* const end = tok->linkAt(1); |
230 | | - for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) { |
231 | | - if (tok2->isConstOp() && (!tok2->isExpandedMacro() || _settings->inconclusive) && !Token::Match(tok2, ">|<|&") && (Token::Match(tok2->previous(), "%var%") || tok2->str() != "*")) { |
232 | | - if (!(Token::Match(tok2->previous(), "%type%") || Token::Match(tok2->next(), "%type%"))) { |
233 | | - sizeofCalculationError(tok2, tok2->isExpandedMacro()); |
234 | | - break; |
235 | | - } |
236 | | - } else if (tok2->type() == Token::eIncDecOp) |
237 | | - sizeofCalculationError(tok2, tok2->isExpandedMacro()); |
238 | | - } |
| 264 | + const Token *argument = tok->next()->astOperand2(); |
| 265 | + if (isCalculation(argument) && (!argument->isExpandedMacro() || _settings->inconclusive)) |
| 266 | + sizeofCalculationError(argument, argument->isExpandedMacro()); |
239 | 267 | } |
240 | 268 | } |
241 | 269 | } |
|
0 commit comments