diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b3987f719..30e6b351d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -118,7 +118,14 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti Scope *new_scope = &scopeList.back(); - scope->addVariable(tok->next()->link()->next(), tok, tok, scope->access, false, false, false, true, new_scope, scope, tok->next()->link()->strAt(2) == "["); + std::vector dimensions; + + bool isArray = false; + + if (tok->next()->link()->strAt(2) == "[") + isArray = arrayDimensions(dimensions, tok->next()->link()->tokAt(2)); + + scope->addVariable(tok->next()->link()->next(), tok, tok, scope->access, false, false, false, true, new_scope, scope, isArray, dimensions); const Token *tok2 = tok->next(); @@ -1218,6 +1225,27 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons } } +bool SymbolDatabase::arrayDimensions(std::vector &dimensions, const Token *tok) const +{ + bool isArray = false; + + const Token *dim = tok; + + while (dim->str() == "[" && dim->next() && dim->next()->str() != "]") + { + Dimension dimension; + dimension.num = 0; + dimension.start = dim->next(); + dimension.end = dim->link()->previous(); + if (dimension.start == dimension.end && dimension.start->isNumber()) + dimension.num = MathLib::toLongNumber(dimension.start->str()); + dimensions.push_back(dimension); + dim = dim->link()->next(); + isArray = true; + } + return isArray; +} + //--------------------------------------------------------------------------- unsigned int Function::initializedArgCount() const @@ -1255,6 +1283,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function isConstVar = bool(tok->str() == "const"); isArrayVar = false; hasDefault = false; + std::vector dimensions; while (tok->str() != "," && tok->str() != ")" && tok->str() != "=") { @@ -1264,7 +1293,9 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function endTok = tok->previous(); } else if (tok->str() == "[") - isArrayVar = true; + { + isArrayVar = symbolDatabase->arrayDimensions(dimensions, tok); + } else if (tok->str() == "<") { int level = 1; @@ -1327,7 +1358,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function tok = tok->next(); } - argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, hasDefault)); + argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, hasDefault, dimensions)); if (tok->str() == ")") break; @@ -1618,11 +1649,20 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess) } bool isArray = false; + std::vector dimensions; if (tok && isVariableDeclaration(tok, vartok, typetok, isArray)) { isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*"); - tok = vartok->next(); + if (isArray) + { + isArray = check->arrayDimensions(dimensions, vartok->next()); + tok = vartok->next(); + while (tok && tok->str() == "[") + tok = tok->link()->next(); + } + else + tok = vartok->next(); } // If the vartok was set in the if-blocks above, create a entry for this variable.. @@ -1636,7 +1676,7 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess) if (typetok) scope = check->findVariableType(this, typetok); - addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray); + addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray, dimensions); } return tok; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index ef4cc19ae..34ca43a87 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -27,6 +27,7 @@ #include #include "token.h" +#include "mathlib.h" class Tokenizer; class Settings; @@ -40,6 +41,16 @@ class SymbolDatabase; */ enum AccessControl { Public, Protected, Private, Global, Namespace, Argument, Local }; +/** + * @brief Array dimension information. + */ +struct Dimension +{ + const Token *start; // size start token + const Token *end; // size end token + MathLib::bigint num; // dimension length when size is a number, 0 if not known +}; + /** @brief Information about a member variable. */ class Variable { @@ -78,7 +89,8 @@ public: Variable(const Token *name_, const Token *start_, const Token *end_, std::size_t index_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_, - const Scope *scope_, bool array_, bool default_) + const Scope *scope_, bool array_, bool default_, + const std::vector &dimensions_) : _name(name_), _start(start_), _end(end_), @@ -94,6 +106,7 @@ public: setFlag(fIsClass, class_); setFlag(fIsArray, array_); setFlag(fHasDefault, default_); + _dimensions = dimensions_; } /** @@ -295,6 +308,24 @@ public: return _scope; } + /** + * Get array dimensions. + * @return array dimensions vector + */ + const std::vector &dimensions() const + { + return _dimensions; + } + + /** + * Get array dimension length. + * @return length of dimension + */ + MathLib::bigint dimension(size_t index_) const + { + return _dimensions[index_].num; + } + private: /** @brief variable name token */ const Token *_name; @@ -319,6 +350,9 @@ private: /** @brief pointer to scope this variable is in */ const Scope *_scope; + + /** @brief array dimensions */ + std::vector _dimensions; }; class Function @@ -452,11 +486,12 @@ public: void addVariable(const Token *token_, const Token *start_, const Token *end_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_, - const Scope *scope_, bool array_) + const Scope *scope_, bool array_, + const std::vector &dimensions_) { varlist.push_back(Variable(token_, start_, end_, varlist.size(), access_, mutable_, static_, const_, class_, - type_, scope_, array_, false)); + type_, scope_, array_, false, dimensions_)); } /** @brief initialize varlist */ @@ -536,6 +571,14 @@ public: */ void debugMessage(const Token *tok, const std::string &msg) const; + /** + * @brief parse and save array dimension information + * @param dimensions array dimensions vector + * @param tokenizer tokenizer pointer + * @return true if array, false if not + */ + bool arrayDimensions(std::vector &dimensions, const Token *tok) const; + private: // Needed by Borland C++: