Improved support for references and pointers in SymbolDatabase
Replaced several isPointer functions by Variable::isPointer function Refactorizations & Make use of symbolDatabase more often
This commit is contained in:
parent
f09a5b408b
commit
f306246c7f
|
@ -422,25 +422,11 @@ static bool for_bailout(const Token * const tok1, unsigned int varid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arrayInfo, const std::string &strindex, bool condition_out_of_bounds, unsigned int counter_varid, const std::string &min_counter_value, const std::string &max_counter_value)
|
void CheckBufferOverrun::parse_for_body(const Token *tok, const ArrayInfo &arrayInfo, const std::string &strindex, bool condition_out_of_bounds, unsigned int counter_varid, const std::string &min_counter_value, const std::string &max_counter_value)
|
||||||
{
|
{
|
||||||
const std::string pattern((arrayInfo.varid() ? std::string("%varid%") : arrayInfo.varname()) + " [ " + strindex + " ]");
|
const std::string pattern((arrayInfo.varid() ? std::string("%varid%") : arrayInfo.varname()) + " [ " + strindex + " ]");
|
||||||
|
|
||||||
// count { and } for tok2
|
for (const Token* tok2 = tok; tok2 && tok2 != tok->link(); tok2 = tok2->next()) {
|
||||||
int indentlevel2 = 0;
|
|
||||||
for (; tok2; tok2 = tok2->next()) {
|
|
||||||
if (tok2->str() == ";" && indentlevel2 == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (tok2->str() == "{")
|
|
||||||
++indentlevel2;
|
|
||||||
|
|
||||||
if (tok2->str() == "}") {
|
|
||||||
--indentlevel2;
|
|
||||||
if (indentlevel2 <= 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: try to reduce false negatives. This is just a quick fix
|
// TODO: try to reduce false negatives. This is just a quick fix
|
||||||
// for TestBufferOverrun::array_index_for_question
|
// for TestBufferOverrun::array_index_for_question
|
||||||
if (tok2->str() == "?")
|
if (tok2->str() == "?")
|
||||||
|
@ -713,31 +699,22 @@ void CheckBufferOverrun::checkFunctionCall(const Token *tok, const ArrayInfo &ar
|
||||||
}
|
}
|
||||||
callstack.push_back(tok);
|
callstack.push_back(tok);
|
||||||
|
|
||||||
|
const Token *tok2 = tok->tokAt(2);
|
||||||
// 1st parameter..
|
// 1st parameter..
|
||||||
if (Token::Match(tok->tokAt(2), "%varid% ,|)", arrayInfo.varid()))
|
if (Token::Match(tok2, "%varid% ,|)", arrayInfo.varid()))
|
||||||
checkFunctionParameter(*tok, 1, arrayInfo, callstack);
|
checkFunctionParameter(*tok, 1, arrayInfo, callstack);
|
||||||
else if (Token::Match(tok->tokAt(2), "%varid% + %num% ,|)", arrayInfo.varid())) {
|
else if (Token::Match(tok2, "%varid% + %num% ,|)", arrayInfo.varid())) {
|
||||||
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok->strAt(4))));
|
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok2->strAt(2))));
|
||||||
checkFunctionParameter(*tok, 1, ai, callstack);
|
checkFunctionParameter(*tok, 1, ai, callstack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// goto 2nd parameter and check it..
|
// goto 2nd parameter and check it..
|
||||||
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) {
|
tok2 = tok2->nextArgument();
|
||||||
if (tok2->str() == "(") {
|
if (Token::Match(tok2, "%varid% ,|)", arrayInfo.varid()))
|
||||||
tok2 = tok2->link();
|
checkFunctionParameter(*tok, 2, arrayInfo, callstack);
|
||||||
continue;
|
else if (Token::Match(tok2, "%varid% + %num% ,|)", arrayInfo.varid())) {
|
||||||
}
|
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok2->strAt(2))));
|
||||||
if (tok2->str() == ";" || tok2->str() == ")")
|
checkFunctionParameter(*tok, 2, ai, callstack);
|
||||||
break;
|
|
||||||
if (tok2->str() == ",") {
|
|
||||||
if (Token::Match(tok2, ", %varid% ,|)", arrayInfo.varid()))
|
|
||||||
checkFunctionParameter(*tok, 2, arrayInfo, callstack);
|
|
||||||
else if (Token::Match(tok2, ", %varid% + %num% ,|)", arrayInfo.varid())) {
|
|
||||||
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok2->strAt(3))));
|
|
||||||
checkFunctionParameter(*tok, 2, ai, callstack);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,7 +989,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
// undefined behaviour: result of pointer arithmetic is out of bounds
|
// undefined behaviour: result of pointer arithmetic is out of bounds
|
||||||
if (varid && Token::Match(tok, "= %varid% + %num% ;", varid)) {
|
else if (varid && Token::Match(tok, "= %varid% + %num% ;", varid)) {
|
||||||
const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(3));
|
const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(3));
|
||||||
if (index > size && _settings->isEnabled("portability"))
|
if (index > size && _settings->isEnabled("portability"))
|
||||||
pointerOutOfBoundsError(tok->next(), "buffer");
|
pointerOutOfBoundsError(tok->next(), "buffer");
|
||||||
|
@ -1020,7 +997,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
||||||
pointerIsOutOfBounds = true;
|
pointerIsOutOfBounds = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointerIsOutOfBounds && Token::Match(tok, "[;{}=] * %varid% [;=]", varid)) {
|
else if (pointerIsOutOfBounds && Token::Match(tok, "[;{}=] * %varid% [;=]", varid)) {
|
||||||
outOfBoundsError(tok->tokAt(2), tok->strAt(2), false, 0, 0);
|
outOfBoundsError(tok->tokAt(2), tok->strAt(2), false, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,31 +288,6 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckNullPointer::isPointer(const unsigned int varid)
|
|
||||||
{
|
|
||||||
// Check if given variable is a pointer
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
const Variable *variableInfo = symbolDatabase->getVariableFromVarId(varid);
|
|
||||||
const Token *tok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
|
||||||
|
|
||||||
if (Token::Match(tok, "%type% %type% * %varid% [;)=]", varid))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// maybe not a pointer
|
|
||||||
if (!Token::Match(tok, "%type% * %varid% [;)=]", varid))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// it is a pointer
|
|
||||||
if (!tok->previous() ||
|
|
||||||
Token::Match(tok->previous(), "[({};]") ||
|
|
||||||
tok->previous()->isName()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is not a pointer
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckNullPointer::nullPointerAfterLoop()
|
void CheckNullPointer::nullPointerAfterLoop()
|
||||||
{
|
{
|
||||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
@ -327,12 +302,10 @@ void CheckNullPointer::nullPointerAfterLoop()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get variable id for the loop variable
|
// Get variable id for the loop variable
|
||||||
const unsigned int varid(tok->tokAt(2)->varId());
|
const Variable* var(symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()));
|
||||||
if (varid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Is variable a pointer?
|
// Is variable a pointer?
|
||||||
if (!isPointer(varid))
|
if (!var || !var->isPointer())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get variable name for the loop variable
|
// Get variable name for the loop variable
|
||||||
|
@ -371,7 +344,7 @@ void CheckNullPointer::nullPointerAfterLoop()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// loop variable is found..
|
// loop variable is found..
|
||||||
else if (tok2->varId() == varid) {
|
else if (tok2->varId() == var->varId()) {
|
||||||
// dummy variable.. is it unknown if pointer is dereferenced or not?
|
// dummy variable.. is it unknown if pointer is dereferenced or not?
|
||||||
bool unknown = _settings->inconclusive;
|
bool unknown = _settings->inconclusive;
|
||||||
|
|
||||||
|
@ -445,8 +418,9 @@ void CheckNullPointer::nullPointerLinkedList()
|
||||||
++indentlevel4;
|
++indentlevel4;
|
||||||
else if (tok4->str() == "}") {
|
else if (tok4->str() == "}") {
|
||||||
if (indentlevel4 <= 1) {
|
if (indentlevel4 <= 1) {
|
||||||
|
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
// Is this variable a pointer?
|
// Is this variable a pointer?
|
||||||
if (isPointer(varid))
|
if (var && var->isPointer())
|
||||||
nullPointerError(tok1, varname, tok3->linenr());
|
nullPointerError(tok1, varname, tok3->linenr());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -580,7 +554,9 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
||||||
// is pointer local?
|
// is pointer local?
|
||||||
bool isLocal = false;
|
bool isLocal = false;
|
||||||
const Variable * var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok1->varId());
|
const Variable * var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok1->varId());
|
||||||
if (var && (var->isLocal() || var->isArgument()))
|
if (!var)
|
||||||
|
continue;
|
||||||
|
if (var->isLocal() || var->isArgument())
|
||||||
isLocal = true;
|
isLocal = true;
|
||||||
|
|
||||||
// member function may or may not nullify the pointer if it's global (#2647)
|
// member function may or may not nullify the pointer if it's global (#2647)
|
||||||
|
@ -641,7 +617,7 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
||||||
// TODO: false negatives for "if (!p || .."
|
// TODO: false negatives for "if (!p || .."
|
||||||
else if (Token::Match(tok2, "if ( !| %varid% )|&&", varid1)) {
|
else if (Token::Match(tok2, "if ( !| %varid% )|&&", varid1)) {
|
||||||
// Is this variable a pointer?
|
// Is this variable a pointer?
|
||||||
if (isPointer(varid1))
|
if (var->isPointer())
|
||||||
nullPointerError(tok1, varname, tok2->linenr(), inconclusive);
|
nullPointerError(tok1, varname, tok2->linenr(), inconclusive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -674,13 +650,9 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
// Name of pointer
|
// Name of pointer
|
||||||
const std::string varname(vartok->str());
|
const std::string varname(vartok->str());
|
||||||
|
|
||||||
|
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
// Check that variable is a pointer..
|
// Check that variable is a pointer..
|
||||||
if (!isPointer(varid))
|
if (!var || !var->isPointer())
|
||||||
continue;
|
|
||||||
|
|
||||||
// Token where pointer is declared
|
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
|
||||||
if (!var)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token * const decltok = var->nameToken();
|
const Token * const decltok = var->nameToken();
|
||||||
|
@ -785,15 +757,8 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
{
|
{
|
||||||
// Check if pointer is NULL and then dereference it..
|
// Check if pointer is NULL and then dereference it..
|
||||||
|
|
||||||
// used to check if a variable is a pointer.
|
|
||||||
// TODO: Use isPointer?
|
|
||||||
std::set<unsigned int> pointerVariables;
|
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "* %var% [;,)=]"))
|
if (Token::simpleMatch(tok, "if (")) {
|
||||||
pointerVariables.insert(tok->next()->varId());
|
|
||||||
|
|
||||||
else if (Token::simpleMatch(tok, "if (")) {
|
|
||||||
// TODO: investigate false negatives:
|
// TODO: investigate false negatives:
|
||||||
// - handle "while"?
|
// - handle "while"?
|
||||||
// - if there are logical operators
|
// - if there are logical operators
|
||||||
|
@ -828,8 +793,9 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
|
|
||||||
const unsigned int linenr = vartok->linenr();
|
const unsigned int linenr = vartok->linenr();
|
||||||
|
|
||||||
// Check if variable is a pointer. TODO: Use isPointer?
|
const Variable* var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||||
if (pointerVariables.find(varid) == pointerVariables.end())
|
// Check if variable is a pointer
|
||||||
|
if (!var || !var->isPointer())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Token::Match(vartok->next(), "&& ( %varid% =", varid))
|
if (Token::Match(vartok->next(), "&& ( %varid% =", varid))
|
||||||
|
@ -906,9 +872,9 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
|
|
||||||
// function call, check if pointer is dereferenced
|
// function call, check if pointer is dereferenced
|
||||||
if (Token::Match(tok2, "%var% (")) {
|
if (Token::Match(tok2, "%var% (")) {
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> vars;
|
||||||
parseFunctionCall(*tok2, var, 0);
|
parseFunctionCall(*tok2, vars, 0);
|
||||||
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) {
|
for (std::list<const Token *>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
|
||||||
if (Token::Match(*it, "%varid% [,)]", varid)) {
|
if (Token::Match(*it, "%varid% [,)]", varid)) {
|
||||||
nullPointerError(*it, pointerName, linenr, inconclusive);
|
nullPointerError(*it, pointerName, linenr, inconclusive);
|
||||||
break;
|
break;
|
||||||
|
@ -932,8 +898,6 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
// init function (global variables)
|
// init function (global variables)
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
|
||||||
if (!var || !(var->isLocal() || var->isArgument()))
|
if (!var || !(var->isLocal() || var->isArgument()))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,12 +120,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a variable is a pointer
|
|
||||||
* @param varid variable id for variable
|
|
||||||
*/
|
|
||||||
bool isPointer(const unsigned int varid);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Does one part of the check for nullPointer().
|
* @brief Does one part of the check for nullPointer().
|
||||||
* Locate insufficient null-pointer handling after loop
|
* Locate insufficient null-pointer handling after loop
|
||||||
|
|
|
@ -750,24 +750,25 @@ void CheckOther::coutCerrMisusageError(const Token* tok, const std::string& stre
|
||||||
//
|
//
|
||||||
// int y = y; // <- redundant initialization to self
|
// int y = y; // <- redundant initialization to self
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
static bool isPOD(const Variable* var)
|
||||||
|
{
|
||||||
|
// TODO: Implement real support for POD definition
|
||||||
|
return(var && var->nameToken()->previous()->isStandardType());
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::checkSelfAssignment()
|
void CheckOther::checkSelfAssignment()
|
||||||
{
|
{
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// POD variables..
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
std::set<unsigned int> pod;
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
if (tok->isStandardType() && Token::Match(tok->tokAt(2), "[,);]") && tok->next()->varId())
|
|
||||||
pod.insert(tok->next()->varId());
|
|
||||||
}
|
|
||||||
|
|
||||||
const char selfAssignmentPattern[] = "%var% = %var% ;|=|)";
|
const char selfAssignmentPattern[] = "%var% = %var% ;|=|)";
|
||||||
const Token *tok = Token::findmatch(_tokenizer->tokens(), selfAssignmentPattern);
|
const Token *tok = Token::findmatch(_tokenizer->tokens(), selfAssignmentPattern);
|
||||||
while (tok) {
|
while (tok) {
|
||||||
if (Token::Match(tok->previous(), "[;{}]") &&
|
if (Token::Match(tok->previous(), "[;{}]") &&
|
||||||
tok->varId() && tok->varId() == tok->tokAt(2)->varId() &&
|
tok->varId() && tok->varId() == tok->tokAt(2)->varId() &&
|
||||||
pod.find(tok->varId()) != pod.end()) {
|
isPOD(symbolDatabase->getVariableFromVarId(tok->varId()))) {
|
||||||
bool err = true;
|
bool err = true;
|
||||||
|
|
||||||
// no false positive for 'x = x ? x : 1;'
|
// no false positive for 'x = x ? x : 1;'
|
||||||
|
@ -1512,29 +1513,26 @@ void CheckOther::unreachableCodeError(const Token *tok)
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Check for unsigned divisions
|
// Check for unsigned divisions
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
static bool isUnsigned(const Variable* var)
|
||||||
|
{
|
||||||
|
return(var && var->typeStartToken()->isUnsigned() && var->typeStartToken() == var->typeEndToken());
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::checkUnsignedDivision()
|
void CheckOther::checkUnsignedDivision()
|
||||||
{
|
{
|
||||||
// Check for "ivar / uvar" and "uvar / ivar"
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
std::set<unsigned int> uvars;
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
if (Token::Match(tok, "[{};(,] %type% %var% [;=,)]")) {
|
|
||||||
if (tok->next()->isUnsigned())
|
|
||||||
uvars.insert(tok->tokAt(2)->varId());
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!Token::Match(tok, "[).]") && Token::Match(tok->next(), "%var% / %num%")) {
|
// Check for "ivar / uvar" and "uvar / ivar"
|
||||||
if (tok->strAt(3)[0] == '-') {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (uvars.find(tok->next()->varId()) != uvars.end()) {
|
if (!Token::Match(tok, "[).]") && Token::Match(tok->next(), "%var% / %num%")) {
|
||||||
udivError(tok->next());
|
if (tok->strAt(3)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->next()->varId()))) {
|
||||||
}
|
udivError(tok->next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "(|[|=|%op% %num% / %var%")) {
|
else if (Token::Match(tok, "(|[|=|%op% %num% / %var%")) {
|
||||||
if (tok->strAt(1)[0] == '-') {
|
if (tok->strAt(1)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()))) {
|
||||||
if (uvars.find(tok->tokAt(3)->varId()) != uvars.end()) {
|
udivError(tok->next());
|
||||||
udivError(tok->next());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1805,6 +1803,11 @@ void CheckOther::passedByValueError(const Token *tok, const std::string &parname
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Check usage of char variables..
|
// Check usage of char variables..
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
static bool isSignedChar(const Variable* var)
|
||||||
|
{
|
||||||
|
return(var && var->nameToken()->previous()->str() == "char" && !var->nameToken()->previous()->isUnsigned() && var->nameToken()->next()->str() != "[");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::checkCharVariable()
|
void CheckOther::checkCharVariable()
|
||||||
{
|
{
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
|
@ -1813,87 +1816,50 @@ void CheckOther::checkCharVariable()
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
// Declaring the variable..
|
if ((tok->str() != ".") && Token::Match(tok->next(), "%var% [ %var% ]")) {
|
||||||
if (Token::Match(tok, "[{};(,] const| char *| const| %var% [;=,)]") ||
|
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId());
|
||||||
Token::Match(tok, "[{};(,] const| char %var% [")) {
|
if (isSignedChar(var))
|
||||||
// goto 'char' token
|
charArrayIndexError(tok->next());
|
||||||
tok = tok->next();
|
}
|
||||||
if (tok->str() == "const")
|
|
||||||
tok = tok->next();
|
|
||||||
|
|
||||||
// Check for unsigned char
|
else if (Token::Match(tok, "[;{}] %var% = %any% [&|] %any% ;")) {
|
||||||
if (tok->isUnsigned())
|
// is a char variable used in the calculation?
|
||||||
|
if (!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())) &&
|
||||||
|
!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId())))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Set tok to point to the variable name
|
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||||
tok = tok->next();
|
if (tok->strAt(4) == "&") {
|
||||||
const bool isPointer(tok->str() == "*" || tok->strAt(1) == "[");
|
if (tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||||
if (tok->str() == "*")
|
continue;
|
||||||
tok = tok->next();
|
if (tok->tokAt(5)->isNumber() && MathLib::isGreater("0x100", tok->strAt(5)))
|
||||||
if (tok->str() == "const")
|
continue;
|
||||||
tok = tok->next();
|
|
||||||
|
|
||||||
const unsigned int varid = tok->varId();
|
|
||||||
if (!varid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check usage of char variable..
|
|
||||||
unsigned int indentlevel = 0;
|
|
||||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
|
||||||
if (tok2->str() == "{")
|
|
||||||
++indentlevel;
|
|
||||||
|
|
||||||
else if (tok2->str() == "}") {
|
|
||||||
if (!indentlevel)
|
|
||||||
break;
|
|
||||||
--indentlevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPointer) {
|
|
||||||
if ((tok2->str() != ".") && Token::Match(tok2->next(), "%var% [ %varid% ]", varid)) {
|
|
||||||
charArrayIndexError(tok2->next());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "[;{}] %var% = %any% [&|] %any% ;")) {
|
|
||||||
// is the char variable used in the calculation?
|
|
||||||
if (tok2->tokAt(3)->varId() != tok->varId() && tok2->tokAt(5)->varId() != tok->varId())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
|
||||||
if (tok2->strAt(4) == "&") {
|
|
||||||
if (tok2->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(3)))
|
|
||||||
continue;
|
|
||||||
if (tok2->tokAt(5)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(5)))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is the result stored in a short|int|long?
|
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok2->next()->varId());
|
|
||||||
if (!(var && Token::Match(var->typeEndToken(), "short|int|long")))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This is an error..
|
|
||||||
charBitOpError(tok2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPointer && Token::Match(tok2, "[;{}] %var% = %any% [&|] ( * %varid% ) ;", tok->varId())) {
|
|
||||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
|
||||||
if (tok2->strAt(4) == "&" && tok2->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(3)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// is the result stored in a short|int|long?
|
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok2->next()->varId());
|
|
||||||
if (!(var && Token::Match(var->typeEndToken(), "short|int|long")))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This is an error..
|
|
||||||
charBitOpError(tok2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is the result stored in a short|int|long?
|
||||||
|
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (!(var && Token::Match(var->typeEndToken(), "short|int|long")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This is an error..
|
||||||
|
charBitOpError(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (Token::Match(tok, "[;{}] %var% = %any% [&|] ( * %var% ) ;")) {
|
||||||
|
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId());
|
||||||
|
if (!var || !var->isPointer())
|
||||||
|
continue;
|
||||||
|
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||||
|
if (tok->strAt(4) == "&" && tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// is the result stored in a short|int|long?
|
||||||
|
var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (!(var && Token::Match(var->typeEndToken(), "short|int|long")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This is an error..
|
||||||
|
charBitOpError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1973,6 +1939,11 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type)
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// str plus char
|
// str plus char
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
static bool isChar(const Variable* var)
|
||||||
|
{
|
||||||
|
return(var && var->nameToken()->previous()->str() == "char" && var->nameToken()->next()->str() != "[");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::strPlusChar()
|
void CheckOther::strPlusChar()
|
||||||
{
|
{
|
||||||
// Don't use this check for Java and C# programs..
|
// Don't use this check for Java and C# programs..
|
||||||
|
@ -1980,25 +1951,17 @@ void CheckOther::strPlusChar()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<unsigned int> charVars;
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
// Declaring char variable..
|
if (Token::Match(tok, "[=(] %str% + %any%")) {
|
||||||
if (Token::Match(tok, "char %var% [;=]")) {
|
|
||||||
unsigned int varid = tok->next()->varId();
|
|
||||||
if (varid > 0)
|
|
||||||
charVars.insert(varid);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
else if (Token::Match(tok, "[=(] %str% + %any%")) {
|
|
||||||
// char constant..
|
// char constant..
|
||||||
if (tok->strAt(3)[0] == '\'')
|
if (tok->strAt(3)[0] == '\'')
|
||||||
strPlusCharError(tok->next());
|
strPlusCharError(tok->next());
|
||||||
|
|
||||||
// char variable..
|
// char variable..
|
||||||
unsigned int varid = tok->tokAt(3)->varId();
|
unsigned int varid = tok->tokAt(3)->varId();
|
||||||
if (varid > 0 && charVars.find(varid) != charVars.end())
|
if (isChar(symbolDatabase->getVariableFromVarId(varid)))
|
||||||
strPlusCharError(tok->next());
|
strPlusCharError(tok->next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2102,7 +2065,7 @@ void CheckOther::checkCCTypeFunctions()
|
||||||
{
|
{
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->varId() == 0 &&
|
if (tok->varId() == 0 &&
|
||||||
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% )") &&
|
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% )") &&
|
||||||
MathLib::isNegative(tok->strAt(2))) {
|
MathLib::isNegative(tok->strAt(2))) {
|
||||||
cctypefunctionCallError(tok, tok->str(), tok->tokAt(2)->str());
|
cctypefunctionCallError(tok, tok->str(), tok->tokAt(2)->str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -997,12 +997,6 @@ void CheckStl::missingComparisonError(const Token *incrementToken1, const Token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isPointer(const SymbolDatabase* symbolDatabase, unsigned int varid)
|
|
||||||
{
|
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
|
||||||
return var && var->nameToken()->previous()->str() == "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isLocal(const SymbolDatabase* symbolDatabase, unsigned int varid)
|
static bool isLocal(const SymbolDatabase* symbolDatabase, unsigned int varid)
|
||||||
{
|
{
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
|
@ -1023,13 +1017,16 @@ void CheckStl::string_c_str()
|
||||||
// Invalid usage..
|
// Invalid usage..
|
||||||
if (Token::Match(tok, "throw %var% . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) {
|
if (Token::Match(tok, "throw %var% . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) {
|
||||||
string_c_strThrowError(tok);
|
string_c_strThrowError(tok);
|
||||||
} else if (Token::Match(tok, "[;{}] %var% = %var% . str ( ) . c_str ( ) ;") && isPointer(symbolDatabase, tok->next()->varId())) {
|
} else if (Token::Match(tok, "[;{}] %var% = %var% . str ( ) . c_str ( ) ;")) {
|
||||||
string_c_strError(tok);
|
const Variable* var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (var && var->isPointer())
|
||||||
|
string_c_strError(tok);
|
||||||
} else if (Token::Match(tok, "[;{}] %var% = %var% (") &&
|
} else if (Token::Match(tok, "[;{}] %var% = %var% (") &&
|
||||||
Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;") &&
|
Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;") &&
|
||||||
isPointer(symbolDatabase, tok->next()->varId()) &&
|
|
||||||
Token::findmatch(_tokenizer->tokens(), ("std :: string " + tok->strAt(3) + " (").c_str())) {
|
Token::findmatch(_tokenizer->tokens(), ("std :: string " + tok->strAt(3) + " (").c_str())) {
|
||||||
string_c_strError(tok);
|
const Variable* var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (var && var->isPointer())
|
||||||
|
string_c_strError(tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using c_str() to get the return value is only dangerous if the function returns a char*
|
// Using c_str() to get the return value is only dangerous if the function returns a char*
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -111,19 +109,26 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
|
|
||||||
// unnamed struct and union
|
// unnamed struct and union
|
||||||
else if (Token::Match(tok, "struct|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));
|
scopeList.push_back(Scope(this, tok, scope));
|
||||||
|
|
||||||
Scope *new_scope = &scopeList.back();
|
Scope *new_scope = &scopeList.back();
|
||||||
|
|
||||||
std::vector<Dimension> dimensions;
|
std::vector<Dimension> dimensions;
|
||||||
|
|
||||||
|
bool isPointer = false;
|
||||||
bool isArray = false;
|
bool isArray = false;
|
||||||
|
|
||||||
if (tok->next()->link()->strAt(2) == "[")
|
const Token* varNameTok = tok->next()->link()->next();
|
||||||
isArray = arrayDimensions(dimensions, tok->next()->link()->tokAt(2));
|
if (varNameTok->str() == "*") {
|
||||||
|
isPointer = true;
|
||||||
|
varNameTok = varNameTok->next();
|
||||||
|
}
|
||||||
|
|
||||||
scope->addVariable(tok->next()->link()->next(), tok, tok, scope->access, false, false, false, true, new_scope, scope, isArray, dimensions);
|
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);
|
||||||
|
|
||||||
const Token *tok2 = tok->next();
|
const Token *tok2 = tok->next();
|
||||||
|
|
||||||
|
@ -1210,20 +1215,14 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
|
||||||
// check for non-empty argument list "( ... )"
|
// check for non-empty argument list "( ... )"
|
||||||
if (arg->link() != arg->next() && !Token::simpleMatch(arg, "( void )")) {
|
if (arg->link() != arg->next() && !Token::simpleMatch(arg, "( void )")) {
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
const Token *startTok;
|
|
||||||
const Token *endTok;
|
for (const Token* tok = arg->next(); tok; tok = tok->next()) {
|
||||||
const Token *nameTok;
|
const Token* startTok = tok;
|
||||||
bool isConstVar;
|
const Token* endTok = NULL;
|
||||||
bool isArrayVar;
|
const Token* nameTok = NULL;
|
||||||
bool hasDefault;
|
bool isConstVar = bool(tok->str() == "const");
|
||||||
const Token *tok = arg->next();
|
bool isArrayVar = false;
|
||||||
for (;;) {
|
bool hasDefault = false;
|
||||||
startTok = tok;
|
|
||||||
endTok = NULL;
|
|
||||||
nameTok = NULL;
|
|
||||||
isConstVar = bool(tok->str() == "const");
|
|
||||||
isArrayVar = false;
|
|
||||||
hasDefault = false;
|
|
||||||
std::vector<Dimension> dimensions;
|
std::vector<Dimension> dimensions;
|
||||||
|
|
||||||
while (tok->str() != "," && tok->str() != ")" && tok->str() != "=") {
|
while (tok->str() != "," && tok->str() != ")" && tok->str() != "=") {
|
||||||
|
@ -1282,6 +1281,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
|
||||||
argType = symbolDatabase->findVariableType(scope, typeTok);
|
argType = symbolDatabase->findVariableType(scope, typeTok);
|
||||||
|
|
||||||
bool isClassVar = startTok == endTok && !startTok->isStandardType();
|
bool isClassVar = startTok == endTok && !startTok->isStandardType();
|
||||||
|
bool isPointerVar = nameTok->strAt(-1) == "*" || nameTok->strAt(-2) == "*";
|
||||||
|
|
||||||
// skip default values
|
// skip default values
|
||||||
if (tok->str() == "=") {
|
if (tok->str() == "=") {
|
||||||
|
@ -1291,12 +1291,10 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, hasDefault, dimensions));
|
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, functionScope, isArrayVar, isPointerVar, hasDefault, dimensions));
|
||||||
|
|
||||||
if (tok->str() == ")")
|
if (tok->str() == ")")
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tok = tok->next();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,8 +1357,7 @@ Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool Scope::hasDefaultConstructor() const
|
||||||
Scope::hasDefaultConstructor() const
|
|
||||||
{
|
{
|
||||||
if (numConstructors) {
|
if (numConstructors) {
|
||||||
std::list<Function>::const_iterator func;
|
std::list<Function>::const_iterator func;
|
||||||
|
@ -1548,10 +1545,12 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isArray = false;
|
bool isArray = false;
|
||||||
|
bool isPointer = false;
|
||||||
std::vector<Dimension> dimensions;
|
std::vector<Dimension> dimensions;
|
||||||
|
|
||||||
if (tok && isVariableDeclaration(tok, vartok, typetok, isArray)) {
|
if (tok && isVariableDeclaration(tok, vartok, typetok, isArray, isPointer)) {
|
||||||
isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*");
|
isPointer = vartok->previous()->str() == "*" || vartok->strAt(-2) == "*";
|
||||||
|
isClass = (!typetok->isStandardType() && !isPointer && vartok->previous()->str() != "&");
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
isArray = check->arrayDimensions(dimensions, vartok->next());
|
isArray = check->arrayDimensions(dimensions, vartok->next());
|
||||||
tok = vartok->next();
|
tok = vartok->next();
|
||||||
|
@ -1571,7 +1570,7 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
|
||||||
if (typetok)
|
if (typetok)
|
||||||
scope = check->findVariableType(this, typetok);
|
scope = check->findVariableType(this, typetok);
|
||||||
|
|
||||||
addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray, dimensions);
|
addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray, isPointer, dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tok;
|
return tok;
|
||||||
|
@ -1607,14 +1606,14 @@ inline const Token* skipPointers(const Token* tok)
|
||||||
{
|
{
|
||||||
const Token* ret = tok;
|
const Token* ret = tok;
|
||||||
|
|
||||||
while (Token::simpleMatch(ret, "*")) {
|
while (Token::Match(ret, "*|&")) {
|
||||||
ret = ret->next();
|
ret = ret->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const
|
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer) const
|
||||||
{
|
{
|
||||||
const Token* localTypeTok = skipScopeIdentifiers(tok);
|
const Token* localTypeTok = skipScopeIdentifiers(tok);
|
||||||
const Token* localVarTok = NULL;
|
const Token* localVarTok = NULL;
|
||||||
|
@ -1649,6 +1648,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
typetok = localTypeTok;
|
typetok = localTypeTok;
|
||||||
isArray = false;
|
isArray = false;
|
||||||
}
|
}
|
||||||
|
isPointer = vartok && (vartok->strAt(-1) == "*" || vartok->strAt(-2) == "*");
|
||||||
|
|
||||||
return NULL != vartok;
|
return NULL != vartok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,8 @@ class Variable {
|
||||||
fIsConst = (1 << 2), /** @brief const variable */
|
fIsConst = (1 << 2), /** @brief const variable */
|
||||||
fIsClass = (1 << 3), /** @brief user defined type */
|
fIsClass = (1 << 3), /** @brief user defined type */
|
||||||
fIsArray = (1 << 4), /** @brief array variable */
|
fIsArray = (1 << 4), /** @brief array variable */
|
||||||
fHasDefault = (1 << 5) /** @brief function argument with default value */
|
fIsPointer = (1 << 5), /** @brief pointer variable */
|
||||||
|
fHasDefault = (1 << 6) /** @brief function argument with default value */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +87,7 @@ public:
|
||||||
Variable(const Token *name_, const Token *start_, const Token *end_,
|
Variable(const Token *name_, const Token *start_, const Token *end_,
|
||||||
std::size_t index_, AccessControl access_, bool mutable_,
|
std::size_t index_, AccessControl access_, bool mutable_,
|
||||||
bool static_, bool const_, bool class_, const Scope *type_,
|
bool static_, bool const_, bool class_, const Scope *type_,
|
||||||
const Scope *scope_, bool array_, bool default_,
|
const Scope *scope_, bool array_, bool pointer_, bool default_,
|
||||||
const std::vector<Dimension> &dimensions_)
|
const std::vector<Dimension> &dimensions_)
|
||||||
: _name(name_),
|
: _name(name_),
|
||||||
_start(start_),
|
_start(start_),
|
||||||
|
@ -101,6 +102,7 @@ public:
|
||||||
setFlag(fIsConst, const_);
|
setFlag(fIsConst, const_);
|
||||||
setFlag(fIsClass, class_);
|
setFlag(fIsClass, class_);
|
||||||
setFlag(fIsArray, array_);
|
setFlag(fIsArray, array_);
|
||||||
|
setFlag(fIsPointer, pointer_);
|
||||||
setFlag(fHasDefault, default_);
|
setFlag(fHasDefault, default_);
|
||||||
_dimensions = dimensions_;
|
_dimensions = dimensions_;
|
||||||
}
|
}
|
||||||
|
@ -259,6 +261,14 @@ public:
|
||||||
return getFlag(fIsArray);
|
return getFlag(fIsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is pointer or array variable.
|
||||||
|
* @return true if pointer, false otherwise
|
||||||
|
*/
|
||||||
|
bool isPointer() const {
|
||||||
|
return getFlag(fIsPointer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does variable have a default value.
|
* Does variable have a default value.
|
||||||
* @return true if has a default falue, false if not
|
* @return true if has a default falue, false if not
|
||||||
|
@ -451,11 +461,11 @@ public:
|
||||||
void addVariable(const Token *token_, const Token *start_,
|
void addVariable(const Token *token_, const Token *start_,
|
||||||
const Token *end_, AccessControl access_, bool mutable_,
|
const Token *end_, AccessControl access_, bool mutable_,
|
||||||
bool static_, bool const_, bool class_, const Scope *type_,
|
bool static_, bool const_, bool class_, const Scope *type_,
|
||||||
const Scope *scope_, bool array_,
|
const Scope *scope_, bool array_, bool pointer_,
|
||||||
const std::vector<Dimension> &dimensions_) {
|
const std::vector<Dimension> &dimensions_) {
|
||||||
varlist.push_back(Variable(token_, start_, end_, varlist.size(),
|
varlist.push_back(Variable(token_, start_, end_, varlist.size(),
|
||||||
access_, mutable_, static_, const_, class_,
|
access_, mutable_, static_, const_, class_,
|
||||||
type_, scope_, array_, false, dimensions_));
|
type_, scope_, array_, pointer_, false, dimensions_));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief initialize varlist */
|
/** @brief initialize varlist */
|
||||||
|
@ -497,9 +507,10 @@ private:
|
||||||
* @param vartok populated with pointer to the variable token, if found
|
* @param vartok populated with pointer to the variable token, if found
|
||||||
* @param typetok populated with pointer to the type token, if found
|
* @param typetok populated with pointer to the type token, if found
|
||||||
* @param isArray reference to variable to set if array is found
|
* @param isArray reference to variable to set if array is found
|
||||||
|
* @param isPointer reference to variable to set if pointer is found
|
||||||
* @return true if tok points to a variable declaration, false otherwise
|
* @return true if tok points to a variable declaration, false otherwise
|
||||||
*/
|
*/
|
||||||
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const;
|
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer) const;
|
||||||
bool isSimpleVariable(const Token* tok) const;
|
bool isSimpleVariable(const Token* tok) const;
|
||||||
bool isArrayVariable(const Token* tok) const;
|
bool isArrayVariable(const Token* tok) const;
|
||||||
bool findClosingBracket(const Token* tok, const Token*& close) const;
|
bool findClosingBracket(const Token* tok, const Token*& close) const;
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
,t(NULL)
|
,t(NULL)
|
||||||
,found(false)
|
,found(false)
|
||||||
,isArray(false)
|
,isArray(false)
|
||||||
|
,isPointer(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void reportOut(const std::string &outmsg) {
|
virtual void reportOut(const std::string &outmsg) {
|
||||||
|
@ -51,6 +52,7 @@ private:
|
||||||
const Token* t;
|
const Token* t;
|
||||||
bool found;
|
bool found;
|
||||||
bool isArray;
|
bool isArray;
|
||||||
|
bool isPointer;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
vartok = NULL;
|
vartok = NULL;
|
||||||
|
@ -58,6 +60,7 @@ private:
|
||||||
t = NULL;
|
t = NULL;
|
||||||
found = false;
|
found = false;
|
||||||
isArray = false;
|
isArray = false;
|
||||||
|
isPointer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -132,209 +135,230 @@ private:
|
||||||
|
|
||||||
void test_isVariableDeclarationCanHandleNull() {
|
void test_isVariableDeclarationCanHandleNull() {
|
||||||
reset();
|
reset();
|
||||||
bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(false, result);
|
ASSERT_EQUALS(false, result);
|
||||||
ASSERT(NULL == vartok);
|
ASSERT(NULL == vartok);
|
||||||
ASSERT(NULL == typetok);
|
ASSERT(NULL == typetok);
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesSimpleDeclaration() {
|
void test_isVariableDeclarationIdentifiesSimpleDeclaration() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize simpleDeclaration("int x;");
|
givenACodeSampleToTokenize simpleDeclaration("int x;");
|
||||||
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("x", vartok->str());
|
ASSERT_EQUALS("x", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesScopedDeclaration() {
|
void test_isVariableDeclarationIdentifiesScopedDeclaration() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize ScopedDeclaration("::int x;");
|
givenACodeSampleToTokenize ScopedDeclaration("::int x;");
|
||||||
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("x", vartok->str());
|
ASSERT_EQUALS("x", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesStdDeclaration() {
|
void test_isVariableDeclarationIdentifiesStdDeclaration() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize StdDeclaration("std::string x;");
|
givenACodeSampleToTokenize StdDeclaration("std::string x;");
|
||||||
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("x", vartok->str());
|
ASSERT_EQUALS("x", vartok->str());
|
||||||
ASSERT_EQUALS("string", typetok->str());
|
ASSERT_EQUALS("string", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesScopedStdDeclaration() {
|
void test_isVariableDeclarationIdentifiesScopedStdDeclaration() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize StdDeclaration("::std::string x;");
|
givenACodeSampleToTokenize StdDeclaration("::std::string x;");
|
||||||
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("x", vartok->str());
|
ASSERT_EQUALS("x", vartok->str());
|
||||||
ASSERT_EQUALS("string", typetok->str());
|
ASSERT_EQUALS("string", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesManyScopes() {
|
void test_isVariableDeclarationIdentifiesManyScopes() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;");
|
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;");
|
||||||
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("x", vartok->str());
|
ASSERT_EQUALS("x", vartok->str());
|
||||||
ASSERT_EQUALS("EE", typetok->str());
|
ASSERT_EQUALS("EE", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesPointers() {
|
void test_isVariableDeclarationIdentifiesPointers() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize pointer("int* p;");
|
givenACodeSampleToTokenize pointer("int* p;");
|
||||||
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("p", vartok->str());
|
ASSERT_EQUALS("p", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationDoesNotIdentifyConstness() {
|
void test_isVariableDeclarationDoesNotIdentifyConstness() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize constness("const int* cp;");
|
givenACodeSampleToTokenize constness("const int* cp;");
|
||||||
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(false, result);
|
ASSERT_EQUALS(false, result);
|
||||||
ASSERT(NULL == vartok);
|
ASSERT(NULL == vartok);
|
||||||
ASSERT(NULL == typetok);
|
ASSERT(NULL == typetok);
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesFirstOfManyVariables() {
|
void test_isVariableDeclarationIdentifiesFirstOfManyVariables() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize multipleDeclaration("int first, second;");
|
givenACodeSampleToTokenize multipleDeclaration("int first, second;");
|
||||||
bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("first", vartok->str());
|
ASSERT_EQUALS("first", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() {
|
void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;");
|
givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;");
|
||||||
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("p", vartok->str());
|
ASSERT_EQUALS("p", vartok->str());
|
||||||
ASSERT_EQUALS("EE", typetok->str());
|
ASSERT_EQUALS("EE", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() {
|
void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize pointerToPointer("int** pp;");
|
givenACodeSampleToTokenize pointerToPointer("int** pp;");
|
||||||
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("pp", vartok->str());
|
ASSERT_EQUALS("pp", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() {
|
void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize pointerToPointer("int***** p;");
|
givenACodeSampleToTokenize pointerToPointer("int***** p;");
|
||||||
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("p", vartok->str());
|
ASSERT_EQUALS("p", vartok->str());
|
||||||
ASSERT_EQUALS("int", typetok->str());
|
ASSERT_EQUALS("int", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesArray() {
|
void test_isVariableDeclarationIdentifiesArray() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize array("::std::string v[3];");
|
givenACodeSampleToTokenize array("::std::string v[3];");
|
||||||
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("v", vartok->str());
|
ASSERT_EQUALS("v", vartok->str());
|
||||||
ASSERT_EQUALS("string", typetok->str());
|
ASSERT_EQUALS("string", typetok->str());
|
||||||
ASSERT(true == isArray);
|
ASSERT(true == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isVariableDeclarationIdentifiesOfArrayPointers() {
|
void test_isVariableDeclarationIdentifiesOfArrayPointers() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize array("A *a[5];");
|
givenACodeSampleToTokenize array("A *a[5];");
|
||||||
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("a", vartok->str());
|
ASSERT_EQUALS("a", vartok->str());
|
||||||
ASSERT_EQUALS("A", typetok->str());
|
ASSERT_EQUALS("A", typetok->str());
|
||||||
ASSERT(true == isArray);
|
ASSERT(true == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesTemplatedPointerVariable() {
|
void isVariableDeclarationIdentifiesTemplatedPointerVariable() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::set<char>* chars;");
|
givenACodeSampleToTokenize var("std::set<char>* chars;");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("chars", vartok->str());
|
ASSERT_EQUALS("chars", vartok->str());
|
||||||
ASSERT_EQUALS("set", typetok->str());
|
ASSERT_EQUALS("set", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() {
|
void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::deque<int>*** ints;");
|
givenACodeSampleToTokenize var("std::deque<int>*** ints;");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("ints", vartok->str());
|
ASSERT_EQUALS("ints", vartok->str());
|
||||||
ASSERT_EQUALS("deque", typetok->str());
|
ASSERT_EQUALS("deque", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(true == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesTemplatedArrayVariable() {
|
void isVariableDeclarationIdentifiesTemplatedArrayVariable() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::deque<int> ints[3];");
|
givenACodeSampleToTokenize var("std::deque<int> ints[3];");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("ints", vartok->str());
|
ASSERT_EQUALS("ints", vartok->str());
|
||||||
ASSERT_EQUALS("deque", typetok->str());
|
ASSERT_EQUALS("deque", typetok->str());
|
||||||
ASSERT(true == isArray);
|
ASSERT(true == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesTemplatedVariable() {
|
void isVariableDeclarationIdentifiesTemplatedVariable() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::vector<int> ints;");
|
givenACodeSampleToTokenize var("std::vector<int> ints;");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("ints", vartok->str());
|
ASSERT_EQUALS("ints", vartok->str());
|
||||||
ASSERT_EQUALS("vector", typetok->str());
|
ASSERT_EQUALS("vector", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesTemplatedVariableIterator() {
|
void isVariableDeclarationIdentifiesTemplatedVariableIterator() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
|
givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("floats", vartok->str());
|
ASSERT_EQUALS("floats", vartok->str());
|
||||||
ASSERT_EQUALS("const_iterator", typetok->str());
|
ASSERT_EQUALS("const_iterator", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationIdentifiesNestedTemplateVariable() {
|
void isVariableDeclarationIdentifiesNestedTemplateVariable() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(true, result);
|
ASSERT_EQUALS(true, result);
|
||||||
ASSERT_EQUALS("intsets", vartok->str());
|
ASSERT_EQUALS("intsets", vartok->str());
|
||||||
ASSERT_EQUALS("deque", typetok->str());
|
ASSERT_EQUALS("deque", typetok->str());
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isVariableDeclarationDoesNotIdentifyTemplateClass() {
|
void isVariableDeclarationDoesNotIdentifyTemplateClass() {
|
||||||
reset();
|
reset();
|
||||||
givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
|
givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
|
||||||
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray);
|
bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray, isPointer);
|
||||||
ASSERT_EQUALS(false, result);
|
ASSERT_EQUALS(false, result);
|
||||||
ASSERT(false == isArray);
|
ASSERT(false == isArray);
|
||||||
|
ASSERT(false == isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void canFindMatchingBracketsNeedsOpen() {
|
void canFindMatchingBracketsNeedsOpen() {
|
||||||
|
|
Loading…
Reference in New Issue