diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index e19b2d01a..a1ed06528 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -36,12 +36,15 @@ void CheckExceptionSafety::destructors() const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase(); // Perform check.. - for (std::list::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) { - for (std::list::const_iterator j = i->functionList.begin(); j != i->functionList.end(); ++j) { + const std::size_t functions = symbolDatabase->functionScopes.size(); + for (std::size_t i = 0; i < functions; ++i) { + const Scope * scope = symbolDatabase->functionScopes[i]; + const Function * j = scope->function; + if (j) { // only looking for destructors - if (j->type == Function::eDestructor && j->functionScope) { + if (j->type == Function::eDestructor) { // Inspect this destructor.. - for (const Token *tok = j->functionScope->classStart->next(); tok != j->functionScope->classEnd; tok = tok->next()) { + for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { // Skip try blocks if (Token::simpleMatch(tok, "try {")) { tok = tok->next()->link(); @@ -70,52 +73,56 @@ void CheckExceptionSafety::deallocThrow() // Deallocate a global/member pointer and then throw exception // the pointer will be a dead pointer - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { - // only looking for delete now - if (tok->str() != "delete") - continue; + const std::size_t functions = symbolDatabase->functionScopes.size(); + for (std::size_t i = 0; i < functions; ++i) { + const Scope * scope = symbolDatabase->functionScopes[i]; + for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { + // only looking for delete now + if (tok->str() != "delete") + continue; - // Check if this is something similar with: "delete p;" - tok = tok->next(); - if (Token::simpleMatch(tok, "[ ]")) - tok = tok->tokAt(2); - if (!tok) - break; - if (!Token::Match(tok, "%var% ;")) - continue; - const unsigned int varid(tok->varId()); - if (varid == 0) - continue; + // Check if this is something similar with: "delete p;" + tok = tok->next(); + if (Token::simpleMatch(tok, "[ ]")) + tok = tok->tokAt(2); + if (!tok) + break; + if (!Token::Match(tok, "%var% ;")) + continue; + const unsigned int varid(tok->varId()); + if (varid == 0) + continue; - // we only look for global variables - const Variable* var = symbolDatabase->getVariableFromVarId(varid); - if (!var || !(var->isGlobal() || var->isStatic())) - continue; + // we only look for global variables + const Variable* var = symbolDatabase->getVariableFromVarId(varid); + if (!var || !(var->isGlobal() || var->isStatic())) + continue; - // Token where throw occurs - const Token *ThrowToken = 0; + // Token where throw occurs + const Token *ThrowToken = 0; - // is there a throw after the deallocation? - const Token* const end2 = tok->scope()->classEnd; - for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) { - // Throw after delete -> Dead pointer - if (tok2->str() == "throw") { - if (_settings->inconclusive) { // For inconclusive checking, throw directly. - deallocThrowError(tok2, tok->str()); + // is there a throw after the deallocation? + const Token* const end2 = tok->scope()->classEnd; + for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) { + // Throw after delete -> Dead pointer + if (tok2->str() == "throw") { + if (_settings->inconclusive) { // For inconclusive checking, throw directly. + deallocThrowError(tok2, tok->str()); + break; + } + ThrowToken = tok2; + } + + // Variable is assigned -> Bail out + else if (Token::Match(tok2, "%varid% =", varid)) { + if (ThrowToken) // For non-inconclusive checking, wait until we find an assignement to it. Otherwise we assume it is safe to leave a dead pointer. + deallocThrowError(ThrowToken, tok2->str()); break; } - ThrowToken = tok2; + // Variable passed to function. Assume it becomes assigned -> Bail out + else if (Token::Match(tok2, "[,(] &| %varid% [,)]", varid)) // TODO: No bailout if passed by value or as const reference + break; } - - // Variable is assigned -> Bail out - else if (Token::Match(tok2, "%varid% =", varid)) { - if (ThrowToken) // For non-inconclusive checking, wait until we find an assignement to it. Otherwise we assume it is safe to leave a dead pointer. - deallocThrowError(ThrowToken, tok2->str()); - break; - } - // Variable passed to function. Assume it becomes assigned -> Bail out - else if (Token::Match(tok2, "[,(] &| %varid% [,)]", varid)) // TODO: No bailout if passed by value or as const reference - break; } } }