|
24 | 24 | #include "ctu.h"
|
25 | 25 | #include "errorlogger.h"
|
26 | 26 | #include "errortypes.h"
|
| 27 | +#include "findtoken.h" |
27 | 28 | #include "library.h"
|
28 | 29 | #include "mathlib.h"
|
29 | 30 | #include "settings.h"
|
@@ -279,47 +280,72 @@ static bool isNullablePointer(const Token* tok)
|
279 | 280 | return false;
|
280 | 281 | }
|
281 | 282 |
|
282 |
| -void CheckNullPointer::nullPointerByDeRefAndChec() |
| 283 | +static bool isPointerUnevaluated(const Token *tok) |
| 284 | +{ |
| 285 | + if (isUnevaluated(tok)) |
| 286 | + return true; |
| 287 | + |
| 288 | + while (tok) { |
| 289 | + if (isUnevaluated(tok->previous())) |
| 290 | + return true; |
| 291 | + |
| 292 | + tok = tok->astParent(); |
| 293 | + } |
| 294 | + return false; |
| 295 | +} |
| 296 | + |
| 297 | + |
| 298 | +void CheckNullPointer::nullPointerByDeRefAndCheck() |
283 | 299 | {
|
284 | 300 | const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive));
|
285 | 301 |
|
286 |
| - for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
287 |
| - if (isUnevaluated(tok)) { |
288 |
| - tok = tok->linkAt(1); |
289 |
| - continue; |
290 |
| - } |
| 302 | + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 303 | + for (const Scope * scope : symbolDatabase->functionScopes) { |
| 304 | + auto pred = [printInconclusive](const Token* tok) -> bool { |
| 305 | + if (!tok) |
| 306 | + return false; |
291 | 307 |
|
292 |
| - if (Token::Match(tok, "%num%|%char%|%str%")) |
293 |
| - continue; |
| 308 | + if (Token::Match(tok, "%num%|%char%|%str%")) |
| 309 | + return false; |
294 | 310 |
|
295 |
| - if (!isNullablePointer(tok) || |
296 |
| - (tok->str() == "." && isNullablePointer(tok->astOperand2()) && tok->astOperand2()->getValue(0))) // avoid duplicate warning |
297 |
| - continue; |
| 311 | + if (!isNullablePointer(tok) || |
| 312 | + (tok->str() == "." && isNullablePointer(tok->astOperand2()) && tok->astOperand2()->getValue(0))) // avoid duplicate warning |
| 313 | + return false; |
298 | 314 |
|
299 |
| - // Can pointer be NULL? |
300 |
| - const ValueFlow::Value *value = tok->getValue(0); |
301 |
| - if (!value) |
302 |
| - continue; |
| 315 | + // Can pointer be NULL? |
| 316 | + const ValueFlow::Value *value = tok->getValue(0); |
| 317 | + if (!value) |
| 318 | + return false; |
303 | 319 |
|
304 |
| - if (!printInconclusive && value->isInconclusive()) |
305 |
| - continue; |
| 320 | + if (!printInconclusive && value->isInconclusive()) |
| 321 | + return false; |
306 | 322 |
|
307 |
| - // Pointer dereference. |
308 |
| - bool unknown = false; |
309 |
| - if (!isPointerDeRef(tok,unknown)) { |
310 |
| - if (unknown) |
311 |
| - nullPointerError(tok, tok->expressionString(), value, true); |
312 |
| - continue; |
313 |
| - } |
| 323 | + return true; |
| 324 | + }; |
| 325 | + std::vector<const Token *> tokens = findTokensSkipDeadCode(mSettings->library, scope->bodyStart, scope->bodyEnd, pred); |
| 326 | + for (const Token *tok : tokens) { |
| 327 | + if (isPointerUnevaluated(tok)) |
| 328 | + continue; |
314 | 329 |
|
315 |
| - nullPointerError(tok, tok->expressionString(), value, value->isInconclusive()); |
| 330 | + const ValueFlow::Value *value = tok->getValue(0); |
| 331 | + |
| 332 | + // Pointer dereference. |
| 333 | + bool unknown = false; |
| 334 | + if (!isPointerDeRef(tok, unknown)) { |
| 335 | + if (unknown) |
| 336 | + nullPointerError(tok, tok->expressionString(), value, true); |
| 337 | + continue; |
| 338 | + } |
| 339 | + |
| 340 | + nullPointerError(tok, tok->expressionString(), value, value->isInconclusive()); |
| 341 | + } |
316 | 342 | }
|
317 | 343 | }
|
318 | 344 |
|
319 | 345 | void CheckNullPointer::nullPointer()
|
320 | 346 | {
|
321 | 347 | logChecker("CheckNullPointer::nullPointer");
|
322 |
| - nullPointerByDeRefAndChec(); |
| 348 | + nullPointerByDeRefAndCheck(); |
323 | 349 | }
|
324 | 350 |
|
325 | 351 | namespace {
|
|
0 commit comments