MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / deallocThrow

Method deallocThrow

lib/checkexceptionsafety.cpp:91–152  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

89
90
91void CheckExceptionSafetyImpl::deallocThrow()
92{
93 if (!mSettings.severity.isEnabled(Severity::warning) && !mSettings.isPremiumEnabled("exceptDeallocThrow"))
94 return;
95
96 logChecker("CheckExceptionSafety::deallocThrow"); // warning
97
98 const bool printInconclusive = mSettings.certainty.isEnabled(Certainty::inconclusive);
99 const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase();
100
101 // Deallocate a global/member pointer and then throw exception
102 // the pointer will be a dead pointer
103 for (const Scope * scope : symbolDatabase->functionScopes) {
104 for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
105 // only looking for delete now
106 if (tok->str() != "delete")
107 continue;
108
109 // Check if this is something similar with: "delete p;"
110 tok = tok->next();
111 if (Token::simpleMatch(tok, "[ ]"))
112 tok = tok->tokAt(2);
113 if (!tok || tok == scope->bodyEnd)
114 break;
115 if (!Token::Match(tok, "%var% ;"))
116 continue;
117
118 // we only look for global variables
119 const Variable *var = tok->variable();
120 if (!var || !(var->isGlobal() || var->isStatic()))
121 continue;
122
123 const unsigned int varid(tok->varId());
124
125 // Token where throw occurs
126 const Token *throwToken = nullptr;
127
128 // is there a throw after the deallocation?
129 const Token* const end2 = tok->scope()->bodyEnd;
130 for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) {
131 // Throw after delete -> Dead pointer
132 if (tok2->str() == "throw") {
133 if (printInconclusive) { // For inconclusive checking, throw directly.
134 deallocThrowError(tok2, tok->str());
135 break;
136 }
137 throwToken = tok2;
138 }
139
140 // Variable is assigned -> Bail out
141 else if (Token::Match(tok2, "%varid% =", varid)) {
142 if (throwToken) // For non-inconclusive checking, wait until we find an assignment to it. Otherwise we assume it is safe to leave a dead pointer.
143 deallocThrowError(throwToken, tok2->str());
144 break;
145 }
146 // Variable passed to function. Assume it becomes assigned -> Bail out
147 else if (Token::Match(tok2, "[,(] &| %varid% [,)]", varid)) // TODO: No bailout if passed by value or as const reference
148 break;

Callers 1

runChecksMethod · 0.80

Calls 9

isPremiumEnabledMethod · 0.80
nextMethod · 0.80
variableMethod · 0.80
scopeMethod · 0.80
simpleMatchFunction · 0.70
isEnabledMethod · 0.45
strMethod · 0.45
tokAtMethod · 0.45
isGlobalMethod · 0.45

Tested by

no test coverage detected