Added support for references to symboldatabase

This commit is contained in:
PKEuS 2012-01-26 17:04:25 +01:00
parent 5c2af0b2e3
commit 6906001366
3 changed files with 109 additions and 41 deletions

View File

@ -107,7 +107,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// unnamed struct and union
else if (Token::Match(tok, "struct|union {") &&
Token::Match(tok->next()->link(), "} |* %var% ;|[")) {
Token::Match(tok->next()->link(), "} *|&| %var% ;|[")) {
scopeList.push_back(Scope(this, tok, scope));
Scope *new_scope = &scopeList.back();
@ -115,18 +115,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
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, scope->access, false, false, false, true, new_scope, scope, isArray, isPointer, dimensions);
scope->addVariable(varNameTok, tok, tok, scope->access, false, false, false, true, new_scope, scope, isArray, isPointer, isReference, dimensions);
const Token *tok2 = tok->next();
@ -1281,6 +1285,7 @@ void SymbolDatabase::printVariable(const Variable *var, const char *indent) cons
std::cout << indent << " isClass: " << (var->isClass() ? "true" : "false") << std::endl;
std::cout << indent << " isArray: " << (var->isArray() ? "true" : "false") << std::endl;
std::cout << indent << " isPointer: " << (var->isPointer() ? "true" : "false") << std::endl;
std::cout << indent << " isReference: " << (var->isReference() ? "true" : "false") << std::endl;
std::cout << indent << " hasDefault: " << (var->hasDefault() ? "true" : "false") << std::endl;
std::cout << indent << "_type: ";
if (var->type()) {
@ -1557,6 +1562,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
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() == "=") {
@ -1566,7 +1572,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, isPointerVar, hasDefault, dimensions));
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, isPointerVar, isReferenceVar, hasDefault, dimensions));
if (tok->str() == ")")
break;
@ -1830,10 +1836,10 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
bool isArray = false;
bool isPointer = false;
bool isReference = false;
std::vector<Dimension> dimensions;
if (tok && isVariableDeclaration(tok, vartok, typetok, isArray, isPointer)) {
isPointer = vartok->previous()->str() == "*" || Token::simpleMatch(vartok->tokAt(-2), "* const");
if (tok && isVariableDeclaration(tok, vartok, typetok, isArray, isPointer, isReference)) {
isClass = (!typetok->isStandardType() && !isPointer && vartok->previous()->str() != "&");
if (isArray) {
isArray = check->arrayDimensions(dimensions, vartok->next());
@ -1854,7 +1860,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, dimensions);
addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray, isPointer, isReference, dimensions);
}
return tok;
@ -1897,7 +1903,7 @@ inline const Token* skipPointers(const Token* tok)
return ret;
}
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer) const
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const
{
const Token* localTypeTok = skipScopeIdentifiers(tok);
const Token* localVarTok = NULL;
@ -1940,6 +1946,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
}
isPointer = vartok && (vartok->strAt(-1) == "*" || Token::simpleMatch(vartok->tokAt(-2), "* const"));
isReference = vartok && vartok->strAt(-1) == "&";
return NULL != vartok;
}

View File

@ -62,7 +62,8 @@ class Variable {
fIsClass = (1 << 3), /** @brief user defined type */
fIsArray = (1 << 4), /** @brief array variable */
fIsPointer = (1 << 5), /** @brief pointer variable */
fHasDefault = (1 << 6) /** @brief function argument with default value */
fIsReference = (1 << 6), /** @brief reference variable */
fHasDefault = (1 << 7) /** @brief function argument with default value */
};
/**
@ -87,8 +88,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 pointer_, bool default_,
const std::vector<Dimension> &dimensions_)
const Scope *scope_, bool array_, bool pointer_, bool reference_,
bool default_, const std::vector<Dimension> &dimensions_)
: _name(name_),
_start(start_),
_end(end_),
@ -103,6 +104,7 @@ public:
setFlag(fIsClass, class_);
setFlag(fIsArray, array_);
setFlag(fIsPointer, pointer_);
setFlag(fIsReference, reference_);
setFlag(fHasDefault, default_);
_dimensions = dimensions_;
}
@ -270,13 +272,21 @@ public:
}
/**
* Is pointer or array variable.
* Is pointer variable.
* @return true if pointer, false otherwise
*/
bool isPointer() const {
return getFlag(fIsPointer);
}
/**
* Is reference variable.
* @return true if reference, false otherwise
*/
bool isReference() const {
return getFlag(fIsReference);
}
/**
* Does variable have a default value.
* @return true if has a default falue, false if not
@ -469,11 +479,11 @@ 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_, bool pointer_,
const Scope *scope_, bool array_, bool pointer_, bool reference_,
const std::vector<Dimension> &dimensions_) {
varlist.push_back(Variable(token_, start_, end_, varlist.size(),
access_, mutable_, static_, const_, class_,
type_, scope_, array_, pointer_, false, dimensions_));
type_, scope_, array_, pointer_, reference_, false, dimensions_));
}
/** @brief initialize varlist */
@ -518,7 +528,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) const;
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const;
bool isSimpleVariable(const Token* tok) const;
bool isArrayVariable(const Token* tok) const;
bool findClosingBracket(const Token* tok, const Token*& close) const;

