Skip to content

Commit dcc1362

Browse files
committed
SymbolDatabase: Support std::array (fixes danmar#6401)
1 parent 03e44d4 commit dcc1362

File tree

3 files changed

+105
-58
lines changed

3 files changed

+105
-58
lines changed

lib/symboldatabase.cpp

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
242242
new_scope->definedType = &typeList.back();
243243
scope->definedTypes.push_back(&typeList.back());
244244

245-
scope->addVariable(varNameTok, tok, tok, access[scope], new_scope->definedType, scope);
245+
scope->addVariable(varNameTok, tok, tok, access[scope], new_scope->definedType, scope, &settings->library);
246246

247247
const Token *tok2 = tok->next();
248248

@@ -800,9 +800,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
800800
scope->nestedList.push_back(&scopeList.back());
801801
scope = &scopeList.back();
802802
if (scope->type == Scope::eFor)
803-
scope->checkVariable(tok->tokAt(2), Local); // check for variable declaration and add it to new scope if found
803+
scope->checkVariable(tok->tokAt(2), Local, &settings->library); // check for variable declaration and add it to new scope if found
804804
else if (scope->type == Scope::eCatch)
805-
scope->checkVariable(tok->tokAt(2), Throw); // check for variable declaration and add it to new scope if found
805+
scope->checkVariable(tok->tokAt(2), Throw, &settings->library); // check for variable declaration and add it to new scope if found
806806
tok = tok1;
807807
} else if (tok->str() == "{" && !tok->previous()->varId()) {
808808
if (tok->strAt(-1) == ")" && tok->linkAt(-1)->strAt(-1) == "]") {
@@ -856,7 +856,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
856856
// fill in variable info
857857
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
858858
// find variables
859-
it->getVariableList();
859+
it->getVariableList(&settings->library);
860860
}
861861

862862
// fill in function arguments
@@ -1342,7 +1342,7 @@ const Token * Variable::declEndToken() const
13421342
return declEnd;
13431343
}
13441344

1345-
void Variable::evaluate()
1345+
void Variable::evaluate(const Library* lib)
13461346
{
13471347
const Token* tok = _start;
13481348
while (tok && tok->previous() && tok->previous()->isName())
@@ -1380,7 +1380,7 @@ void Variable::evaluate()
13801380
_end = _end->previous();
13811381

13821382
if (_name)
1383-
setFlag(fIsArray, arrayDimensions(_dimensions, _name->next()));
1383+
setFlag(fIsArray, arrayDimensions(lib));
13841384
if (_start) {
13851385
setFlag(fIsClass, !_start->isStandardType() && !isPointer() && !isReference());
13861386
setFlag(fIsStlType, Token::simpleMatch(_start, "std ::"));
@@ -1396,7 +1396,7 @@ void Variable::evaluate()
13961396
tok = tok->link()->previous();
13971397
// add array dimensions if present
13981398
if (tok && tok->next()->str() == "[")
1399-
setFlag(fIsArray, arrayDimensions(_dimensions, tok->next()));
1399+
setFlag(fIsArray, arrayDimensions(lib));
14001400
}
14011401
if (!tok)
14021402
return;
@@ -1951,12 +1951,42 @@ bool Type::hasCircularDependencies(std::set<BaseInfo>* anchestors) const
19511951
return false;
19521952
}
19531953

1954-
bool Variable::arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok)
1954+
bool Variable::arrayDimensions(const Library* lib)
19551955
{
1956-
bool isArray = false;
1956+
const Library::Container* container = lib->detectContainer(_start);
1957+
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
1958+
Dimension dimension;
1959+
const Token* tok = Token::findsimplematch(_start, "<");
1960+
if (tok) {
1961+
tok = tok->next();
1962+
for (int i = 0; i < container->size_templateArgNo && tok; i++) {
1963+
tok = tok->nextTemplateArgument();
1964+
}
1965+
if (tok) {
1966+
dimension.start = tok;
1967+
dimension.end = Token::findmatch(tok, ",|>");
1968+
if (dimension.end)
1969+
dimension.end = dimension.end->previous();
1970+
if (dimension.start == dimension.end)
1971+
dimension.num = MathLib::toLongNumber(dimension.start->str());
1972+
}
1973+
_dimensions.push_back(dimension);
1974+
return true;
1975+
}
1976+
}
19571977

1958-
const Token *dim = tok;
1978+
const Token *dim = _name;
1979+
if (!dim) {
1980+
// Argument without name
1981+
dim = _end;
1982+
// back up to start of array dimensions
1983+
while (dim && dim->str() == "]")
1984+
dim = dim->link()->previous();
1985+
}
1986+
if (dim)
1987+
dim = dim->next();
19591988

