- Improved nullpointer check: Fixed #1171
- Improved accuracy of function analysis in symboldatabase - Code cleanups
This commit is contained in:
parent
15669d20b4
commit
42f418db54
|
@ -115,28 +115,31 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
functionNames2_nullptr.insert("modf");
|
functionNames2_nullptr.insert("modf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Token::Match(&tok, "%var% ( )") || !tok.tokAt(2))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Token* firstParam = tok.tokAt(2);
|
||||||
|
const Token* secondParam = firstParam->nextArgument();
|
||||||
|
|
||||||
// 1st parameter..
|
// 1st parameter..
|
||||||
if ((Token::Match(&tok, "%var% ( %var% ,|)") && tok.tokAt(2)->varId() > 0) ||
|
if ((Token::Match(firstParam, "%var% ,|)") && firstParam->varId() > 0) ||
|
||||||
(value == 0 && Token::Match(&tok, "%var% ( 0 ,|)"))) {
|
(value == 0 && Token::Match(firstParam, "0 ,|)"))) {
|
||||||
if (functionNames1_all.find(tok.str()) != functionNames1_all.end())
|
if (functionNames1_all.find(tok.str()) != functionNames1_all.end())
|
||||||
var.push_back(tok.tokAt(2));
|
var.push_back(firstParam);
|
||||||
else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
|
else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
|
||||||
var.push_back(tok.tokAt(2));
|
var.push_back(firstParam);
|
||||||
else if (value != 0 && Token::simpleMatch(&tok, "fflush"))
|
else if (value != 0 && tok.str() == "fflush")
|
||||||
var.push_back(tok.tokAt(2));
|
var.push_back(firstParam);
|
||||||
else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && tok.strAt(4) != "0") // Only if length is not zero
|
else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero
|
||||||
var.push_back(tok.tokAt(2));
|
var.push_back(firstParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2nd parameter..
|
// 2nd parameter..
|
||||||
if (Token::Match(&tok, "%var% ( !!)")) {
|
if (secondParam && ((value == 0 && secondParam->str() == "0") || (Token::Match(secondParam, "%var%") && secondParam->varId() > 0))) {
|
||||||
const Token* secondParameter = tok.tokAt(2)->nextArgument();
|
if (functionNames2_all.find(tok.str()) != functionNames2_all.end())
|
||||||
if (secondParameter && ((value == 0 && secondParameter->str() == "0") || (Token::Match(secondParameter, "%var%") && secondParameter->varId() > 0))) {
|
var.push_back(secondParam);
|
||||||
if (functionNames2_all.find(tok.str()) != functionNames2_all.end())
|
else if (value == 0 && functionNames2_nullptr.find(tok.str()) != functionNames2_nullptr.end())
|
||||||
var.push_back(secondParameter);
|
var.push_back(secondParam);
|
||||||
else if (value == 0 && functionNames2_nullptr.find(tok.str()) != functionNames2_nullptr.end())
|
|
||||||
var.push_back(secondParameter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf")) {
|
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf")) {
|
||||||
|
@ -145,25 +148,22 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf");
|
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf");
|
||||||
|
|
||||||
if (Token::Match(&tok, "printf|scanf ( %str%")) {
|
if (Token::Match(&tok, "printf|scanf ( %str%")) {
|
||||||
formatString = tok.strAt(2);
|
formatString = firstParam->strValue();
|
||||||
if (tok.strAt(3) == ",")
|
argListTok = secondParam;
|
||||||
argListTok = tok.tokAt(4);
|
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf")) {
|
||||||
else
|
const Token* formatStringTok = secondParam; // Find second parameter (format string)
|
||||||
argListTok = 0;
|
if (formatStringTok && formatStringTok->str()[0] == '"') {
|
||||||
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %any%")) {
|
|
||||||
const Token* formatStringTok = tok.tokAt(2)->nextArgument(); // Find second parameter (format string)
|
|
||||||
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
|
|
||||||
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
|
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
|
||||||
formatString = formatStringTok->str();
|
formatString = formatStringTok->strValue();
|
||||||
}
|
}
|
||||||
} else if (Token::Match(&tok, "snprintf|fnprintf ( %any%")) {
|
} else if (Token::Match(&tok, "snprintf|fnprintf")) {
|
||||||
const Token* formatStringTok = tok.tokAt(2);
|
const Token* formatStringTok = secondParam;
|
||||||
for (int i = 0; i < 2 && formatStringTok; i++) {
|
for (int i = 0; i < 1 && formatStringTok; i++) {
|
||||||
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
|
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
|
||||||
}
|
}
|
||||||
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
|
if (formatStringTok && formatStringTok->str()[0] == '"') {
|
||||||
argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
|
argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
|
||||||
formatString = formatStringTok->str();
|
formatString = formatStringTok->strValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
|
if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
|
||||||
if ((value == 0 && argListTok->str() == "0") || (Token::Match(argListTok, "%var%") && argListTok->varId() > 0)) {
|
if ((value == 0 && argListTok->str() == "0") || (argListTok->varId() > 0)) {
|
||||||
var.push_back(argListTok);
|
var.push_back(argListTok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,7 +1026,13 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]")))
|
else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]")))
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
|
|
||||||
else if (Token::Match(tok->previous(), "[={};] %var% (")) {
|
else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) {
|
||||||
|
if (Token::Match(tok->tokAt(2), "0 )")) {
|
||||||
|
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
|
||||||
|
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::"))
|
||||||
|
nullPointerError(tok);
|
||||||
|
}
|
||||||
|
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(*tok, var, 0);
|
parseFunctionCall(*tok, var, 0);
|
||||||
|
|
||||||
|
@ -1038,11 +1044,6 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
}
|
}
|
||||||
} else if (Token::simpleMatch(tok, "std :: string ( 0 )"))
|
} else if (Token::simpleMatch(tok, "std :: string ( 0 )"))
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
else if (Token::Match(tok, "%var% ( 0 )")) {
|
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
|
|
||||||
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::"))
|
|
||||||
nullPointerError(tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ovarid = 0;
|
unsigned int ovarid = 0;
|
||||||
if (Token::Match(tok, "0 ==|!= %var%"))
|
if (Token::Match(tok, "0 ==|!= %var%"))
|
||||||
|
|
|
@ -199,14 +199,14 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scope->access = Private;
|
scope->access = Private;
|
||||||
else if (tok->str() == "protected")
|
else if (tok->str() == "protected")
|
||||||
scope->access = Protected;
|
scope->access = Protected;
|
||||||
else if (tok->str() == "public")
|
else
|
||||||
scope->access = Public;
|
scope->access = Public;
|
||||||
|
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// class function?
|
// class function?
|
||||||
else if (tok->previous()->str() != "::" && isFunction(tok, &funcStart, &argStart)) {
|
else if (tok->previous()->str() != "::" && isFunction(tok, scope, &funcStart, &argStart)) {
|
||||||
Function function;
|
Function function;
|
||||||
|
|
||||||
// save the function definition argument start '('
|
// save the function definition argument start '('
|
||||||
|
@ -347,12 +347,12 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
}
|
}
|
||||||
|
|
||||||
// nested class or friend function?
|
// nested class or friend function?
|
||||||
else if (tok->previous()->str() == "::" && isFunction(tok, &funcStart, &argStart)) {
|
else if (tok->previous()->str() == "::" && isFunction(tok, scope, &funcStart, &argStart)) {
|
||||||
/** @todo check entire qualification for match */
|
/** @todo check entire qualification for match */
|
||||||
Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
|
Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
|
||||||
|
|
||||||
if (nested)
|
if (nested)
|
||||||
addFunction(&scope, &tok, argStart);
|
addClassFunction(&scope, &tok, argStart);
|
||||||
else {
|
else {
|
||||||
/** @todo handle friend functions */
|
/** @todo handle friend functions */
|
||||||
}
|
}
|
||||||
|
@ -373,54 +373,23 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
const Token *argStart = 0;
|
const Token *argStart = 0;
|
||||||
|
|
||||||
// function?
|
// function?
|
||||||
if (isFunction(tok, &funcStart, &argStart)) {
|
if (isFunction(tok, scope, &funcStart, &argStart)) {
|
||||||
// has body?
|
// has body?
|
||||||
if (Token::Match(argStart->link(), ") const| {|:")) {
|
if (Token::Match(argStart->link(), ") const| {|:")) {
|
||||||
Scope *old_scope = scope;
|
Scope *old_scope = scope;
|
||||||
|
|
||||||
// class function
|
// class function
|
||||||
if (tok->previous() && tok->previous()->str() == "::")
|
if (tok->previous() && tok->previous()->str() == "::")
|
||||||
addFunction(&scope, &tok, argStart);
|
addClassFunction(&scope, &tok, argStart);
|
||||||
|
|
||||||
// class destructor
|
// class destructor
|
||||||
else if (tok->previous() && tok->previous()->str() == "~" &&
|
else if (tok->previous() && tok->previous()->str() == "~" &&
|
||||||
tok->tokAt(-2) && tok->strAt(-2) == "::")
|
tok->tokAt(-2) && tok->strAt(-2) == "::")
|
||||||
addFunction(&scope, &tok, argStart);
|
addClassFunction(&scope, &tok, argStart);
|
||||||
|
|
||||||
// regular function
|
// regular function
|
||||||
else {
|
else
|
||||||
Function function;
|
addGlobalFunction(scope, tok, argStart, funcStart);
|
||||||
|
|
||||||
// save the function definition argument start '('
|
|
||||||
function.argDef = argStart;
|
|
||||||
|
|
||||||
// save the access type
|
|
||||||
function.access = Public;
|
|
||||||
|
|
||||||
// save the function name location
|
|
||||||
function.tokenDef = funcStart;
|
|
||||||
function.token = funcStart;
|
|
||||||
|
|
||||||
function.isInline = false;
|
|
||||||
function.hasBody = true;
|
|
||||||
function.arg = function.argDef;
|
|
||||||
function.type = Function::eFunction;
|
|
||||||
|
|
||||||
// find start of function '{'
|
|
||||||
const Token *start = tok;
|
|
||||||
while (start && start->str() != "{")
|
|
||||||
start = start->next();
|
|
||||||
|
|
||||||
// save start of function
|
|
||||||
function.start = start;
|
|
||||||
|
|
||||||
addNewFunction(&scope, &tok);
|
|
||||||
|
|
||||||
if (scope) {
|
|
||||||
old_scope->functionList.push_back(function);
|
|
||||||
scope->function = &old_scope->functionList.back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// syntax error
|
// syntax error
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
|
@ -432,47 +401,17 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
// function returning function pointer with body
|
// function returning function pointer with body
|
||||||
else if (Token::simpleMatch(argStart->link(), ") ) (") &&
|
else if (Token::simpleMatch(argStart->link(), ") ) (") &&
|
||||||
Token::Match(argStart->link()->linkAt(2), ") const| {")) {
|
Token::Match(argStart->link()->linkAt(2), ") const| {")) {
|
||||||
const Token *tok1 = funcStart;
|
tok = funcStart;
|
||||||
Scope *old_scope = scope;
|
Scope *old_scope = scope;
|
||||||
|
|
||||||
// class function
|
// class function
|
||||||
if (tok1->previous()->str() == "::")
|
if (tok->previous()->str() == "::")
|
||||||
addFunction(&scope, &tok1, argStart);
|
addClassFunction(&scope, &tok, argStart);
|
||||||
|
|
||||||
// regular function
|
// regular function
|
||||||
else {
|
else {
|
||||||
Function function;
|
Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
|
||||||
|
function->retFuncPtr = true;
|
||||||
// save the function definition argument start '('
|
|
||||||
function.argDef = argStart;
|
|
||||||
|
|
||||||
// save the access type
|
|
||||||
function.access = Public;
|
|
||||||
|
|
||||||
// save the function name location
|
|
||||||
function.tokenDef = funcStart;
|
|
||||||
function.token = funcStart;
|
|
||||||
|
|
||||||
function.isInline = false;
|
|
||||||
function.hasBody = true;
|
|
||||||
function.arg = function.argDef;
|
|
||||||
function.type = Function::eFunction;
|
|
||||||
function.retFuncPtr = true;
|
|
||||||
|
|
||||||
// find start of function '{'
|
|
||||||
const Token *start = tok;
|
|
||||||
while (start && start->str() != "{")
|
|
||||||
start = start->next();
|
|
||||||
|
|
||||||
// save start of function
|
|
||||||
function.start = start;
|
|
||||||
|
|
||||||
addNewFunction(&scope, &tok1);
|
|
||||||
|
|
||||||
if (scope) {
|
|
||||||
old_scope->functionList.push_back(function);
|
|
||||||
scope->function = &old_scope->functionList.back();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// syntax error?
|
// syntax error?
|
||||||
|
@ -480,8 +419,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scope = old_scope;
|
scope = old_scope;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = tok1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function prototype
|
// function prototype
|
||||||
|
@ -810,7 +747,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolDatabase::isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const
|
bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart) const
|
||||||
{
|
{
|
||||||
// function returning function pointer? '... ( ... %var% ( ... ))( ... ) {'
|
// function returning function pointer? '... ( ... %var% ( ... ))( ... ) {'
|
||||||
if (tok->str() == "(" &&
|
if (tok->str() == "(" &&
|
||||||
|
@ -825,7 +762,10 @@ bool SymbolDatabase::isFunction(const Token *tok, const Token **funcStart, const
|
||||||
}
|
}
|
||||||
|
|
||||||
// regular function?
|
// regular function?
|
||||||
else if (Token::Match(tok, "%var% (") &&
|
else if (Token::Match(tok, "%var% (") && tok->previous() &&
|
||||||
|
(tok->previous()->isName() || tok->previous()->str() == "&" || tok->previous()->str() == "*" || // Either a return type in front of tok
|
||||||
|
tok->previous()->str() == "::" || tok->previous()->str() == "~" || // or a scope qualifier in front of tok
|
||||||
|
outerScope->isClassOrStruct()) && // or a ctor/dtor
|
||||||
(Token::Match(tok->next()->link(), ") const| ;|{|=") ||
|
(Token::Match(tok->next()->link(), ") const| ;|{|=") ||
|
||||||
Token::Match(tok->next()->link(), ") : %var% (|::"))) {
|
Token::Match(tok->next()->link(), ") : %var% (|::"))) {
|
||||||
*funcStart = tok;
|
*funcStart = tok;
|
||||||
|
@ -848,10 +788,18 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
|
|
||||||
// skip default value assignment
|
// skip default value assignment
|
||||||
else if (first->next()->str() == "=") {
|
else if (first->next()->str() == "=") {
|
||||||
first = first->tokAt(2);
|
first = first->nextArgument();
|
||||||
|
|
||||||
if (second->next()->str() == "=")
|
if (second->next()->str() == "=") {
|
||||||
second = second->tokAt(2);
|
second = second->nextArgument();
|
||||||
|
if (!first || !second) { // End of argument list (first or second)
|
||||||
|
match = !first && !second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!first) { // End of argument list (first)
|
||||||
|
match = second->next() && second->next()->str() == ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// definition missing variable name
|
// definition missing variable name
|
||||||
|
@ -877,10 +825,6 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
// skip variable names
|
// skip variable names
|
||||||
first = first->next();
|
first = first->next();
|
||||||
second = second->next();
|
second = second->next();
|
||||||
|
|
||||||
// skip default value assignment
|
|
||||||
if (first->next()->str() == "=")
|
|
||||||
first = first->tokAt(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// variable with class path
|
// variable with class path
|
||||||
|
@ -920,7 +864,45 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDatabase::addFunction(Scope **scope, const Token **tok, const Token *argStart)
|
Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart)
|
||||||
|
{
|
||||||
|
Function function;
|
||||||
|
|
||||||
|
// save the function definition argument start '('
|
||||||
|
function.argDef = argStart;
|
||||||
|
|
||||||
|
// save the access type
|
||||||
|
function.access = Public;
|
||||||
|
|
||||||
|
// save the function name location
|
||||||
|
function.tokenDef = funcStart;
|
||||||
|
function.token = funcStart;
|
||||||
|
|
||||||
|
function.isInline = false;
|
||||||
|
function.hasBody = true;
|
||||||
|
function.arg = function.argDef;
|
||||||
|
function.type = Function::eFunction;
|
||||||
|
|
||||||
|
// find start of function '{'
|
||||||
|
const Token *start = tok;
|
||||||
|
while (start && start->str() != "{")
|
||||||
|
start = start->next();
|
||||||
|
|
||||||
|
// save start of function
|
||||||
|
function.start = start;
|
||||||
|
|
||||||
|
Scope* old_scope = scope;
|
||||||
|
addNewFunction(&scope, &tok);
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
old_scope->functionList.push_back(function);
|
||||||
|
scope->function = &old_scope->functionList.back();
|
||||||
|
return scope->function;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const Token *argStart)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
bool added = false;
|
bool added = false;
|
||||||
|
@ -1880,29 +1862,25 @@ const Variable *Scope::getVariable(const std::string &varname) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Token* skipScopeIdentifiers(const Token* tok)
|
static const Token* skipScopeIdentifiers(const Token* tok)
|
||||||
{
|
{
|
||||||
const Token* ret = tok;
|
if (Token::simpleMatch(tok, "::")) {
|
||||||
|
tok = tok->next();
|
||||||
if (Token::simpleMatch(ret, "::")) {
|
|
||||||
ret = ret->next();
|
|
||||||
}
|
}
|
||||||
while (Token::Match(ret, "%type% ::")) {
|
while (Token::Match(tok, "%type% ::")) {
|
||||||
ret = ret->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Token* skipPointers(const Token* tok)
|
static const Token* skipPointers(const Token* tok)
|
||||||
{
|
{
|
||||||
const Token* ret = tok;
|
while (Token::Match(tok, "*|&")) {
|
||||||
|
tok = tok->next();
|
||||||
while (Token::Match(ret, "*|&")) {
|
|
||||||
ret = ret->next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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, bool &isArray, bool &isPointer, bool &isReference) const
|
||||||
|
@ -1928,11 +1906,11 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
localVarTok = skipPointers(localTypeTok->next());
|
localVarTok = skipPointers(localTypeTok->next());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSimpleVariable(localVarTok)) {
|
if (Token::Match(localVarTok, "%var% ;|=")) {
|
||||||
vartok = localVarTok;
|
vartok = localVarTok;
|
||||||
typetok = localTypeTok;
|
typetok = localTypeTok;
|
||||||
isArray = false;
|
isArray = false;
|
||||||
} else if (isArrayVariable(localVarTok)) {
|
} else if (Token::Match(localVarTok, "%var% [") && localVarTok->str() != "operator") {
|
||||||
vartok = localVarTok;
|
vartok = localVarTok;
|
||||||
typetok = localTypeTok;
|
typetok = localTypeTok;
|
||||||
isArray = true;
|
isArray = true;
|
||||||
|
@ -1956,16 +1934,6 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
return NULL != vartok;
|
return NULL != vartok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scope::isSimpleVariable(const Token* tok) const
|
|
||||||
{
|
|
||||||
return Token::Match(tok, "%var% ;|=");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scope::isArrayVariable(const Token* tok) const
|
|
||||||
{
|
|
||||||
return Token::Match(tok, "%var% [") && tok->next()->str() != "operator";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scope::findClosingBracket(const Token* tok, const Token*& close) const
|
bool Scope::findClosingBracket(const Token* tok, const Token*& close) const
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
|
@ -530,8 +530,6 @@ private:
|
||||||
* @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, bool &isPointer, bool &isReference) 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;
|
bool findClosingBracket(const Token* tok, const Token*& close) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -589,10 +587,11 @@ private:
|
||||||
// Needed by Borland C++:
|
// Needed by Borland C++:
|
||||||
friend class Scope;
|
friend class Scope;
|
||||||
|
|
||||||
void addFunction(Scope **info, const Token **tok, const Token *argStart);
|
void addClassFunction(Scope **info, const Token **tok, const Token *argStart);
|
||||||
|
Function* addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart);
|
||||||
void addNewFunction(Scope **info, const Token **tok);
|
void addNewFunction(Scope **info, const Token **tok);
|
||||||
const Token *initBaseInfo(Scope *info, const Token *tok);
|
const Token *initBaseInfo(Scope *info, const Token *tok);
|
||||||
bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const;
|
bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart) const;
|
||||||
|
|
||||||
/** class/struct types */
|
/** class/struct types */
|
||||||
std::set<std::string> classAndStructTypes;
|
std::set<std::string> classAndStructTypes;
|
||||||
|
|
|
@ -1521,6 +1521,13 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n", errout.str());
|
||||||
|
|
||||||
|
// Ticket #1171
|
||||||
|
check("void foo(void* bar) {\n"
|
||||||
|
" if(strcmp(0, bar) == 0)\n"
|
||||||
|
" func();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
|
||||||
|
|
||||||
// Ticket #2413 - it's ok to pass NULL to fflush
|
// Ticket #2413 - it's ok to pass NULL to fflush
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" fflush(NULL);\n"
|
" fflush(NULL);\n"
|
||||||
|
|
|
@ -226,7 +226,7 @@ private:
|
||||||
|
|
||||||
// ticket #3121
|
// ticket #3121
|
||||||
void test_declared_function() {
|
void test_declared_function() {
|
||||||
check("ftime ( int a )\n"
|
check("int ftime ( int a )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return a;\n"
|
" return a;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
Loading…
Reference in New Issue