View File

@ -39,6 +39,7 @@ public:
,found(false)
,isArray(false)
,isPointer(false)
,isReference(false)
{}
virtual void reportOut(const std::string &outmsg) {
@ -53,6 +54,7 @@ private:
bool found;
bool isArray;
bool isPointer;
bool isReference;
void reset() {
vartok = NULL;
@ -61,6 +63,7 @@ private:
found = false;
isArray = false;
isPointer = false;
isReference = false;
}
void run() {
@ -84,6 +87,7 @@ private:
TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariable);
TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariableIterator);
TEST_CASE(isVariableDeclarationIdentifiesNestedTemplateVariable);
TEST_CASE(isVariableDeclarationIdentifiesReference);
TEST_CASE(isVariableDeclarationDoesNotIdentifyTemplateClass);
TEST_CASE(canFindMatchingBracketsNeedsOpen);
TEST_CASE(canFindMatchingBracketsInnerPair);
@ -143,230 +147,277 @@ private:
void test_isVariableDeclarationCanHandleNull() {
reset();
bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(false, result);
ASSERT(NULL == vartok);
ASSERT(NULL == typetok);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesSimpleDeclaration() {
reset();
givenACodeSampleToTokenize simpleDeclaration("int x;");
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesScopedDeclaration() {
reset();
givenACodeSampleToTokenize ScopedDeclaration("::int x;");
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesStdDeclaration() {
reset();
givenACodeSampleToTokenize StdDeclaration("std::string x;");
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesScopedStdDeclaration() {
reset();
givenACodeSampleToTokenize StdDeclaration("::std::string x;");
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesManyScopes() {
reset();
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;");
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("x", vartok->str());
ASSERT_EQUALS("EE", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesPointers() {
reset();
givenACodeSampleToTokenize pointer("int* p;");
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationDoesNotIdentifyConstness() {
reset();
givenACodeSampleToTokenize constness("const int* cp;");
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray, isPointer, isReference);
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);
bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("first", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() {
reset();
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;");
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("EE", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() {
reset();
givenACodeSampleToTokenize pointerToPointer("int** pp;");
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("pp", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() {
reset();
givenACodeSampleToTokenize pointerToPointer("int***** p;");
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("p", vartok->str());
ASSERT_EQUALS("int", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesArray() {
reset();
givenACodeSampleToTokenize array("::std::string v[3];");
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("v", vartok->str());
ASSERT_EQUALS("string", typetok->str());
ASSERT(true == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void test_isVariableDeclarationIdentifiesOfArrayPointers() {
reset();
givenACodeSampleToTokenize array("A *a[5];");
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("a", vartok->str());
ASSERT_EQUALS("A", typetok->str());
ASSERT(true == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesTemplatedPointerVariable() {
reset();
givenACodeSampleToTokenize var("std::set<char>* chars;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("chars", vartok->str());
ASSERT_EQUALS("set", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<int>*** ints;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(false == isArray);
ASSERT(true == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesTemplatedArrayVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<int> ints[3];");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(true == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesTemplatedVariable() {
reset();
givenACodeSampleToTokenize var("std::vector<int> ints;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("ints", vartok->str());
ASSERT_EQUALS("vector", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesTemplatedVariableIterator() {
reset();
givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("floats", vartok->str());
ASSERT_EQUALS("const_iterator", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesNestedTemplateVariable() {
reset();
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result);
ASSERT_EQUALS("intsets", vartok->str());
ASSERT_EQUALS("deque", typetok->str());
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void isVariableDeclarationIdentifiesReference() {
reset();
givenACodeSampleToTokenize var1("int& foo;");
bool result1 = si.isVariableDeclaration(var1.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result1);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
reset();
givenACodeSampleToTokenize var2("foo*& bar;");
bool result2 = si.isVariableDeclaration(var2.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result2);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
reset();
givenACodeSampleToTokenize var3("std::vector<int>& foo;");
bool result3 = si.isVariableDeclaration(var3.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(true, result3);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(true == isReference);
}
void isVariableDeclarationDoesNotIdentifyTemplateClass() {
reset();
givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer, isReference);
ASSERT_EQUALS(false, result);
ASSERT(false == isArray);
ASSERT(false == isPointer);
ASSERT(false == isReference);
}
void canFindMatchingBracketsNeedsOpen() {