Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
b02919ae67
|
@ -992,7 +992,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check function call..
|
// Check function call..
|
||||||
if (Token::Match(tok, "%var% ("))
|
if (Token::Match(tok, "%var% (") && total_size > 0)
|
||||||
{
|
{
|
||||||
// No varid => function calls are not handled
|
// No varid => function calls are not handled
|
||||||
if (varid == 0)
|
if (varid == 0)
|
||||||
|
@ -1405,7 +1405,7 @@ void CheckBufferOverrun::checkStructVariable()
|
||||||
const std::string &structname = tok->next()->str();
|
const std::string &structname = tok->next()->str();
|
||||||
const Token *tok2 = tok;
|
const Token *tok2 = tok;
|
||||||
|
|
||||||
while (tok2->str() != "{")
|
while (tok2 && tok2->str() != "{")
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
|
|
||||||
// Found a struct declaration. Search for arrays..
|
// Found a struct declaration. Search for arrays..
|
||||||
|
|
|
@ -640,9 +640,7 @@ void CheckClass::privateFunctions()
|
||||||
// Check that all private functions are used..
|
// Check that all private functions are used..
|
||||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
|
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
|
||||||
{
|
{
|
||||||
const Token *ftok = func->arg->link()->next();
|
const Token *ftok = func->start;
|
||||||
while (ftok->str() != "{")
|
|
||||||
ftok = ftok->next();
|
|
||||||
const Token *etok = ftok->link();
|
const Token *etok = ftok->link();
|
||||||
|
|
||||||
for (; ftok != etok; ftok = ftok->next())
|
for (; ftok != etok; ftok = ftok->next())
|
||||||
|
@ -869,10 +867,12 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check of *this is returned
|
// check if *this is returned
|
||||||
else if (!(Token::Match(tok->tokAt(1), "(| * this ;|=") ||
|
else if (!(Token::Match(tok->tokAt(1), "(| * this ;|=") ||
|
||||||
Token::Match(tok->tokAt(1), "(| * this +=") ||
|
Token::Match(tok->tokAt(1), "(| * this +=") ||
|
||||||
Token::simpleMatch(tok->tokAt(1), "operator= (")))
|
Token::simpleMatch(tok->tokAt(1), "operator= (") ||
|
||||||
|
(Token::Match(tok->tokAt(1), "%type% :: operator= (") &&
|
||||||
|
tok->next()->str() == scope->className)))
|
||||||
operatorEqRetRefThisError(func->token);
|
operatorEqRetRefThisError(func->token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1351,7 +1351,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok)
|
||||||
{
|
{
|
||||||
const Token *tok1 = tok;
|
const Token *tok1 = tok;
|
||||||
|
|
||||||
while (tok->previous() && !Token::Match(tok->previous(), "}|{|;|public:|protected:|private:|return|:|?"))
|
while (tok->previous() && !Token::Match(tok->previous(), "}|{|;(||public:|protected:|private:|return|:|?"))
|
||||||
{
|
{
|
||||||
if (Token::simpleMatch(tok->previous(), "* this"))
|
if (Token::simpleMatch(tok->previous(), "* this"))
|
||||||
return true;
|
return true;
|
||||||
|
@ -1489,6 +1489,12 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Token *tok)
|
||||||
isconst = false;
|
isconst = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (Token::simpleMatch(tok1->previous(), ") <<") &&
|
||||||
|
isMemberVar(scope, tok1->tokAt(-2)))
|
||||||
|
{
|
||||||
|
isconst = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// increment/decrement (member variable?)..
|
// increment/decrement (member variable?)..
|
||||||
else if (Token::Match(tok1, "++|--"))
|
else if (Token::Match(tok1, "++|--"))
|
||||||
|
|
|
@ -350,8 +350,19 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo There are lots of false negatives here. A dereference
|
||||||
|
* is only investigated if a few specific conditions are met.
|
||||||
|
*/
|
||||||
|
|
||||||
// dereference in assignment
|
// dereference in assignment
|
||||||
if (Token::Match(tok1, "[{};] %var% = %var% . %var%"))
|
if (Token::Match(tok1, "[;{}] %var% . %var%"))
|
||||||
|
{
|
||||||
|
tok1 = tok1->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dereference in assignment
|
||||||
|
else if (Token::Match(tok1, "[{};] %var% = %var% . %var%"))
|
||||||
{
|
{
|
||||||
if (std::string(tok1->strAt(1)) == tok1->strAt(3))
|
if (std::string(tok1->strAt(1)) == tok1->strAt(3))
|
||||||
continue;
|
continue;
|
||||||
|
@ -433,8 +444,8 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check if pointer is null.
|
// Check if pointer is null.
|
||||||
// TODO: false negatives for something like: "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 (isPointer(varid1))
|
||||||
|
@ -563,14 +574,13 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
|
|
||||||
// vartok : token for the variable
|
// vartok : token for the variable
|
||||||
const Token *vartok = 0;
|
const Token *vartok = 0;
|
||||||
if (Token::Match(tok, "if ( ! %var% ) {"))
|
if (Token::Match(tok, "if ( ! %var% )|&&"))
|
||||||
vartok = tok->tokAt(3);
|
vartok = tok->tokAt(3);
|
||||||
else if (Token::Match(tok, "if ( NULL|0 == %var% ) {"))
|
else if (Token::Match(tok, "if ( NULL|0 == %var% )|&&"))
|
||||||
vartok = tok->tokAt(4);
|
vartok = tok->tokAt(4);
|
||||||
else if (Token::Match(tok, "if ( %var% == NULL|0 ) {"))
|
else if (Token::Match(tok, "if ( %var% == NULL|0 )|&&"))
|
||||||
vartok = tok->tokAt(2);
|
vartok = tok->tokAt(2);
|
||||||
else if (Token::Match(tok, "if|while ( %var% ) {") &&
|
else if (Token::Match(tok, "if|while ( %var% )|&&"))
|
||||||
!Token::simpleMatch(tok->tokAt(4)->link(), "} else"))
|
|
||||||
vartok = tok->tokAt(2);
|
vartok = tok->tokAt(2);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
@ -590,7 +600,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
// start token = inside the if-body
|
// start token = inside the if-body
|
||||||
const Token *tok1 = tok->next()->link()->tokAt(2);
|
const Token *tok1 = tok->next()->link()->tokAt(2);
|
||||||
|
|
||||||
if (Token::Match(tok, "if|while ( %var% )"))
|
if (Token::Match(tok, "if|while ( %var% )|&&"))
|
||||||
{
|
{
|
||||||
// pointer might be null
|
// pointer might be null
|
||||||
null = false;
|
null = false;
|
||||||
|
|
|
@ -321,7 +321,7 @@ void CheckOther::checkSelfAssignment()
|
||||||
std::set<unsigned int> pod;
|
std::set<unsigned int> pod;
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (tok->isStandardType() && tok->next()->varId() && Token::Match(tok->tokAt(2), "[,);]"))
|
if (tok->isStandardType() && Token::Match(tok->tokAt(2), "[,);]") && tok->next()->varId())
|
||||||
pod.insert(tok->next()->varId());
|
pod.insert(tok->next()->varId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,40 @@ void ExecutionPath::checkScope(const Token *tok, std::list<ExecutionPath *> &che
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #2231 - loop body only contains a conditional initialization..
|
||||||
|
if (Token::simpleMatch(tok2->next(), "if ("))
|
||||||
|
{
|
||||||
|
// Start { for the if block
|
||||||
|
const Token *tok3 = tok2->tokAt(2)->link();
|
||||||
|
if (Token::simpleMatch(tok3,") {"))
|
||||||
|
{
|
||||||
|
tok3 = tok3->next();
|
||||||
|
|
||||||
|
// End } for the if block
|
||||||
|
const Token *tok4 = tok3->link();
|
||||||
|
if (Token::Match(tok3, "{ %var% =") &&
|
||||||
|
Token::simpleMatch(tok4, "} }") &&
|
||||||
|
Token::simpleMatch(tok4->tokAt(-2), "break ;"))
|
||||||
|
{
|
||||||
|
// Is there a assignment and then a break?
|
||||||
|
const Token *t = Token::findmatch(tok3, ";");
|
||||||
|
if (t && t->tokAt(3) == tok4)
|
||||||
|
{
|
||||||
|
for (std::list<ExecutionPath *>::iterator it = checks.begin(); it != checks.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->varId == tok3->next()->varId())
|
||||||
|
{
|
||||||
|
(*it)->numberOfIf++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tok = tok2->link();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// parse loop bodies
|
// parse loop bodies
|
||||||
check->parseLoopBody(tok2->next(), checks);
|
check->parseLoopBody(tok2->next(), checks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,20 +338,32 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have finished a line that didn't contain any comment
|
// First skip over any whitespace that may be present
|
||||||
// (the '\n' is swallowed when a // comment is detected)
|
if (std::isspace(ch))
|
||||||
if ((ch == '\n' || str.compare(i,2,"//")==0) && !suppressionIDs.empty())
|
|
||||||
{
|
{
|
||||||
// Add the suppressions.
|
if (ch == ' ' && previous == ' ')
|
||||||
for (size_t j(0); j < suppressionIDs.size(); ++j)
|
|
||||||
{
|
{
|
||||||
const std::string errmsg(settings->nomsg.addSuppression(suppressionIDs[j], filename, lineno));
|
// Skip double white space
|
||||||
if (!errmsg.empty())
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
code << char(ch);
|
||||||
|
previous = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there has been <backspace><newline> sequences, add extra newlines..
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
++lineno;
|
||||||
|
if (newlines > 0)
|
||||||
|
{
|
||||||
|
code << std::string(newlines, '\n');
|
||||||
|
newlines = 0;
|
||||||
|
previous = '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suppressionIDs.clear();
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove comments..
|
// Remove comments..
|
||||||
|
@ -382,6 +394,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
||||||
}
|
}
|
||||||
else if (str.compare(i, 2, "/*", 0, 2) == 0)
|
else if (str.compare(i, 2, "/*", 0, 2) == 0)
|
||||||
{
|
{
|
||||||
|
size_t commentStart = i + 2;
|
||||||
unsigned char chPrev = 0;
|
unsigned char chPrev = 0;
|
||||||
++i;
|
++i;
|
||||||
while (i < str.length() && (chPrev != '*' || ch != '/'))
|
while (i < str.length() && (chPrev != '*' || ch != '/'))
|
||||||
|
@ -395,10 +408,44 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
||||||
++lineno;
|
++lineno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings && settings->_inlineSuppressions)
|
||||||
|
{
|
||||||
|
std::string comment(str, commentStart, i - commentStart);
|
||||||
|
std::istringstream iss(comment);
|
||||||
|
std::string word;
|
||||||
|
iss >> word;
|
||||||
|
if (word == "cppcheck-suppress")
|
||||||
|
{
|
||||||
|
iss >> word;
|
||||||
|
if (iss)
|
||||||
|
suppressionIDs.push_back(word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not whitespace and not a comment. Must be code here!
|
||||||
|
// Add any pending inline suppressions that have accumulated.
|
||||||
|
if (!suppressionIDs.empty())
|
||||||
|
{
|
||||||
|
if (settings != NULL)
|
||||||
|
{
|
||||||
|
// Add the suppressions.
|
||||||
|
for (size_t j(0); j < suppressionIDs.size(); ++j)
|
||||||
|
{
|
||||||
|
const std::string errmsg(settings->nomsg.addSuppression(suppressionIDs[j], filename, lineno));
|
||||||
|
if (!errmsg.empty())
|
||||||
|
{
|
||||||
|
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suppressionIDs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// String or char constants..
|
// String or char constants..
|
||||||
else if (ch == '\"' || ch == '\'')
|
if (ch == '\"' || ch == '\'')
|
||||||
{
|
{
|
||||||
code << char(ch);
|
code << char(ch);
|
||||||
char chNext;
|
char chNext;
|
||||||
|
@ -489,32 +536,11 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
||||||
previous = 'R';
|
previous = 'R';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just some code..
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ch == ' ' && previous == ' ')
|
|
||||||
{
|
|
||||||
// Skip double white space
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
code << char(ch);
|
code << char(ch);
|
||||||
previous = ch;
|
previous = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if there has been <backspace><newline> sequences, add extra newlines..
|
|
||||||
if (ch == '\n')
|
|
||||||
{
|
|
||||||
++lineno;
|
|
||||||
if (newlines > 0)
|
|
||||||
{
|
|
||||||
code << std::string(newlines, '\n');
|
|
||||||
newlines = 0;
|
|
||||||
previous = '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1304,7 +1330,33 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
|
||||||
if (it != variables.end())
|
if (it != variables.end())
|
||||||
{
|
{
|
||||||
if (!it->second.empty())
|
if (!it->second.empty())
|
||||||
tok->str(it->second);
|
{
|
||||||
|
// Tokenize the value
|
||||||
|
Tokenizer tokenizer2(&settings,NULL);
|
||||||
|
std::istringstream istr2(it->second);
|
||||||
|
tokenizer2.tokenize(istr2,"","",true);
|
||||||
|
|
||||||
|
// Copy the value tokens
|
||||||
|
std::stack<Token *> link;
|
||||||
|
for (const Token *tok2 = tokenizer2.tokens(); tok2; tok2 = tok2->next())
|
||||||
|
{
|
||||||
|
tok->str(tok2->str());
|
||||||
|
|
||||||
|
if (Token::Match(tok2,"[{([]"))
|
||||||
|
link.push(tok);
|
||||||
|
else if (!link.empty() && Token::Match(tok2,"[})]]"))
|
||||||
|
{
|
||||||
|
Token::createMutualLinks(link.top(), tok);
|
||||||
|
link.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tok2->next())
|
||||||
|
{
|
||||||
|
tok->insertToken("");
|
||||||
|
tok = tok->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if ((!tok->previous() || tok->strAt(-1) == "||" || tok->strAt(-1) == "&&" || tok->strAt(-1) == "(") &&
|
else if ((!tok->previous() || tok->strAt(-1) == "||" || tok->strAt(-1) == "&&" || tok->strAt(-1) == "(") &&
|
||||||
(!tok->next() || tok->strAt(1) == "||" || tok->strAt(1) == "&&" || tok->strAt(1) == ")"))
|
(!tok->next() || tok->strAt(1) == "||" || tok->strAt(1) == "&&" || tok->strAt(1) == ")"))
|
||||||
tok->str("1");
|
tok->str("1");
|
||||||
|
|
|
@ -57,6 +57,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
|
|
||||||
// goto initial '{'
|
// goto initial '{'
|
||||||
tok2 = initBaseInfo(new_scope, tok);
|
tok2 = initBaseInfo(new_scope, tok);
|
||||||
|
|
||||||
|
// make sure we have valid code
|
||||||
|
if (!tok2)
|
||||||
|
{
|
||||||
|
delete new_scope;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_scope->classStart = tok2;
|
new_scope->classStart = tok2;
|
||||||
|
@ -213,7 +220,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
function.isConst = true;
|
function.isConst = true;
|
||||||
|
|
||||||
// pure virtual function
|
// pure virtual function
|
||||||
if (Token::Match(end, ") const| = %any% ;"))
|
if (Token::Match(end, ") const| = %any%"))
|
||||||
function.isPure = true;
|
function.isPure = true;
|
||||||
|
|
||||||
// count the number of constructors
|
// count the number of constructors
|
||||||
|
@ -241,6 +248,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
function.isInline = true;
|
function.isInline = true;
|
||||||
function.hasBody = true;
|
function.hasBody = true;
|
||||||
|
|
||||||
|
// find start of function '{'
|
||||||
|
while (end && end->str() != "{")
|
||||||
|
end = end->next();
|
||||||
|
|
||||||
|
// save start of function
|
||||||
|
function.start = end;
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->functionList.push_back(function);
|
||||||
|
|
||||||
const Token *tok2 = funcStart;
|
const Token *tok2 = funcStart;
|
||||||
|
@ -761,6 +775,10 @@ void SymbolDatabase::addFunction(Scope **scope, const Token **tok, const Token *
|
||||||
func->hasBody = true;
|
func->hasBody = true;
|
||||||
func->token = *tok;
|
func->token = *tok;
|
||||||
func->arg = argStart;
|
func->arg = argStart;
|
||||||
|
const Token *start = argStart->link()->next();
|
||||||
|
while (start && start->str() != "{")
|
||||||
|
start = start->next();
|
||||||
|
func->start = start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (func->tokenDef->str() == (*tok)->str() && (*tok)->previous()->str() != "~")
|
else if (func->tokenDef->str() == (*tok)->str() && (*tok)->previous()->str() != "~")
|
||||||
|
@ -776,6 +794,10 @@ void SymbolDatabase::addFunction(Scope **scope, const Token **tok, const Token *
|
||||||
func->hasBody = true;
|
func->hasBody = true;
|
||||||
func->token = *tok;
|
func->token = *tok;
|
||||||
func->arg = argStart;
|
func->arg = argStart;
|
||||||
|
const Token *start = argStart->link()->next();
|
||||||
|
while (start && start->str() != "{")
|
||||||
|
start = start->next();
|
||||||
|
func->start = start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,6 +808,10 @@ void SymbolDatabase::addFunction(Scope **scope, const Token **tok, const Token *
|
||||||
func->hasBody = true;
|
func->hasBody = true;
|
||||||
func->token = *tok;
|
func->token = *tok;
|
||||||
func->arg = argStart;
|
func->arg = argStart;
|
||||||
|
const Token *start = argStart->link()->next()->next()->link()->next();
|
||||||
|
while (start && start->str() != "{")
|
||||||
|
start = start->next();
|
||||||
|
func->start = start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -872,6 +898,10 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok)
|
||||||
|
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
|
|
||||||
|
// check for invalid code
|
||||||
|
if (!tok2->next())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (tok2->str() == "public")
|
if (tok2->str() == "public")
|
||||||
{
|
{
|
||||||
base.access = Public;
|
base.access = Public;
|
||||||
|
@ -1142,6 +1172,7 @@ void Scope::getVariableList()
|
||||||
// This is the start of a statement
|
// This is the start of a statement
|
||||||
const Token *vartok = NULL;
|
const Token *vartok = NULL;
|
||||||
const Token *typetok = NULL;
|
const Token *typetok = NULL;
|
||||||
|
const Token *typestart = tok;
|
||||||
|
|
||||||
// Is it const..?
|
// Is it const..?
|
||||||
bool isConst = false;
|
bool isConst = false;
|
||||||
|
@ -1211,7 +1242,7 @@ void Scope::getVariableList()
|
||||||
if (typetok)
|
if (typetok)
|
||||||
scope = check->findVariableType(this, typetok);
|
scope = check->findVariableType(this, typetok);
|
||||||
|
|
||||||
addVariable(vartok, varaccess, isMutable, isStatic, isConst, isClass, scope);
|
addVariable(vartok, typestart, varaccess, isMutable, isStatic, isConst, isClass, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1453,7 @@ Scope * Scope::findInNestedListRecursive(const std::string & name)
|
||||||
for (it = nestedList.begin(); it != nestedList.end(); ++it)
|
for (it = nestedList.begin(); it != nestedList.end(); ++it)
|
||||||
{
|
{
|
||||||
Scope *child = (*it)->findInNestedListRecursive(name);
|
Scope *child = (*it)->findInNestedListRecursive(name);
|
||||||
|
if (child)
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -73,10 +73,11 @@ class Variable
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Variable(const Token *name_, std::size_t index_, AccessControl access_,
|
Variable(const Token *name_, const Token *start_, std::size_t index_,
|
||||||
bool mutable_, bool static_, bool const_, bool class_,
|
AccessControl access_, bool mutable_, bool static_, bool const_,
|
||||||
const Scope *type_)
|
bool class_, const Scope *type_)
|
||||||
: _name(name_),
|
: _name(name_),
|
||||||
|
_start(start_),
|
||||||
_index(index_),
|
_index(index_),
|
||||||
_access(access_),
|
_access(access_),
|
||||||
_flags(0),
|
_flags(0),
|
||||||
|
@ -97,6 +98,15 @@ public:
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get type start token.
|
||||||
|
* @return type start token
|
||||||
|
*/
|
||||||
|
const Token *typeStartToken() const
|
||||||
|
{
|
||||||
|
return _start;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get name string.
|
* Get name string.
|
||||||
* @return name string
|
* @return name string
|
||||||
|
@ -200,6 +210,9 @@ private:
|
||||||
/** @brief variable name token */
|
/** @brief variable name token */
|
||||||
const Token *_name;
|
const Token *_name;
|
||||||
|
|
||||||
|
/** @brief variable type start token */
|
||||||
|
const Token *_start;
|
||||||
|
|
||||||
/** @brief order declared */
|
/** @brief order declared */
|
||||||
std::size_t _index;
|
std::size_t _index;
|
||||||
|
|
||||||
|
@ -223,6 +236,7 @@ public:
|
||||||
argDef(NULL),
|
argDef(NULL),
|
||||||
token(NULL),
|
token(NULL),
|
||||||
arg(NULL),
|
arg(NULL),
|
||||||
|
start(NULL),
|
||||||
access(Public),
|
access(Public),
|
||||||
hasBody(false),
|
hasBody(false),
|
||||||
isInline(false),
|
isInline(false),
|
||||||
|
@ -245,6 +259,7 @@ public:
|
||||||
const Token *argDef; // function argument start '(' in class definition
|
const Token *argDef; // function argument start '(' in class definition
|
||||||
const Token *token; // function name token in implementation
|
const Token *token; // function name token in implementation
|
||||||
const Token *arg; // function argument start '('
|
const Token *arg; // function argument start '('
|
||||||
|
const Token *start; // function start '{'
|
||||||
AccessControl access; // public/protected/private
|
AccessControl access; // public/protected/private
|
||||||
bool hasBody; // has implementation
|
bool hasBody; // has implementation
|
||||||
bool isInline; // implementation in class definition
|
bool isInline; // implementation in class definition
|
||||||
|
@ -317,9 +332,9 @@ public:
|
||||||
*/
|
*/
|
||||||
Scope * findInNestedListRecursive(const std::string & name);
|
Scope * findInNestedListRecursive(const std::string & name);
|
||||||
|
|
||||||
void addVariable(const Token *token_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_)
|
void addVariable(const Token *token_, const Token *start_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_)
|
||||||
{
|
{
|
||||||
varlist.push_back(Variable(token_, varlist.size(), access_, mutable_, static_, const_, class_, type_));
|
varlist.push_back(Variable(token_, start_, varlist.size(), access_, mutable_, static_, const_, class_, type_));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief initialize varlist */
|
/** @brief initialize varlist */
|
||||||
|
|
136
lib/tokenize.cpp
136
lib/tokenize.cpp
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Cppcheck - A tool for static C/C++ code analysis
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
* Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team.
|
* Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team.
|
||||||
*
|
*
|
||||||
|
@ -837,6 +837,15 @@ static Token *splitDefinitionFromTypedef(Token *tok)
|
||||||
|
|
||||||
tok1->insertToken(";");
|
tok1->insertToken(";");
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
|
|
||||||
|
if (tok1->next()->str() == ";" && tok1 && tok1->previous()->str() == "}")
|
||||||
|
{
|
||||||
|
tok->deleteThis();
|
||||||
|
tok1->deleteThis();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
tok1->insertToken("typedef");
|
tok1->insertToken("typedef");
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
Token * tok3 = tok1;
|
Token * tok3 = tok1;
|
||||||
|
@ -850,6 +859,7 @@ static Token *splitDefinitionFromTypedef(Token *tok)
|
||||||
tok1->insertToken(name.c_str());
|
tok1->insertToken(name.c_str());
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
tok = tok3;
|
tok = tok3;
|
||||||
|
}
|
||||||
|
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
@ -2457,21 +2467,31 @@ void Tokenizer::labels()
|
||||||
* is the token pointing at a template parameters block
|
* is the token pointing at a template parameters block
|
||||||
* < int , 3 > => yes
|
* < int , 3 > => yes
|
||||||
* \param tok start token that must point at "<"
|
* \param tok start token that must point at "<"
|
||||||
* \return true if the tokens look like template parameters
|
* \return number of parameters (invalid parameters => 0)
|
||||||
*/
|
*/
|
||||||
static bool templateParameters(const Token *tok)
|
static unsigned int templateParameters(const Token *tok)
|
||||||
{
|
{
|
||||||
|
unsigned int numberOfParameters = 0;
|
||||||
|
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return false;
|
return 0;
|
||||||
if (tok->str() != "<")
|
if (tok->str() != "<")
|
||||||
return false;
|
return 0;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
while (tok)
|
while (tok)
|
||||||
{
|
{
|
||||||
|
++numberOfParameters;
|
||||||
|
|
||||||
|
// skip std::
|
||||||
|
while (Token::Match(tok, "%var% ::"))
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
if (!tok)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// num/type ..
|
// num/type ..
|
||||||
if (!tok->isNumber() && !tok->isName())
|
if (!tok->isNumber() && !tok->isName())
|
||||||
return false;
|
return 0;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
// optional "*"
|
// optional "*"
|
||||||
|
@ -2480,12 +2500,12 @@ static bool templateParameters(const Token *tok)
|
||||||
|
|
||||||
// ,/>
|
// ,/>
|
||||||
if (tok->str() == ">")
|
if (tok->str() == ">")
|
||||||
return true;
|
return numberOfParameters;
|
||||||
if (tok->str() != ",")
|
if (tok->str() != ",")
|
||||||
break;
|
break;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2768,6 +2788,33 @@ void Tokenizer::simplifyTemplatesUseDefaultArgumentValues(const std::list<Token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match template declaration/instantiation
|
||||||
|
* @param instance template instantiation
|
||||||
|
* @param name name of template
|
||||||
|
* @param numberOfArguments number of template arguments
|
||||||
|
* @param patternAfter pattern that must match the tokens after the ">"
|
||||||
|
* @return match => true
|
||||||
|
*/
|
||||||
|
static bool simplifyTemplatesInstantiateMatch(const Token *instance, const std::string &name, unsigned int numberOfArguments, const char patternAfter[])
|
||||||
|
{
|
||||||
|
if (!Token::simpleMatch(instance, (name + " <").c_str()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (numberOfArguments != templateParameters(instance->next()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (patternAfter)
|
||||||
|
{
|
||||||
|
const Token *tok = Token::findmatch(instance, ">");
|
||||||
|
if (!tok || !Token::Match(tok->next(), patternAfter))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing mismatching was found..
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
std::list<Token *> &used,
|
std::list<Token *> &used,
|
||||||
std::set<std::string> &expandedtemplates)
|
std::set<std::string> &expandedtemplates)
|
||||||
|
@ -2826,16 +2873,6 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
const bool isfunc(tok->strAt(namepos + 1) == "(");
|
const bool isfunc(tok->strAt(namepos + 1) == "(");
|
||||||
|
|
||||||
// locate template usage..
|
// locate template usage..
|
||||||
|
|
||||||
std::string s(name + " <");
|
|
||||||
for (unsigned int i = 0; i < type.size(); ++i)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
s += ",";
|
|
||||||
s += " %any% ";
|
|
||||||
}
|
|
||||||
const std::string pattern(s + "> ");
|
|
||||||
|
|
||||||
std::string::size_type sz1 = used.size();
|
std::string::size_type sz1 = used.size();
|
||||||
unsigned int recursiveCount = 0;
|
unsigned int recursiveCount = 0;
|
||||||
|
|
||||||
|
@ -2855,17 +2892,16 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
}
|
}
|
||||||
|
|
||||||
Token * const tok2 = *iter2;
|
Token * const tok2 = *iter2;
|
||||||
|
|
||||||
if (tok2->str() != name)
|
if (tok2->str() != name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Token::Match(tok2->previous(), "[;{}=]") &&
|
if (Token::Match(tok2->previous(), "[;{}=]") &&
|
||||||
!Token::Match(tok2, (pattern + (isfunc ? "(" : "*| %var%")).c_str()))
|
!simplifyTemplatesInstantiateMatch(*iter2, name, type.size(), isfunc ? "(" : "*| %var%"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// New type..
|
// New type..
|
||||||
std::vector<Token> types2;
|
std::vector<const Token *> types2;
|
||||||
s = "";
|
std::string s;
|
||||||
std::string s1(name + " < ");
|
std::string s1(name + " < ");
|
||||||
for (const Token *tok3 = tok2->tokAt(2); tok3 && tok3->str() != ">"; tok3 = tok3->next())
|
for (const Token *tok3 = tok2->tokAt(2); tok3 && tok3->str() != ">"; tok3 = tok3->next())
|
||||||
{
|
{
|
||||||
|
@ -2876,8 +2912,8 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
}
|
}
|
||||||
s1 += tok3->str();
|
s1 += tok3->str();
|
||||||
s1 += " ";
|
s1 += " ";
|
||||||
if (tok3->str() != ",")
|
if (Token::Match(tok3->previous(), "[<,]"))
|
||||||
types2.push_back(*tok3);
|
types2.push_back(tok3);
|
||||||
// add additional type information
|
// add additional type information
|
||||||
if (tok3->isUnsigned())
|
if (tok3->isUnsigned())
|
||||||
s += "unsigned";
|
s += "unsigned";
|
||||||
|
@ -2939,7 +2975,9 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
}
|
}
|
||||||
|
|
||||||
// member function implemented outside class definition
|
// member function implemented outside class definition
|
||||||
else if (_indentlevel == 0 && _parlevel == 0 && Token::Match(tok3, (pattern + " :: ~| %var% (").c_str()))
|
else if (_indentlevel == 0 &&
|
||||||
|
_parlevel == 0 &&
|
||||||
|
simplifyTemplatesInstantiateMatch(tok3, name, type.size(), ":: ~| %var% ("))
|
||||||
{
|
{
|
||||||
addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex());
|
addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex());
|
||||||
while (tok3->str() != "::")
|
while (tok3->str() != "::")
|
||||||
|
@ -2987,7 +3025,12 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
// replace type with given type..
|
// replace type with given type..
|
||||||
if (itype < type.size())
|
if (itype < type.size())
|
||||||
{
|
{
|
||||||
addtoken(&types2[itype], tok3->linenr(), tok3->fileIndex());
|
for (const Token *typetok = types2[itype];
|
||||||
|
typetok && !Token::Match(typetok, "[,>]");
|
||||||
|
typetok = typetok->next())
|
||||||
|
{
|
||||||
|
addtoken(typetok, tok3->linenr(), tok3->fileIndex());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3055,18 +3098,26 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
|
||||||
bool match = true;
|
bool match = true;
|
||||||
Token * tok5 = tok4->tokAt(2);
|
Token * tok5 = tok4->tokAt(2);
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
const Token *typetok = (!types2.empty()) ? types2[0] : 0;
|
||||||
while (tok5->str() != ">")
|
while (tok5->str() != ">")
|
||||||
{
|
{
|
||||||
if (tok5->str() != ",")
|
if (tok5->str() != ",")
|
||||||
{
|
{
|
||||||
if (tok5->isUnsigned() != types2[count].isUnsigned() ||
|
if (!typetok ||
|
||||||
tok5->isSigned() != types2[count].isSigned() ||
|
tok5->isUnsigned() != typetok->isUnsigned() ||
|
||||||
tok5->isLong() != types2[count].isLong())
|
tok5->isSigned() != typetok->isSigned() ||
|
||||||
|
tok5->isLong() != typetok->isLong())
|
||||||
{
|
{
|
||||||
match = false;
|
match = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
count++;
|
|
||||||
|
typetok = typetok ? typetok->next() : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
typetok = (count < types2.size()) ? types2[count] : 0;
|
||||||
}
|
}
|
||||||
tok5 = tok5->next();
|
tok5 = tok5->next();
|
||||||
}
|
}
|
||||||
|
@ -6257,7 +6308,7 @@ bool Tokenizer::simplifyKnownVariables()
|
||||||
if (tok2->str() == tok2->strAt(2))
|
if (tok2->str() == tok2->strAt(2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool pointeralias(tok2->tokAt(2)->isName() || tok2->tokAt(2)->str() == "&");
|
const Token * const valueToken = tok2->tokAt(2);
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
unsigned int valueVarId = 0;
|
unsigned int valueVarId = 0;
|
||||||
|
@ -6268,7 +6319,7 @@ bool Tokenizer::simplifyKnownVariables()
|
||||||
if (!simplifyKnownVariablesGetData(varid, &tok2, &tok3, value, valueVarId, valueIsPointer, floatvars.find(tok2->varId()) != floatvars.end()))
|
if (!simplifyKnownVariablesGetData(varid, &tok2, &tok3, value, valueVarId, valueIsPointer, floatvars.find(tok2->varId()) != floatvars.end()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, pointeralias, indentlevel);
|
ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6360,8 +6411,10 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, bool pointeralias, int indentlevel)
|
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel)
|
||||||
{
|
{
|
||||||
|
const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %var% ["));
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
Token* bailOutFromLoop = 0;
|
Token* bailOutFromLoop = 0;
|
||||||
|
@ -6540,6 +6593,11 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
tok3->deleteNext();
|
tok3->deleteNext();
|
||||||
tok3->deleteNext();
|
tok3->deleteNext();
|
||||||
}
|
}
|
||||||
|
if (Token::Match(valueToken, "& %var% ;"))
|
||||||
|
{
|
||||||
|
tok3->insertToken("&");
|
||||||
|
tok3 = tok3->next();
|
||||||
|
}
|
||||||
tok3 = tok3->next();
|
tok3 = tok3->next();
|
||||||
tok3->str(value);
|
tok3->str(value);
|
||||||
tok3->varId(valueVarId);
|
tok3->varId(valueVarId);
|
||||||
|
@ -8078,7 +8136,7 @@ void Tokenizer::cppcheckError(const Token *tok) const
|
||||||
|
|
||||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||||
Severity::error,
|
Severity::error,
|
||||||
"### Internal error in Cppcheck. Please report it.",
|
"Analysis failed. If the code is valid then please report this failure.",
|
||||||
"cppcheckError");
|
"cppcheckError");
|
||||||
|
|
||||||
if (_errorLogger)
|
if (_errorLogger)
|
||||||
|
@ -9015,7 +9073,7 @@ void Tokenizer::simplifyBitfields()
|
||||||
{
|
{
|
||||||
Token *last = 0;
|
Token *last = 0;
|
||||||
|
|
||||||
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %num% ;|,"))
|
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,"))
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tok->next()->str() == "const")
|
if (tok->next()->str() == "const")
|
||||||
|
@ -9024,7 +9082,7 @@ void Tokenizer::simplifyBitfields()
|
||||||
last = tok->tokAt(5 + offset);
|
last = tok->tokAt(5 + offset);
|
||||||
Token::eraseTokens(tok->tokAt(2 + offset), tok->tokAt(5 + offset));
|
Token::eraseTokens(tok->tokAt(2 + offset), tok->tokAt(5 + offset));
|
||||||
}
|
}
|
||||||
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %num% ;"))
|
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;"))
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tok->next()->str() == "const")
|
if (tok->next()->str() == "const")
|
||||||
|
@ -9179,9 +9237,11 @@ void Tokenizer::simplifyBorland()
|
||||||
// Remove Qt signals and slots
|
// Remove Qt signals and slots
|
||||||
void Tokenizer::simplifyQtSignalsSlots()
|
void Tokenizer::simplifyQtSignalsSlots()
|
||||||
{
|
{
|
||||||
Token *tok = _tokens;
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
while ((tok = const_cast<Token *>(Token::findmatch(tok, "class %var% :"))))
|
|
||||||
{
|
{
|
||||||
|
if (!Token::Match(tok, "class %var% :"))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (tok->previous() && tok->previous()->str() == "enum")
|
if (tok->previous() && tok->previous()->str() == "enum")
|
||||||
{
|
{
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
|
|
|
@ -320,7 +320,7 @@ public:
|
||||||
* utility function for simplifyKnownVariables. Perform simplification
|
* utility function for simplifyKnownVariables. Perform simplification
|
||||||
* of a given variable
|
* of a given variable
|
||||||
*/
|
*/
|
||||||
bool simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, bool pointeralias, int indentlevel);
|
bool simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel);
|
||||||
|
|
||||||
/** Replace a "goto" with the statements */
|
/** Replace a "goto" with the statements */
|
||||||
void simplifyGoto();
|
void simplifyGoto();
|
||||||
|
|
|
@ -135,6 +135,7 @@ private:
|
||||||
TEST_CASE(buffer_overrun_16);
|
TEST_CASE(buffer_overrun_16);
|
||||||
TEST_CASE(buffer_overrun_17); // ticket #2548
|
TEST_CASE(buffer_overrun_17); // ticket #2548
|
||||||
TEST_CASE(buffer_overrun_18); // ticket #2576 - for, calculation with loop variable
|
TEST_CASE(buffer_overrun_18); // ticket #2576 - for, calculation with loop variable
|
||||||
|
TEST_CASE(buffer_overrun_19); // #2597 - class member with unknown type
|
||||||
TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch
|
TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch
|
||||||
|
|
||||||
// It is undefined behaviour to point out of bounds of an array
|
// It is undefined behaviour to point out of bounds of an array
|
||||||
|
@ -1891,6 +1892,20 @@ private:
|
||||||
errout.str());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void buffer_overrun_19() // #2597 - class member with unknown type
|
||||||
|
{
|
||||||
|
check("class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" u8 buf[10];\n"
|
||||||
|
" A();"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"A::A() {\n"
|
||||||
|
" memset(buf, 0, 10);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void buffer_overrun_bailoutIfSwitch()
|
void buffer_overrun_bailoutIfSwitch()
|
||||||
{
|
{
|
||||||
// No false positive
|
// No false positive
|
||||||
|
|
|
@ -113,6 +113,7 @@ private:
|
||||||
TEST_CASE(operatorEqToSelf6); // ticket # 1550
|
TEST_CASE(operatorEqToSelf6); // ticket # 1550
|
||||||
TEST_CASE(operatorEqToSelf7);
|
TEST_CASE(operatorEqToSelf7);
|
||||||
TEST_CASE(operatorEqToSelf8); // ticket #2179
|
TEST_CASE(operatorEqToSelf8); // ticket #2179
|
||||||
|
TEST_CASE(operatorEqToSelf9); // ticket #2592
|
||||||
TEST_CASE(memsetOnStruct);
|
TEST_CASE(memsetOnStruct);
|
||||||
TEST_CASE(memsetVector);
|
TEST_CASE(memsetVector);
|
||||||
TEST_CASE(memsetOnClass);
|
TEST_CASE(memsetOnClass);
|
||||||
|
@ -163,6 +164,7 @@ private:
|
||||||
TEST_CASE(const41); // ticket #2255
|
TEST_CASE(const41); // ticket #2255
|
||||||
TEST_CASE(const42); // ticket #2282
|
TEST_CASE(const42); // ticket #2282
|
||||||
TEST_CASE(const43); // ticket #2377
|
TEST_CASE(const43); // ticket #2377
|
||||||
|
TEST_CASE(const44); // ticket #2595
|
||||||
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
||||||
TEST_CASE(assigningArrayElementIsNotAConstOperation);
|
TEST_CASE(assigningArrayElementIsNotAConstOperation);
|
||||||
TEST_CASE(constoperator1); // operator< can often be const
|
TEST_CASE(constoperator1); // operator< can often be const
|
||||||
|
@ -192,6 +194,7 @@ private:
|
||||||
TEST_CASE(symboldatabase11); // ticket #2539
|
TEST_CASE(symboldatabase11); // ticket #2539
|
||||||
TEST_CASE(symboldatabase12); // ticket #2547
|
TEST_CASE(symboldatabase12); // ticket #2547
|
||||||
TEST_CASE(symboldatabase13); // ticket #2577
|
TEST_CASE(symboldatabase13); // ticket #2577
|
||||||
|
TEST_CASE(symboldatabase14); // ticket #2589
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the operator Equal
|
// Check the operator Equal
|
||||||
|
@ -1298,6 +1301,26 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operatorEqToSelf9()
|
||||||
|
{
|
||||||
|
checkOpertorEqToSelf(
|
||||||
|
"class Foo\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" Foo& operator=(Foo* pOther);\n"
|
||||||
|
" Foo& operator=(Foo& other);\n"
|
||||||
|
"};\n"
|
||||||
|
"Foo& Foo::operator=(Foo* pOther)\n"
|
||||||
|
"{\n"
|
||||||
|
" return *this;\n"
|
||||||
|
"}\n"
|
||||||
|
"Foo& Foo::operator=(Foo& other)\n"
|
||||||
|
"{\n"
|
||||||
|
" return Foo::operator=(&other);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Check that base classes have virtual destructors
|
// Check that base classes have virtual destructors
|
||||||
void checkVirtualDestructor(const char code[])
|
void checkVirtualDestructor(const char code[])
|
||||||
{
|
{
|
||||||
|
@ -4959,6 +4982,21 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void const44() // ticket 2595
|
||||||
|
{
|
||||||
|
checkConst("class A\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" bool bOn;\n"
|
||||||
|
" bool foo()\n"
|
||||||
|
" {\n"
|
||||||
|
" return 0 != (bOn = bOn && true);\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n");
|
||||||
|
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void assigningPointerToPointerIsNotAConstOperation()
|
void assigningPointerToPointerIsNotAConstOperation()
|
||||||
{
|
{
|
||||||
checkConst("struct s\n"
|
checkConst("struct s\n"
|
||||||
|
@ -5550,6 +5588,14 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void symboldatabase14()
|
||||||
|
{
|
||||||
|
// ticket #2589 - segmentation fault
|
||||||
|
checkConst("struct B : A\n");
|
||||||
|
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestClass)
|
REGISTER_TEST(TestClass)
|
||||||
|
|
|
@ -193,13 +193,42 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4\n", errout.str());
|
||||||
|
|
||||||
check("void foo(struct ABC *abc)\n"
|
check("void foo(struct ABC *abc) {\n"
|
||||||
"{\n"
|
|
||||||
" bar(abc->a);\n"
|
" bar(abc->a);\n"
|
||||||
" if (!abc)\n"
|
" if (!abc)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 3\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(ABC *abc) {\n"
|
||||||
|
" abc->do_something();\n"
|
||||||
|
" if (abc)\n"
|
||||||
|
" ;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 3\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(ABC *abc) {\n"
|
||||||
|
" if (abc->a == 3) {\n"
|
||||||
|
" return;\n"
|
||||||
|
" }\n"
|
||||||
|
" if (abc) {}\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 5\n", "", errout.str());
|
||||||
|
|
||||||
|
// TODO: False negative if member of member is dereferenced
|
||||||
|
check("void foo(ABC *abc) {\n"
|
||||||
|
" abc->next->a = 0;\n"
|
||||||
|
" if (abc->next)\n"
|
||||||
|
" ;\n"
|
||||||
|
"}\n");
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 3\n", "", errout.str());
|
||||||
|
|
||||||
|
check("void foo(ABC *abc) {\n"
|
||||||
|
" abc->a = 0;\n"
|
||||||
|
" if (abc && abc->b == 0)\n"
|
||||||
|
" ;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 3\n", errout.str());
|
||||||
|
|
||||||
// ok dereferencing in a condition
|
// ok dereferencing in a condition
|
||||||
check("void foo(struct ABC *abc)\n"
|
check("void foo(struct ABC *abc)\n"
|
||||||
|
@ -718,6 +747,21 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("error",
|
TODO_ASSERT_EQUALS("error",
|
||||||
"", errout.str());
|
"", errout.str());
|
||||||
|
|
||||||
|
// #2231 - error if assignment in loop is not used
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *p = 0;\n"
|
||||||
|
"\n"
|
||||||
|
" for (int x = 0; x < 3; ++x) {\n"
|
||||||
|
" if (y[x] == 0) {\n"
|
||||||
|
" p = malloc(10);\n"
|
||||||
|
" break;\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" *p = 0;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:11]: (error) Possible null pointer dereference: p\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nullpointer7()
|
void nullpointer7()
|
||||||
|
@ -787,6 +831,19 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(char *p) {\n"
|
||||||
|
" if (p && *p == 0) {\n"
|
||||||
|
" }\n"
|
||||||
|
" printf(\"%c\", *p);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(char *p) {\n"
|
||||||
|
" if (p && *p == 0) {\n"
|
||||||
|
" } else { *p = 0; }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p\n", errout.str());
|
||||||
|
|
||||||
check("void foo(abc *p) {\n"
|
check("void foo(abc *p) {\n"
|
||||||
" if (!p) {\n"
|
" if (!p) {\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
|
|
|
@ -119,6 +119,7 @@ private:
|
||||||
TEST_CASE(if_cond9);
|
TEST_CASE(if_cond9);
|
||||||
TEST_CASE(if_cond10);
|
TEST_CASE(if_cond10);
|
||||||
TEST_CASE(if_cond11);
|
TEST_CASE(if_cond11);
|
||||||
|
TEST_CASE(if_cond12);
|
||||||
|
|
||||||
TEST_CASE(if_or_1);
|
TEST_CASE(if_or_1);
|
||||||
TEST_CASE(if_or_2);
|
TEST_CASE(if_or_2);
|
||||||
|
@ -1340,6 +1341,15 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if_cond12()
|
||||||
|
{
|
||||||
|
const char filedata[] = "#define A (1)\n"
|
||||||
|
"#if A == 1\n"
|
||||||
|
";\n"
|
||||||
|
"#endif\n";
|
||||||
|
ASSERT_EQUALS("\n\n;\n\n", Preprocessor::getcode(filedata,"","",NULL,NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void if_or_1()
|
void if_or_1()
|
||||||
|
|
|
@ -110,6 +110,7 @@ private:
|
||||||
TEST_CASE(template19);
|
TEST_CASE(template19);
|
||||||
TEST_CASE(template20);
|
TEST_CASE(template20);
|
||||||
TEST_CASE(template21);
|
TEST_CASE(template21);
|
||||||
|
TEST_CASE(template22);
|
||||||
TEST_CASE(template_unhandled);
|
TEST_CASE(template_unhandled);
|
||||||
TEST_CASE(template_default_parameter);
|
TEST_CASE(template_default_parameter);
|
||||||
TEST_CASE(template_default_type);
|
TEST_CASE(template_default_type);
|
||||||
|
@ -237,6 +238,7 @@ private:
|
||||||
TEST_CASE(simplifyTypedef77); // ticket #2554
|
TEST_CASE(simplifyTypedef77); // ticket #2554
|
||||||
TEST_CASE(simplifyTypedef78); // ticket #2568
|
TEST_CASE(simplifyTypedef78); // ticket #2568
|
||||||
TEST_CASE(simplifyTypedef79); // ticket #2348
|
TEST_CASE(simplifyTypedef79); // ticket #2348
|
||||||
|
TEST_CASE(simplifyTypedef80); // ticket #2587
|
||||||
|
|
||||||
TEST_CASE(simplifyTypedefFunction1);
|
TEST_CASE(simplifyTypedefFunction1);
|
||||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||||
|
@ -1984,6 +1986,19 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template22()
|
||||||
|
{
|
||||||
|
const char code[] = "template <classname T> struct Fred { T a; };\n"
|
||||||
|
"Fred<std::string> fred;";
|
||||||
|
|
||||||
|
const std::string expected("; "
|
||||||
|
"Fred<std::string> fred ; "
|
||||||
|
"struct Fred<std::string> { std :: string a ; }");
|
||||||
|
|
||||||
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void template_unhandled()
|
void template_unhandled()
|
||||||
{
|
{
|
||||||
// An unhandled template usage should be simplified..
|
// An unhandled template usage should be simplified..
|
||||||
|
@ -4876,6 +4891,23 @@ private:
|
||||||
ASSERT_EQUALS(expected, sizeof_(code));
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyTypedef80() // ticket #2587
|
||||||
|
{
|
||||||
|
const char code[] = "typedef struct s { };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" sizeof(struct s);\n"
|
||||||
|
"};\n";
|
||||||
|
const std::string expected = "struct s { } ; "
|
||||||
|
"void f ( ) { "
|
||||||
|
"sizeof ( struct s ) ; "
|
||||||
|
"} ;";
|
||||||
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
|
|
||||||
|
// Check for output..
|
||||||
|
checkSimplifyTypedef(code);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyTypedefFunction1()
|
void simplifyTypedefFunction1()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -5767,11 +5799,7 @@ private:
|
||||||
"}\n";
|
"}\n";
|
||||||
const char expected[] = "int f ( ) "
|
const char expected[] = "int f ( ) "
|
||||||
"{"
|
"{"
|
||||||
" int i ;"
|
" ; return 5 ; "
|
||||||
" int * p ;"
|
|
||||||
" p = & i ;"
|
|
||||||
" i = 5 ;"
|
|
||||||
" return 5 ; "
|
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,35 @@ private:
|
||||||
"");
|
"");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar inline
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" // cppcheck-suppress uninitvar\n"
|
||||||
|
"\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar inline
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" /* cppcheck-suppress uninitvar */\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar inline
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" /* cppcheck-suppress uninitvar */\n"
|
||||||
|
"\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// suppress uninitvar inline, without error present
|
// suppress uninitvar inline, without error present
|
||||||
(this->*check)("void f() {\n"
|
(this->*check)("void f() {\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
|
|
|
@ -127,6 +127,7 @@ private:
|
||||||
TEST_CASE(simplifyKnownVariables38); // ticket #2399 - simplify conditions
|
TEST_CASE(simplifyKnownVariables38); // ticket #2399 - simplify conditions
|
||||||
TEST_CASE(simplifyKnownVariables39);
|
TEST_CASE(simplifyKnownVariables39);
|
||||||
TEST_CASE(simplifyKnownVariables40);
|
TEST_CASE(simplifyKnownVariables40);
|
||||||
|
TEST_CASE(simplifyKnownVariables41); // p=&x; if (p) ..
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutAssign);
|
TEST_CASE(simplifyKnownVariablesBailOutAssign);
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutFor1);
|
TEST_CASE(simplifyKnownVariablesBailOutFor1);
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutFor2);
|
TEST_CASE(simplifyKnownVariablesBailOutFor2);
|
||||||
|
@ -278,6 +279,7 @@ private:
|
||||||
TEST_CASE(bitfields3);
|
TEST_CASE(bitfields3);
|
||||||
TEST_CASE(bitfields4); // ticket #1956
|
TEST_CASE(bitfields4); // ticket #1956
|
||||||
TEST_CASE(bitfields5); // ticket #1956
|
TEST_CASE(bitfields5); // ticket #1956
|
||||||
|
TEST_CASE(bitfields6); // ticket #2595
|
||||||
|
|
||||||
TEST_CASE(microsoftMFC);
|
TEST_CASE(microsoftMFC);
|
||||||
|
|
||||||
|
@ -2020,6 +2022,16 @@ private:
|
||||||
ASSERT_EQUALS("void f ( ) {\n;\nchar c2 ; c2 = { 'a' } ;\n}", tokenizeAndStringify(code, true));
|
ASSERT_EQUALS("void f ( ) {\n;\nchar c2 ; c2 = { 'a' } ;\n}", tokenizeAndStringify(code, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyKnownVariables41()
|
||||||
|
{
|
||||||
|
const char code[] = "void f() {\n"
|
||||||
|
" int x = 0;\n"
|
||||||
|
" const int *p; p = &x;\n"
|
||||||
|
" if (p) { return 0; }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("void f ( ) {\nint x ; x = 0 ;\nconst int * p ; p = & x ;\nif ( & x ) { return 0 ; }\n}", tokenizeAndStringify(code, true));
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyKnownVariablesBailOutAssign()
|
void simplifyKnownVariablesBailOutAssign()
|
||||||
{
|
{
|
||||||
const char code[] = "int foo() {\n"
|
const char code[] = "int foo() {\n"
|
||||||
|
@ -5072,6 +5084,18 @@ private:
|
||||||
ASSERT_EQUALS("struct A { virtual void f ( ) { } int f1 ; } ;", tokenizeAndStringify(code3,false));
|
ASSERT_EQUALS("struct A { virtual void f ( ) { } int f1 ; } ;", tokenizeAndStringify(code3,false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bitfields6() // ticket #2595
|
||||||
|
{
|
||||||
|
const char code1[] = "struct A { bool b : true; };";
|
||||||
|
ASSERT_EQUALS("struct A { bool b ; } ;", tokenizeAndStringify(code1,false));
|
||||||
|
|
||||||
|
const char code2[] = "struct A { bool b : true, c : true; };";
|
||||||
|
ASSERT_EQUALS("struct A { bool b ; bool c ; } ;", tokenizeAndStringify(code2,false));
|
||||||
|
|
||||||
|
const char code3[] = "struct A { bool : true; };";
|
||||||
|
ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3,false));
|
||||||
|
}
|
||||||
|
|
||||||
void microsoftMFC()
|
void microsoftMFC()
|
||||||
{
|
{
|
||||||
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
||||||
|
|
|
@ -801,6 +801,21 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n",
|
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n",
|
||||||
"", errout.str());
|
"", errout.str());
|
||||||
|
|
||||||
|
// #2231 - conditional initialization in loop..
|
||||||
|
checkUninitVar("int foo(char *a) {\n"
|
||||||
|
" int x;\n"
|
||||||
|
"\n"
|
||||||
|
" for (int i = 0; i < 10; ++i) {\n"
|
||||||
|
" if (a[i] == 'x') {\n"
|
||||||
|
" x = i;\n"
|
||||||
|
" break;\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:11]: (error) Uninitialized variable: x\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch..
|
// switch..
|
||||||
|
|
Loading…
Reference in New Issue