From 6b0aff487fd37cebf83c1ecda24445775496e239 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 25 Jan 2012 22:05:29 -0500 Subject: [PATCH] symbol database: add preliminary support for throw/catch block scopes. Just like the rest of cppcheck, ... is not handled properly for variables. Deep namespaces are also not handled properly yet. This is not an issue because this new capability is not used by any checks so it should be harmless. --- lib/symboldatabase.cpp | 35 +++++++++++++++++++++++++++++++++++ lib/symboldatabase.h | 12 ++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index df8cfab7b..508e8d55d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -545,6 +545,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti tok = tok1; scope = &scopeList.back(); scope->nestedIn->nestedList.push_back(scope); + } else if (Token::simpleMatch(tok, "try {")) { + const Token *tok1 = tok->next(); + scopeList.push_back(Scope(this, tok, scope, Scope::eTry, tok1)); + tok = tok1; + scope = &scopeList.back(); + scope->nestedIn->nestedList.push_back(scope); + } else if (Token::simpleMatch(tok, "catch (") && + Token::simpleMatch(tok->next()->link(), ") {")) { + const Token *tok1 = tok->next()->link()->next(); + const Token *tok2 = tok->tokAt(2); + scopeList.push_back(Scope(this, tok, scope, Scope::eCatch, tok1)); + tok = tok1; + scope = &scopeList.back(); + scope->nestedIn->nestedList.push_back(scope); + // check for variable declaration and add it to new scope if found + scope->checkVariable(tok2, Throw); } else if (tok->str() == "{") { if (!Token::Match(tok->previous(), "=|,")) { scopeList.push_back(Scope(this, tok, scope, Scope::eUnconditional, tok)); @@ -1228,6 +1244,8 @@ static std::ostream & operator << (std::ostream & s, Scope::ScopeType type) type == Scope::eWhile ? "While" : type == Scope::eDo ? "Do" : type == Scope::eSwitch ? "Switch" : + type == Scope::eTry ? "Try" : + type == Scope::eCatch ? "Catch" : type == Scope::eUnconditional ? "Unconditional" : "Unknown"); return s; @@ -1254,6 +1272,7 @@ void SymbolDatabase::printVariable(const Variable *var, const char *indent) cons var->isNamespace() ? "Namespace" : var->isArgument() ? "Argument" : var->isLocal() ? "Local" : + var->isThrow() ? "Throw" : "???") << std::endl; std::cout << indent << "_flags: " << std::endl; std::cout << indent << " isMutable: " << (var->isMutable() ? "true" : "false") << std::endl; @@ -1766,6 +1785,15 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess) const Token *vartok = NULL; const Token *typetok = NULL; + // Is it a throw..? + if (Token::Match(tok, "throw %any% (") && + Token::simpleMatch(tok->linkAt(2), ") ;")) { + return tok->linkAt(2); + } else if ((Token::Match(tok, "throw %any% :: %any% (") && + Token::simpleMatch(tok->linkAt(4), ") ;"))) { + return tok->linkAt(4); + } + // Is it const..? bool isConst = false; if (tok->str() == "const") { @@ -1903,7 +1931,14 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const vartok = localVarTok; typetok = localTypeTok; isArray = false; + } else if (type == eCatch && + (Token::Match(localTypeTok, "%var% )") || + Token::Match(localTypeTok, "%var% &| %var% )"))) { + vartok = localVarTok; + typetok = localTypeTok; + isArray = false; } + isPointer = vartok && (vartok->strAt(-1) == "*" || Token::simpleMatch(vartok->tokAt(-2), "* const")); return NULL != vartok; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index b00b5e8a4..a3ccccc73 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -39,7 +39,7 @@ class SymbolDatabase; /** * @brief Access control enumerations. */ -enum AccessControl { Public, Protected, Private, Global, Namespace, Argument, Local }; +enum AccessControl { Public, Protected, Private, Global, Namespace, Argument, Local, Throw }; /** * @brief Array dimension information. @@ -245,6 +245,14 @@ public: return getFlag(fIsConst); } + /** + * Is variable a throw type. + * @return true if throw type, false if not + */ + bool isThrow() const { + return _access == Throw; + } + /** * Is variable a user defined (or unknown) type. * @return true if user defined type, false if not @@ -407,7 +415,7 @@ public: Scope *scope; }; - enum ScopeType { eGlobal, eClass, eStruct, eUnion, eNamespace, eFunction, eIf, eElse, eElseIf, eFor, eWhile, eDo, eSwitch, eUnconditional }; + enum ScopeType { eGlobal, eClass, eStruct, eUnion, eNamespace, eFunction, eIf, eElse, eElseIf, eFor, eWhile, eDo, eSwitch, eUnconditional, eTry, eCatch }; enum NeedInitialization { Unknown, True, False }; Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_);