1989+
bool isArray = false;
19601990
while (dim && dim->next() && dim->str() == "[") {
19611991
Dimension dimension;
19621992
// check for empty array dimension []
@@ -1966,7 +1996,7 @@ bool Variable::arrayDimensions(std::vector<Dimension> &dimensions, const Token *
19661996
if (dimension.start == dimension.end && dimension.start->isNumber())
19671997
dimension.num = MathLib::toLongNumber(dimension.start->str());
19681998
}
1969-
dimensions.push_back(dimension);
1999+
_dimensions.push_back(dimension);
19702000
dim = dim->link()->next();
19712001
isArray = true;
19722002
}
@@ -2452,7 +2482,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
24522482
}
24532483
}
24542484

2455-
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope));
2485+
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library));
24562486

24572487
if (tok->str() == ")")
24582488
break;
@@ -2634,7 +2664,7 @@ AccessControl Scope::defaultAccess() const
26342664
}
26352665

26362666
// Get variable list..
2637-
void Scope::getVariableList()
2667+
void Scope::getVariableList(const Library* lib)
26382668
{
26392669
const Token *start;
26402670

@@ -2748,14 +2778,14 @@ void Scope::getVariableList()
27482778
continue;
27492779
}
27502780

2751-
tok = checkVariable(tok, varaccess);
2781+
tok = checkVariable(tok, varaccess, lib);
27522782

27532783
if (!tok)
27542784
break;
27552785
}
27562786
}
27572787

2758-
const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
2788+
const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, const Library* lib)
27592789
{
27602790
// Is it a throw..?
27612791
if (Token::Match(tok, "throw %any% (") &&
@@ -2823,7 +2853,7 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
28232853
}
28242854
}
28252855

2826-
addVariable(vartok, typestart, vartok->previous(), varaccess, vType, this);
2856+
addVariable(vartok, typestart, vartok->previous(), varaccess, vType, this, lib);
28272857
}
28282858

28292859
return tok;

lib/symboldatabase.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
class Tokenizer;
3636
class Settings;
3737
class ErrorLogger;
38+
class Library;
3839

3940
class Scope;
4041
class SymbolDatabase;
@@ -163,16 +164,15 @@ class CPPCHECKLIB Variable {
163164

164165
/**
165166
* @brief parse and save array dimension information
166-
* @param dimensions array dimensions vector
167-
* @param tok the first '[' token of array declaration
167+
* @param lib Library instance
168168
* @return true if array, false if not
169169
*/
170-
static bool arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok);
170+
bool arrayDimensions(const Library* lib);
171171

172172
public:
173173
Variable(const Token *name_, const Token *start_, const Token *end_,
174174
std::size_t index_, AccessControl access_, const Type *type_,
175-
const Scope *scope_)
175+
const Scope *scope_, const Library* lib)
176176
: _name(name_),
177177
_start(start_),
178178
_end(end_),
@@ -181,7 +181,7 @@ class CPPCHECKLIB Variable {
181181
_flags(0),
182182
_type(type_),
183183
_scope(scope_) {
184-
evaluate();
184+
evaluate(lib);
185185
}
186186

187187
/**
@@ -553,7 +553,7 @@ class CPPCHECKLIB Variable {
553553
std::vector<Dimension> _dimensions;
554554

555555
/** @brief fill in information, depending on Tokens given at instantiation */
556-
void evaluate();
556+
void evaluate(const Library* lib);
557557
};
558558

559559
class CPPCHECKLIB Function {
@@ -857,14 +857,14 @@ class CPPCHECKLIB Scope {
857857

858858
void addVariable(const Token *token_, const Token *start_,
859859
const Token *end_, AccessControl access_, const Type *type_,
860-
const Scope *scope_) {
860+
const Scope *scope_, const Library* lib) {
861861
varlist.push_back(Variable(token_, start_, end_, varlist.size(),
862862
access_,
863-
type_, scope_));
863+
type_, scope_, lib));
864864
}
865865

866866
/** @brief initialize varlist */
867-
void getVariableList();
867+
void getVariableList(const Library* lib);
868868

869869
const Function *getDestructor() const;
870870

@@ -892,9 +892,10 @@ class CPPCHECKLIB Scope {
892892
* @brief check if statement is variable declaration and add it if it is
893893
* @param tok pointer to start of statement
894894
* @param varaccess access control of statement
895+
* @param lib Library instance
895896
* @return pointer to last token
896897
*/
897-
const Token *checkVariable(const Token *tok, AccessControl varaccess);
898+
const Token *checkVariable(const Token *tok, AccessControl varaccess, const Library* lib);
898899

899900
/**
900901
* @brief get variable from name
@@ -988,6 +989,7 @@ class CPPCHECKLIB SymbolDatabase {
988989

989990
private:
990991
friend class Scope;
992+
friend class Function;
991993

992994
void addClassFunction(Scope **info, const Token **tok, const Token *argStart);
993995
Function *addGlobalFunctionDecl(Scope*& scope, const Token* tok, const Token *argStart, const Token* funcStart);

0 commit comments

Comments
 (0)