Refactorizations in SymbolDatabase:

- Moved complete evaluation of variables type into one function executed when the variable is constructed
- Moved SymbolDatabase::ArrayDimensions to Variable::ArrayDimensions
This commit is contained in:
PKEuS 2012-05-11 17:56:47 +02:00
parent 11a296cb02
commit 0452b03f53
3 changed files with 209 additions and 211 deletions

View File

@ -121,25 +121,14 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
Scope *new_scope = &scopeList.back();
access[new_scope] = Public;
std::vector<Dimension> dimensions;
bool isPointer = false;
bool isReference = false;
bool isArray = false;
const Token* varNameTok = tok->next()->link()->next();
if (varNameTok->str() == "*") {
isPointer = true;
varNameTok = varNameTok->next();
} else if (varNameTok->str() == "&") {
isReference = true;
varNameTok = varNameTok->next();
}
if (varNameTok->next()->str() == "[")
isArray = arrayDimensions(dimensions, varNameTok->next());
scope->addVariable(varNameTok, tok, tok, access[scope], false, false, false, true, new_scope, scope, isArray, isPointer, isReference, dimensions);
scope->addVariable(varNameTok, tok, tok, access[scope], new_scope, scope);
const Token *tok2 = tok->next();
@ -817,6 +806,39 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
return false;
}
void Variable::evaluate()
{
const Token* tok = _start;
if (tok && tok->previous() && tok->previous()->isName())
tok = tok->previous();
for (; tok != _name; tok = tok->next()) {
if (tok->str() == "<")
tok->findClosingBracket(tok);
if (tok->str() == "static")
setFlag(fIsStatic, true);
else if (tok->str() == "mutable")
setFlag(fIsMutable, true);
else if (tok->str() == "const")
setFlag(fIsConst, true);
else if (tok->str() == "*") {
setFlag(fIsPointer, true);
setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
} else if (tok->str() == "&")
setFlag(fIsReference, true);
}
if (_name)
setFlag(fIsArray, arrayDimensions(_dimensions, _name->next()));
if (_start)
setFlag(fIsClass, !_start->isStandardType() && !isPointer() && !isReference());
if (_access == Argument && _name) {
const Token* tok = _name->next();
while (tok->str() == "[")
tok = tok->link();
setFlag(fHasDefault, tok->str() == "=");
}
}
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth)
{
while (first->str() == second->str()) {
@ -1233,7 +1255,7 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons
}
}
bool SymbolDatabase::arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok) const
bool Variable::arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok)
{
bool isArray = false;
@ -1524,18 +1546,12 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
const Token* startTok = tok;
const Token* endTok = NULL;
const Token* nameTok = NULL;
bool isConstVar = bool(tok->str() == "const");
bool isArrayVar = false;
bool hasDefault = false;
std::vector<Dimension> dimensions;
while (tok->str() != "," && tok->str() != ")" && tok->str() != "=") {
if (tok->varId() != 0) {
nameTok = tok;
endTok = tok->previous();
} else if (tok->str() == "[") {
isArrayVar = symbolDatabase->arrayDimensions(dimensions, tok);
// skip array dimension(s)
tok = tok->link();
while (tok->next()->str() == "[")
@ -1552,7 +1568,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
return;
}
const Token *typeTok = startTok->tokAt(isConstVar ? 1 : 0);
const Token *typeTok = startTok->tokAt(startTok->str() == "const" ? 1 : 0);
if (typeTok->str() == "struct")
typeTok = typeTok->next();
@ -1575,19 +1591,13 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
if (!typeTok->isStandardType())
argType = symbolDatabase->findVariableType(scope, typeTok);
bool isClassVar = startTok == endTok && !startTok->isStandardType();
bool isPointerVar = nameTok->strAt(-1) == "*" || nameTok->strAt(-2) == "*";
bool isReferenceVar = nameTok->strAt(-1) == "&";
// skip default values
if (tok->str() == "=") {
hasDefault = true;
while (tok->str() != "," && tok->str() != ")")
tok = tok->next();
}
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, isPointerVar, isReferenceVar, hasDefault, dimensions));
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope));
if (tok->str() == ")")
break;
@ -1883,56 +1893,38 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
}
// Is it const..?
bool isConst(tok->str() == "const");
if (isConst) {
if (tok->str() == "const") {
tok = tok->next();
}
// Is it a static variable?
const bool isStatic(tok->str() == "static");
if (isStatic) {
if (tok->str() == "static") {
tok = tok->next();
}
// Is it a mutable variable?
const bool isMutable(tok->str() == "mutable");
if (isMutable) {
if (tok->str() == "mutable") {
tok = tok->next();
}
// Is it const..?
if (tok->str() == "const") {
tok = tok->next();
isConst = true;
}
// the start of the type tokens does not include the above modifiers
const Token *typestart = tok;
bool isClass = false;
if (Token::Match(tok, "struct|union")) {
tok = tok->next();
}
bool isArray = false;
bool isPointer = false;
bool isReference = false;
std::vector<Dimension> dimensions;
if (tok && isVariableDeclaration(tok, vartok, typetok, isArray, isPointer, isReference)) {
isClass = (!typetok->isStandardType() && !isPointer && vartok->previous()->str() != "&");
if (isArray) {
isArray = check->arrayDimensions(dimensions, vartok->next());
if (tok && isVariableDeclaration(tok, vartok, typetok)) {
// If the vartok was set in the if-blocks above, create a entry for this variable..
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..
if (vartok && vartok->str() != "operator") {
if (vartok->varId() == 0 && !vartok->isBoolean())
check->debugMessage(vartok, "Scope::checkVariable found variable \'" + vartok->str() + "\' with varid 0.");
@ -1941,7 +1933,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, isPointer, isReference, dimensions);
addVariable(vartok, typestart, vartok->previous(), varaccess, scope, this);
}
return tok;
@ -1980,7 +1972,7 @@ static const Token* skipPointers(const Token* tok)
return tok;
}
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const
{
if (tok && tok->str() == "throw" && check->_tokenizer->isCPP())
return false;
@ -2006,28 +1998,21 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
if (Token::Match(localVarTok, "%var% ;|=")) {
vartok = localVarTok;
typetok = localTypeTok;
isArray = false;
} else if (Token::Match(localVarTok, "%var% [") && localVarTok->str() != "operator") {
vartok = localVarTok;
typetok = localTypeTok;
isArray = true;
} else if ((isLocal() || type == Scope::eFunction) &&
Token::Match(localVarTok, "%var% (") &&
Token::simpleMatch(localVarTok->next()->link(), ") ;")) {
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"));
isReference = vartok && vartok->strAt(-1) == "&";
return NULL != vartok;
}

View File

@ -84,12 +84,18 @@ class Variable {
_flags = state_ ? _flags | flag_ : _flags & ~flag_;
}
/**
* @brief parse and save array dimension information
* @param dimensions array dimensions vector
* @param tok the first '[' token of array declaration
* @return true if array, false if not
*/
static bool arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok);
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 pointer_, bool reference_,
bool default_, const std::vector<Dimension> &dimensions_)
std::size_t index_, AccessControl access_, const Scope *type_,
const Scope *scope_)
: _name(name_),
_start(start_),
_end(end_),
@ -98,15 +104,7 @@ public:
_flags(0),
_type(type_),
_scope(scope_) {
setFlag(fIsMutable, mutable_);
setFlag(fIsStatic, static_);
setFlag(fIsConst, const_);
setFlag(fIsClass, class_);
setFlag(fIsArray, array_);
setFlag(fIsPointer, pointer_);
setFlag(fIsReference, reference_);
setFlag(fHasDefault, default_);
_dimensions = dimensions_;
evaluate();
}
/**
@ -354,6 +352,9 @@ private:
/** @brief array dimensions */
std::vector<Dimension> _dimensions;
/** @brief fill in information, depending on Tokens given at instanciation */
void evaluate();
};
class Function {
@ -384,7 +385,6 @@ public:
std::size_t argCount() const {
return argumentList.size();
}
/** @brief get a pointer to the variable instance associated with the given argument number */
const Variable* getArgumentVar(unsigned int num) const;
unsigned int initializedArgCount() const;
void addArguments(const SymbolDatabase *symbolDatabase, const Scope *scope);
@ -486,13 +486,11 @@ public:
const Scope * findQualifiedScope(const std::string & name) const;
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_, bool pointer_, bool reference_,
const std::vector<Dimension> &dimensions_) {
const Token *end_, AccessControl access_, const Scope *type_,
const Scope *scope_) {
varlist.push_back(Variable(token_, start_, end_, varlist.size(),
access_, mutable_, static_, const_, class_,
type_, scope_, array_, pointer_, reference_, false, dimensions_));
access_,
type_, scope_));
}
/** @brief initialize varlist */
@ -537,7 +535,7 @@ private:
* @param isPointer reference to variable to set if pointer is found
* @return true if tok points to a variable declaration, false otherwise
*/
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const;
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
};
class SymbolDatabase {
@ -578,14 +576,6 @@ public:
*/
void debugMessage(const Token *tok, const std::string &msg) const;
/**
* @brief parse and save array dimension information
* @param dimensions array dimensions vector
* @param tok the first '[' token of array declaration
* @return true if array, false if not
*/
bool arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok) const;
void printOut(const char * title = NULL) const;
void printVariable(const Variable *var, const char *indent) const;

