51     logChecker(
"CheckExceptionSafety::destructors"); 
 
   66                     tok = tok->next()->link();
 
   71                     tok = tok->next()->link(); 
 
   72                     tok = tok->next()->link(); 
 
   76                 else if (tok->str() == 
"throw") {
 
   88                 "Class " + className + 
" is not safe, destructor throws exception\n" 
   89                 "The class " + className + 
" is not safe because its destructor " 
   90                 "throws an exception. If " + className + 
" is used and an exception " 
  100     logChecker(
"CheckExceptionSafety::deallocThrow"); 
 
  110             if (tok->str() != 
"delete")
 
  117             if (!tok || tok == scope->
bodyEnd)
 
  123             const Variable *var = tok->variable();
 
  127             const unsigned int varid(tok->varId());
 
  130             const Token *throwToken = 
nullptr;
 
  133             const Token* 
const end2 = tok->
scope()->bodyEnd;
 
  134             for (
const Token *tok2 = tok; tok2 != end2; tok2 = tok2->
next()) {
 
  136                 if (tok2->str() == 
"throw") {
 
  137                     if (printInconclusive) { 
 
  151                 else if (
Token::Match(tok2, 
"[,(] &| %varid% [,)]", varid)) 
 
  175     logChecker(
"CheckExceptionSafety::checkRethrowCopy"); 
 
  186                 if (
Token::simpleMatch(tok, 
"catch (") && tok->next()->link() && tok->next()->link()->next()) { 
 
  187                     tok = tok->next()->link()->next()->link();
 
  206                 "Throwing a copy of the caught exception instead of rethrowing the original exception.\n" 
  207                 "Rethrowing an exception with 'throw " + varname + 
";' creates an unnecessary copy of '" + varname + 
"'. " 
  208                 "To rethrow the caught exception without unnecessary copying or slicing, use a bare 'throw;'.", 
CWE398, 
Certainty::normal);
 
  219     logChecker(
"CheckExceptionSafety::checkCatchExceptionByValue"); 
 
  238                 "catchExceptionByValue", 
"Exception should be caught by reference.\n" 
  239                 "The exception is caught by value. It could be caught " 
  247     if (!recursive.insert(
function).second)
 
  250     if (!function->functionScope)
 
  253     for (
const Token *tok = function->functionScope->bodyStart->
next();
 
  254          tok != function->functionScope->bodyEnd; tok = tok->
next()) {
 
  257         if (tok->str() == 
"throw")
 
  259         if (tok->function()) {
 
  260             const Function * called = tok->function();
 
  277     std::set<const Function *> recursive;
 
  289     logChecker(
"CheckExceptionSafety::nothrowThrows");
 
  299         if (function->isNoExcept() &&
 
  300             (!function->noexceptArg || function->noexceptArg->str() == 
"true")) {
 
  307         else if (function->isThrow() && !function->throwArg) {
 
  314         else if (function->isAttributeNothrow()) {
 
  336     logChecker(
"CheckExceptionSafety::unhandledExceptionSpecification"); 
 
  345                 if (tok->str() == 
"try")
 
  347                 if (tok->function()) {
 
  348                     const Function * called = tok->function();
 
  362     const std::string str1(tok1 ? tok1->
str() : 
"foo");
 
  363     const std::list<const Token*> locationList = { tok1, tok2 };
 
  365                 "Unhandled exception specification when calling function " + str1 + 
"().\n" 
  366                 "Unhandled exception specification when calling function " + str1 + 
"(). " 
  367                 "Either use a try/catch around the function call, or add a exception specification for " + funcname + 
"() also.", 
CWE703, 
Certainty::inconclusive);
 
  375     logChecker(
"CheckExceptionSafety::rethrowNoCurrentException");
 
  385         if (
Token::simpleMatch(function->functionScope->bodyStart->next(), 
"try { throw ; } catch ("))
 
  388         for (
const Token *tok = function->functionScope->bodyStart->
next();
 
  389              tok != function->functionScope->bodyEnd; tok = tok->
next()) {
 
  391                 tok = tok->linkAt(1);       
 
  393                     tok = tok->linkAt(1);   
 
  407                 "Rethrowing current exception with 'throw;', it seems there is no current exception to rethrow." 
  408                 " If there is no current exception this calls std::terminate()." 
  409                 " More: https://isocpp.org/wiki/faq/exceptions#throw-without-an-object",
 
static const CWE CWE398(398U)
 
static const Token * functionThrowsRecursive(const Function *function, std::set< const Function * > &recursive)
 
static const Token * functionThrows(const Function *function)
 
static const CWE CWE480(480U)
 
static const CWE CWE703(703U)
 
Check exception safety (exceptions shouldn't cause leaks nor corrupt data)
 
void unhandledExceptionSpecification()
Check for unhandled exception specification
 
void destructors()
Don't throw exceptions in destructors.
 
void nothrowThrows()
Check for functions that throw that shouldn't
 
void deallocThrowError(const Token *const tok, const std::string &varname)
 
void rethrowCopyError(const Token *const tok, const std::string &varname)
 
void noexceptThrowError(const Token *const tok)
 
void rethrowNoCurrentException()
Check for rethrow not from catch scope
 
void checkCatchExceptionByValue()
Check for exceptions that are caught by value instead of by reference
 
void catchExceptionByValueError(const Token *tok)
 
void deallocThrow()
deallocating memory and then throw (dead pointer)
 
void rethrowNoCurrentExceptionError(const Token *tok)
Rethrow without currently handled exception.
 
void checkRethrowCopy()
Don't rethrow a copy of the caught exception; use a bare throw instead.
 
void unhandledExceptionSpecificationError(const Token *const tok1, const Token *const tok2, const std::string &funcname)
Missing exception specification.
 
void destructorsError(const Token *const tok, const std::string &className)
Don't throw exceptions in destructors.
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
const std::string & name() const
 
const Scope * functionScope
scope of function body
 
const Token * throwArg
throw token
 
const Token * tokenDef
function name token in class definition
 
const Token * noexceptArg
noexcept token
 
bool isentrypoint(const std::string &func) const
 
Function * function
function info for this function
 
const Token * classDef
class/struct/union/namespace token
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
 
SimpleEnableGroup< Certainty > certainty
 
SimpleEnableGroup< Severity > severity
 
bool isEnabled(T flag) const
 
std::vector< const Scope * > functionScopes
Fast access to function scopes.
 
std::list< Scope > scopeList
Information about all namespaces/classes/structures.
 
The token list that the TokenList generates is a linked-list of this class.
 
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
 
const Token * tokAt(int index) const
 
void scope(const Scope *s)
Associate this token with given scope.
 
const Token * linkAt(int index) const
 
void variable(const Variable *v)
Associate this token with given variable.
 
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
 
void astParent(Token *tok)
 
const SymbolDatabase * getSymbolDatabase() const
 
Information about a member variable.
 
bool isClass() const
Is variable a user defined (or unknown) type.
 
bool isReference() const
Is reference variable.
 
bool isGlobal() const
Is variable global.
 
bool isPointer() const
Is pointer variable.
 
bool isStatic() const
Is variable static.
 
@ error
Programming error.