View File

@ -44,31 +44,21 @@ public:
,vartok(NULL)
,typetok(NULL)
,t(NULL)
,isArray(false)
,isPointer(false)
,isReference(false)
,found(false)
{}
virtual void reportOut(const std::string &outmsg) {
errout << outmsg << std::endl;
}
private:
const Scope si;
const Token* vartok;
const Token* typetok;
const Token* t;
bool isArray;
bool isPointer;
bool isReference;
bool found;
void reset() {
vartok = NULL;
typetok = NULL;
t = NULL;
isArray = false;
isPointer = false;
isReference = false;
found = false;
}
void run() {
@ -157,287 +147,301 @@ private:
void test_isVariableDeclarationCanHandleNull() {
reset();
bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(NULL, vartok, typetok);
ASSERT_EQUALS(false, result);
ASSERT(NULL == vartok);
ASSERT(NULL == typetok);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(NULL, NULL, NULL, 0, Public, 0, 0);
}
void test_isVariableDeclarationIdentifiesSimpleDeclaration() {
reset();
givenACodeSampleToTokenize simpleDeclaration("int x;");
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesScopedDeclaration() {
reset();
givenACodeSampleToTokenize ScopedDeclaration("::int x;");
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesStdDeclaration() {
reset();
givenACodeSampleToTokenize StdDeclaration("std::string x;");
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesScopedStdDeclaration() {
reset();
givenACodeSampleToTokenize StdDeclaration("::std::string x;");
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesManyScopes() {
reset();
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;");
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("EE", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesPointers() {
reset();
givenACodeSampleToTokenize pointer("int* p;");
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationDoesNotIdentifyConstness() {
reset();
givenACodeSampleToTokenize constness("const int* cp;");
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok);
ASSERT_EQUALS(false, result);
ASSERT(NULL == vartok);
ASSERT(NULL == typetok);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesFirstOfManyVariables() {
reset();
givenACodeSampleToTokenize multipleDeclaration("int first, second;");
bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("first", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() {
reset();
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;");
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("EE", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() {
reset();
givenACodeSampleToTokenize pointerToPointer("int** pp;");
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("pp", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() {
reset();
givenACodeSampleToTokenize pointerToPointer("int***** p;");
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesArray() {
reset();
givenACodeSampleToTokenize array("::std::string v[3];");
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("v", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(true == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(true == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void test_isVariableDeclarationIdentifiesOfArrayPointers() {
reset();
givenACodeSampleToTokenize array("A *a[5];");
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("a", vartok->str());
ASSERT_EQUALS("A", typetok->str());
ASSERT(true == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(true == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesTemplatedPointerVariable() {
reset();
givenACodeSampleToTokenize var("std::set<char>* chars;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("chars", vartok->str());
ASSERT_EQUALS("set", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<int>*** ints;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesTemplatedArrayVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<int> ints[3];");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(true == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(true == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesTemplatedVariable() {
reset();
givenACodeSampleToTokenize var("std::vector<int> ints;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("vector", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesTemplatedVariableIterator() {
reset();
givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("floats", vartok->str());
ASSERT_EQUALS("const_iterator", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesNestedTemplateVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("intsets", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(false == v.isPointer());
ASSERT(false == v.isReference());
}
void isVariableDeclarationIdentifiesReference() {
reset();
givenACodeSampleToTokenize var1("int& foo;");
bool result1 = si.isVariableDeclaration(var1.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result1 = si.isVariableDeclaration(var1.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result1);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
Variable v1(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v1.isArray());
ASSERT(false == v1.isPointer());
ASSERT(true == v1.isReference());
reset();
givenACodeSampleToTokenize var2("foo*& bar;");
bool result2 = si.isVariableDeclaration(var2.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result2 = si.isVariableDeclaration(var2.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result2);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
Variable v2(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v2.isArray());
ASSERT(true == v2.isPointer());
ASSERT(true == v2.isReference());
reset();
givenACodeSampleToTokenize var3("std::vector<int>& foo;");
bool result3 = si.isVariableDeclaration(var3.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result3 = si.isVariableDeclaration(var3.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result3);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
Variable v3(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v3.isArray());
ASSERT(false == v3.isPointer());
ASSERT(true == v3.isReference());
}
void isVariableDeclarationDoesNotIdentifyTemplateClass() {
reset();
givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(false, result);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationPointerConst() {
reset();
givenACodeSampleToTokenize var("std::string const* s;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok);
ASSERT_EQUALS(true, result);
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0);
ASSERT(false == v.isArray());
ASSERT(true == v.isPointer());
ASSERT(false == v.isReference());
}
void hasRegularFunction() {
@ -450,12 +454,14 @@ private:
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->next());
ASSERT(scope && scope->className == "func");
ASSERT(scope && scope->functionOf == 0);
const Function *function = db->findFunctionByToken(tokenizer.tokens()->next());
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->next());
ASSERT(function && function->hasBody);
ASSERT(function && function->functionScope == scope && scope->function == function);
}
}
@ -469,12 +475,14 @@ private:
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(4));
ASSERT(scope && scope->className == "func");
ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(4));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(4));
ASSERT(function && function->hasBody && function->isInline);
ASSERT(function && function->functionScope == scope && scope->function == function);
}
}
@ -507,12 +515,14 @@ private:
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(12));
ASSERT(scope && scope->className == "func");
ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(12));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(12));
ASSERT(function && function->hasBody && !function->isInline);
ASSERT(function && function->functionScope == scope && scope->function == function);
}
}
@ -712,14 +722,27 @@ private:
}
void functionArgs1() {
check("void f(std::vector<std::string s>, const std::vector<int> & v) { }\n");
{
GET_SYMBOL_DB("void f(std::vector<std::string>, const std::vector<int> & v) { }");
TODO_ASSERT_EQUALS(1+1, 1+2, db->getVariableListSize());
const Variable* v = db->getVariableFromVarId(2); // TODO: varId 1
ASSERT(v && v->isReference() && v->isConst() && v->isArgument());
const Scope* f = db->findScopeByName("f");
ASSERT(f && f->type == Scope::eFunction && f->function);
if (f && f->function)
ASSERT(f->function->argumentList.size() == 2 && f->function->argumentList.front().index() == 0 && f->function->argumentList.front().name() == "" && f->function->argumentList.back().index() == 1);
ASSERT_EQUALS("", errout.str());
check("void f(std::map<std::string, std::vector<int> > m) { }\n");
}
{
GET_SYMBOL_DB("void g(std::map<std::string, std::vector<int> > m) { }");
ASSERT_EQUALS(1+1, db->getVariableListSize());
const Variable* m = db->getVariableFromVarId(1);
ASSERT(m && !m->isReference() && !m->isConst() && m->isArgument() && m->isClass());
const Scope* g = db->findScopeByName("g");
ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().index() == 0);
ASSERT_EQUALS("", errout.str());
}
}
void functionArgs2() {
GET_SYMBOL_DB("void f(int a[][4]) { }");