Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
a69fbffa76
|
@ -98,7 +98,7 @@ QStringList ProjectFileDialog::GetIncludePaths() const
|
||||||
QListWidgetItem *item = mUI.mListIncludeDirs->item(i);
|
QListWidgetItem *item = mUI.mListIncludeDirs->item(i);
|
||||||
includePaths << QDir::fromNativeSeparators(item->text());
|
includePaths << QDir::fromNativeSeparators(item->text());
|
||||||
}
|
}
|
||||||
return includePaths;
|
return includePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ProjectFileDialog::GetDefines() const
|
QStringList ProjectFileDialog::GetDefines() const
|
||||||
|
|
|
@ -266,7 +266,6 @@ void CheckAutoVariables::returnPointerToLocalArray()
|
||||||
tok2 = tok2->next()->link();
|
tok2 = tok2->next()->link();
|
||||||
|
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
std::set<unsigned int> arrayVar;
|
|
||||||
for (; tok2; tok2 = tok2->next())
|
for (; tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
// indentlevel..
|
// indentlevel..
|
||||||
|
@ -279,21 +278,13 @@ void CheckAutoVariables::returnPointerToLocalArray()
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declaring a local array..
|
|
||||||
if (Token::Match(tok2, "[;{}] %type% %var% ["))
|
|
||||||
{
|
|
||||||
const unsigned int varid = tok2->tokAt(2)->varId();
|
|
||||||
if (varid > 0)
|
|
||||||
{
|
|
||||||
arrayVar.insert(varid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return pointer to local array variable..
|
// Return pointer to local array variable..
|
||||||
if (Token::Match(tok2, "return %var% ;"))
|
if (Token::Match(tok2, "return %var% ;"))
|
||||||
{
|
{
|
||||||
const unsigned int varid = tok2->next()->varId();
|
const unsigned int varid = tok2->next()->varId();
|
||||||
if (varid > 0 && arrayVar.find(varid) != arrayVar.end())
|
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
|
|
||||||
|
if (var && var->isLocal() && !var->isStatic() && var->isArray())
|
||||||
{
|
{
|
||||||
errorReturnPointerToLocalArray(tok2);
|
errorReturnPointerToLocalArray(tok2);
|
||||||
}
|
}
|
||||||
|
@ -361,7 +352,6 @@ void CheckAutoVariables::returnReference()
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
|
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
std::set<unsigned int> localvar; // local variables in function
|
|
||||||
for (; tok2; tok2 = tok2->next())
|
for (; tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
// indentlevel..
|
// indentlevel..
|
||||||
|
@ -374,33 +364,14 @@ void CheckAutoVariables::returnReference()
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// declare local variable..
|
|
||||||
if (Token::Match(tok2, "[{};] %type%") && tok2->next()->str() != "return")
|
|
||||||
{
|
|
||||||
// goto next token..
|
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
// skip "const"
|
|
||||||
if (Token::Match(tok2, "const %type%"))
|
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
// skip "std::" if it is seen
|
|
||||||
if (Token::simpleMatch(tok2, "std ::"))
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
|
|
||||||
// is it a variable declaration?
|
|
||||||
if (Token::Match(tok2, "%type% %var% ;"))
|
|
||||||
localvar.insert(tok2->next()->varId());
|
|
||||||
else if (Token::Match(tok2, "%type% < %any% > %var% ;"))
|
|
||||||
localvar.insert(tok2->tokAt(4)->varId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// return..
|
// return..
|
||||||
else if (Token::Match(tok2, "return %var% ;"))
|
if (Token::Match(tok2, "return %var% ;"))
|
||||||
{
|
{
|
||||||
// is the returned variable a local variable?
|
// is the returned variable a local variable?
|
||||||
if ((tok2->next()->varId() > 0) &&
|
const unsigned int varid = tok2->next()->varId();
|
||||||
(localvar.find(tok2->next()->varId()) != localvar.end()))
|
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
|
|
||||||
|
if (var && var->isLocal() && !var->isStatic())
|
||||||
{
|
{
|
||||||
// report error..
|
// report error..
|
||||||
errorReturnReference(tok2);
|
errorReturnReference(tok2);
|
||||||
|
@ -462,7 +433,6 @@ void CheckAutoVariables::returncstr()
|
||||||
tok2 = tok2->next()->link();
|
tok2 = tok2->next()->link();
|
||||||
|
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
std::set<unsigned int> localvar; // local variables in function
|
|
||||||
for (; tok2; tok2 = tok2->next())
|
for (; tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
// indentlevel..
|
// indentlevel..
|
||||||
|
@ -475,31 +445,14 @@ void CheckAutoVariables::returncstr()
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// declare local variable..
|
|
||||||
if (Token::Match(tok2, "[{};] %type%") && tok2->next()->str() != "return")
|
|
||||||
{
|
|
||||||
// goto next token..
|
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
// skip "const"
|
|
||||||
if (Token::Match(tok2, "const %type%"))
|
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
// skip "std::" if it is seen
|
|
||||||
if (Token::simpleMatch(tok2, "std ::"))
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
|
|
||||||
// is it a variable declaration?
|
|
||||||
if (Token::Match(tok2, "%type% %var% [;=]"))
|
|
||||||
localvar.insert(tok2->next()->varId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// return..
|
// return..
|
||||||
else if (Token::Match(tok2, "return %var% . c_str ( ) ;"))
|
if (Token::Match(tok2, "return %var% . c_str ( ) ;"))
|
||||||
{
|
{
|
||||||
// is the returned variable a local variable?
|
// is the returned variable a local variable?
|
||||||
if ((tok2->next()->varId() > 0) &&
|
const unsigned int varid = tok2->next()->varId();
|
||||||
(localvar.find(tok2->next()->varId()) != localvar.end()))
|
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
|
|
||||||
|
if (var && var->isLocal() && !var->isStatic())
|
||||||
{
|
{
|
||||||
// report error..
|
// report error..
|
||||||
errorReturnAutocstr(tok2);
|
errorReturnAutocstr(tok2);
|
||||||
|
|
|
@ -178,10 +178,6 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename,
|
||||||
// Remove all comments..
|
// Remove all comments..
|
||||||
result = removeComments(result, filename, settings);
|
result = removeComments(result, filename, settings);
|
||||||
|
|
||||||
// Remove '#if 0' blocks
|
|
||||||
if (result.find("#if 0\n") != std::string::npos)
|
|
||||||
result = removeIf0(result);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Clean up all preprocessor statements
|
// Clean up all preprocessor statements
|
||||||
|
@ -192,6 +188,10 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename,
|
||||||
// Clean up preprocessor #if statements with Parantheses
|
// Clean up preprocessor #if statements with Parantheses
|
||||||
result = removeParantheses(result);
|
result = removeParantheses(result);
|
||||||
|
|
||||||
|
// Remove '#if 0' blocks
|
||||||
|
if (result.find("#if 0\n") != std::string::npos)
|
||||||
|
result = removeIf0(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,19 +563,33 @@ std::string Preprocessor::removeIf0(const std::string &code)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// replace '#if 0' with empty line
|
// replace '#if 0' with empty line
|
||||||
ret << "\n";
|
ret << line << "\n";
|
||||||
|
|
||||||
// goto the end of the '#if 0' block
|
// goto the end of the '#if 0' block
|
||||||
unsigned int level = 1;
|
unsigned int level = 1;
|
||||||
|
bool in = false;
|
||||||
while (level > 0 && std::getline(istr,line))
|
while (level > 0 && std::getline(istr,line))
|
||||||
{
|
{
|
||||||
if (line.compare(0,3,"#if") == 0)
|
if (line.compare(0,3,"#if") == 0)
|
||||||
++level;
|
++level;
|
||||||
else if (line == "#endif")
|
else if (line == "#endif")
|
||||||
--level;
|
--level;
|
||||||
|
else if (line == "#else")
|
||||||
|
{
|
||||||
|
if (level == 1)
|
||||||
|
in = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (in)
|
||||||
|
ret << line << "\n";
|
||||||
|
else
|
||||||
|
// replace code within '#if 0' block with empty lines
|
||||||
|
ret << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// replace code within '#if 0' block with empty lines
|
ret << line << "\n";
|
||||||
ret << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,22 +623,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scope = *it;
|
scope = *it;
|
||||||
|
|
||||||
if (scope->isClassOrStruct() && scope->needInitialization == Scope::Unknown)
|
if (scope->isClassOrStruct() && scope->needInitialization == Scope::Unknown)
|
||||||
{
|
debugMessage(scope->classDef, "SymbolDatabase::SymbolDatabase couldn't resolve all user defined types.");
|
||||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
|
||||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
|
||||||
loc.line = scope->classDef->linenr();
|
|
||||||
loc.setfile(_tokenizer->file(scope->classDef));
|
|
||||||
locationList.push_back(loc);
|
|
||||||
|
|
||||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
|
||||||
Severity::debug,
|
|
||||||
"SymbolDatabase::SymbolDatabase couldn't resolve all user defined types.",
|
|
||||||
"debug");
|
|
||||||
if (_errorLogger)
|
|
||||||
_errorLogger->reportErr(errmsg);
|
|
||||||
else
|
|
||||||
Check::reportError(errmsg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,6 +1063,27 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok)
|
||||||
return tok2;
|
return tok2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) const
|
||||||
|
{
|
||||||
|
if (tok && _settings->debugwarnings)
|
||||||
|
{
|
||||||
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||||
|
loc.line = tok->linenr();
|
||||||
|
loc.setfile(_tokenizer->file(tok));
|
||||||
|
locationList.push_back(loc);
|
||||||
|
|
||||||
|
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||||
|
Severity::debug,
|
||||||
|
msg,
|
||||||
|
"debug");
|
||||||
|
if (_errorLogger)
|
||||||
|
_errorLogger->reportErr(errmsg);
|
||||||
|
else
|
||||||
|
Check::reportError(errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
unsigned int Function::argCount() const
|
unsigned int Function::argCount() const
|
||||||
|
@ -1124,6 +1130,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
const Token *endTok;
|
const Token *endTok;
|
||||||
const Token *nameTok;
|
const Token *nameTok;
|
||||||
bool isConstVar;
|
bool isConstVar;
|
||||||
|
bool isArrayVar;
|
||||||
const Token *tok = arg->next();
|
const Token *tok = arg->next();
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -1131,6 +1138,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
endTok = NULL;
|
endTok = NULL;
|
||||||
nameTok = NULL;
|
nameTok = NULL;
|
||||||
isConstVar = bool(tok->str() == "const");
|
isConstVar = bool(tok->str() == "const");
|
||||||
|
isArrayVar = false;
|
||||||
|
|
||||||
while (tok->str() != "," && tok->str() != ")")
|
while (tok->str() != "," && tok->str() != ")")
|
||||||
{
|
{
|
||||||
|
@ -1139,12 +1147,28 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
nameTok = tok;
|
nameTok = tok;
|
||||||
endTok = tok->previous();
|
endTok = tok->previous();
|
||||||
}
|
}
|
||||||
|
else if (tok->str() == "[")
|
||||||
|
isArrayVar = true;
|
||||||
|
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for argument with no name
|
// check for argument with no name or missing varid
|
||||||
if (!endTok)
|
if (!endTok)
|
||||||
endTok = tok->previous();
|
{
|
||||||
|
if (tok->previous()->isName())
|
||||||
|
{
|
||||||
|
if (tok->previous() != startTok->tokAt(isConstVar ? 1 : 0))
|
||||||
|
{
|
||||||
|
nameTok = tok->previous();
|
||||||
|
endTok = nameTok->previous();
|
||||||
|
|
||||||
|
symbolDatabase->debugMessage(nameTok, "Function::addArguments found argument \'" + nameTok->str() + "\' with varid 0.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
endTok = tok->previous();
|
||||||
|
}
|
||||||
|
|
||||||
const Token *typeTok = startTok;
|
const Token *typeTok = startTok;
|
||||||
if (isConstVar)
|
if (isConstVar)
|
||||||
|
@ -1156,7 +1180,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
|
|
||||||
bool isClassVar = startTok == endTok && !startTok->isStandardType();
|
bool isClassVar = startTok == endTok && !startTok->isStandardType();
|
||||||
|
|
||||||
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, false));
|
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, isArrayVar));
|
||||||
|
|
||||||
if (tok->str() == ")")
|
if (tok->str() == ")")
|
||||||
break;
|
break;
|
||||||
|
@ -1429,23 +1453,8 @@ void Scope::getVariableList()
|
||||||
// If the vartok was set in the if-blocks above, create a entry for this variable..
|
// If the vartok was set in the if-blocks above, create a entry for this variable..
|
||||||
if (vartok && vartok->str() != "operator")
|
if (vartok && vartok->str() != "operator")
|
||||||
{
|
{
|
||||||
if (vartok->varId() == 0 && !vartok->isBoolean() && check->_settings->debugwarnings)
|
if (vartok->varId() == 0 && !vartok->isBoolean())
|
||||||
{
|
check->debugMessage(vartok, "Scope::getVariableList found variable \'" + vartok->str() + "\' with varid 0.");
|
||||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
|
||||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
|
||||||
loc.line = vartok->linenr();
|
|
||||||
loc.setfile(check->_tokenizer->file(vartok));
|
|
||||||
locationList.push_back(loc);
|
|
||||||
|
|
||||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
|
||||||
Severity::debug,
|
|
||||||
"Scope::getVariableList found variable \'" + vartok->str() + "\' with varid 0.",
|
|
||||||
"debug");
|
|
||||||
if (check->_errorLogger)
|
|
||||||
check->_errorLogger->reportErr(errmsg);
|
|
||||||
else
|
|
||||||
Check::reportError(errmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Scope *scope = NULL;
|
const Scope *scope = NULL;
|
||||||
|
|
||||||
|
|
|
@ -500,6 +500,11 @@ public:
|
||||||
return _variableList[varId];
|
return _variableList[varId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief output a debug message
|
||||||
|
*/
|
||||||
|
void debugMessage(const Token *tok, const std::string &msg) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Needed by Borland C++:
|
// Needed by Borland C++:
|
||||||
|
|
|
@ -1790,6 +1790,7 @@ void Tokenizer::simplifyTypedef()
|
||||||
{
|
{
|
||||||
if (!inCast && !inSizeof)
|
if (!inCast && !inSizeof)
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
|
|
||||||
tok2 = copyTokens(tok2, arrayStart, arrayEnd);
|
tok2 = copyTokens(tok2, arrayStart, arrayEnd);
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
|
|
||||||
|
@ -4600,9 +4601,6 @@ void Tokenizer::simplifyIfAddBraces()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->previous() && !Token::Match(tok->previous(), ";|{|}|else|)|:"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Token::Match(tok, "if|for|while ("))
|
if (Token::Match(tok, "if|for|while ("))
|
||||||
{
|
{
|
||||||
// don't add "{}" around ";" in "do {} while();" (#609)
|
// don't add "{}" around ";" in "do {} while();" (#609)
|
||||||
|
@ -6639,6 +6637,12 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)|;").c_str(), varid) ||
|
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)|;").c_str(), varid) ||
|
||||||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
||||||
{
|
{
|
||||||
|
if (value[0] == '\"' && tok3->strAt(-1) != "strlen")
|
||||||
|
{
|
||||||
|
// bail out if value is a string unless if it's just given
|
||||||
|
// as parameter to strlen
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!structname.empty())
|
if (!structname.empty())
|
||||||
{
|
{
|
||||||
tok3->deleteNext();
|
tok3->deleteNext();
|
||||||
|
@ -6737,6 +6741,8 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
Token::Match(tok3, ("<<|>> " + structname + " %varid% [+-*/%^|;])]").c_str(), varid) ||
|
Token::Match(tok3, ("<<|>> " + structname + " %varid% [+-*/%^|;])]").c_str(), varid) ||
|
||||||
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid))
|
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid))
|
||||||
{
|
{
|
||||||
|
if (value[0] == '\"')
|
||||||
|
break;
|
||||||
if (!structname.empty())
|
if (!structname.empty())
|
||||||
{
|
{
|
||||||
tok3->deleteNext();
|
tok3->deleteNext();
|
||||||
|
@ -6853,13 +6859,14 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
|
|
||||||
// return variable..
|
// return variable..
|
||||||
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
||||||
isOp(tok3->tokAt(2)))
|
isOp(tok3->tokAt(2)) &&
|
||||||
|
value[0] != '\"')
|
||||||
{
|
{
|
||||||
tok3->next()->str(value);
|
tok3->next()->str(value);
|
||||||
tok3->next()->varId(valueVarId);
|
tok3->next()->varId(valueVarId);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid))
|
else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid) && value[0] != '\"')
|
||||||
{
|
{
|
||||||
tok3->deleteNext();
|
tok3->deleteNext();
|
||||||
tok3->next()->str(value);
|
tok3->next()->str(value);
|
||||||
|
@ -9124,7 +9131,8 @@ void Tokenizer::simplifyBitfields()
|
||||||
{
|
{
|
||||||
Token *last = 0;
|
Token *last = 0;
|
||||||
|
|
||||||
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,"))
|
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,") &&
|
||||||
|
tok->next()->str() != "case")
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tok->next()->str() == "const")
|
if (tok->next()->str() == "const")
|
||||||
|
@ -9133,7 +9141,8 @@ 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% : %any% ;"))
|
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;") &&
|
||||||
|
tok->next()->str() != "default")
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tok->next()->str() == "const")
|
if (tok->next()->str() == "const")
|
||||||
|
@ -9349,26 +9358,56 @@ const SymbolDatabase *Tokenizer::getSymbolDatabase() const
|
||||||
|
|
||||||
void Tokenizer::simplifyOperatorName()
|
void Tokenizer::simplifyOperatorName()
|
||||||
{
|
{
|
||||||
for (const Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (Token::Match(tok, ") const| {|;|="))
|
if (tok->str() == "operator")
|
||||||
{
|
{
|
||||||
Token *tok1 = tok->link();
|
// operator op
|
||||||
Token *tok2 = tok1;
|
std::string op;
|
||||||
|
Token *par = tok->next();
|
||||||
tok1 = tok1->previous();
|
bool done = false;
|
||||||
while (tok1 && !Token::Match(tok1, "operator|{|}|;|public:|private|protected:"))
|
while (!done && par)
|
||||||
{
|
{
|
||||||
tok1 = tok1->previous();
|
done = true;
|
||||||
|
if (par && par->isName())
|
||||||
|
{
|
||||||
|
op += par->str();
|
||||||
|
par = par->next();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (Token::Match(par, "[<>+-*&/=.]") || Token::Match(par, "==|!=|<=|>="))
|
||||||
|
{
|
||||||
|
op += par->str();
|
||||||
|
par = par->next();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (Token::simpleMatch(par, "[ ]"))
|
||||||
|
{
|
||||||
|
op += "[]";
|
||||||
|
par = par->next()->next();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (Token::Match(par, "( *| )"))
|
||||||
|
{
|
||||||
|
// break out and simplify..
|
||||||
|
if (Token::Match(par, "( ) const| [=;{),]"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
while (par->str() != ")")
|
||||||
|
{
|
||||||
|
op += par->str();
|
||||||
|
par = par->next();
|
||||||
|
}
|
||||||
|
op += ")";
|
||||||
|
par = par->next();
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok1 && tok1->str() == "operator")
|
if (par && Token::Match(par->link(), ") const| [=;{),]"))
|
||||||
{
|
{
|
||||||
while (tok1->next() != tok2)
|
tok->str("operator" + op);
|
||||||
{
|
Token::eraseTokens(tok,par);
|
||||||
tok1->str(tok1->str() + tok1->next()->str());
|
|
||||||
tok1->deleteNext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ private:
|
||||||
" EventPtr event = *eventP;\n"
|
" EventPtr event = *eventP;\n"
|
||||||
" *actionsP = &event->actions;\n"
|
" *actionsP = &event->actions;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
TODO_ASSERT_EQUALS("", "[test.cpp:1]: (debug) Function::addArguments found argument 'eventP' with varid 0.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void returnLocalVariable1()
|
void returnLocalVariable1()
|
||||||
|
|
|
@ -92,6 +92,11 @@ private:
|
||||||
|
|
||||||
TEST_CASE(error3);
|
TEST_CASE(error3);
|
||||||
|
|
||||||
|
TEST_CASE(if0_exclude);
|
||||||
|
TEST_CASE(if0_whitespace);
|
||||||
|
TEST_CASE(if0_else);
|
||||||
|
TEST_CASE(if0_elif);
|
||||||
|
|
||||||
// Don't handle include in a #if 0 block
|
// Don't handle include in a #if 0 block
|
||||||
TEST_CASE(if0_include_1);
|
TEST_CASE(if0_include_1);
|
||||||
TEST_CASE(if0_include_2);
|
TEST_CASE(if0_include_2);
|
||||||
|
@ -641,6 +646,74 @@ private:
|
||||||
ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout.str());
|
ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if0_exclude()
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
|
||||||
|
std::istringstream code("#if 0\n"
|
||||||
|
"A\n"
|
||||||
|
"#endif\n"
|
||||||
|
"B\n");
|
||||||
|
ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code,"",NULL));
|
||||||
|
|
||||||
|
std::istringstream code2("#if (0)\n"
|
||||||
|
"A\n"
|
||||||
|
"#endif\n"
|
||||||
|
"B\n");
|
||||||
|
ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code2,"",NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void if0_whitespace()
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
|
||||||
|
std::istringstream code(" # if 0 \n"
|
||||||
|
"A\n"
|
||||||
|
" # endif \n"
|
||||||
|
"B\n");
|
||||||
|
ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code,"",NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void if0_else()
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
|
||||||
|
std::istringstream code("#if 0\n"
|
||||||
|
"A\n"
|
||||||
|
"#else\n"
|
||||||
|
"B\n"
|
||||||
|
"#endif\n"
|
||||||
|
"C\n");
|
||||||
|
ASSERT_EQUALS("#if 0\n\n#else\nB\n#endif\nC\n", preprocessor.read(code,"",NULL));
|
||||||
|
|
||||||
|
std::istringstream code2("#if 1\n"
|
||||||
|
"A\n"
|
||||||
|
"#else\n"
|
||||||
|
"B\n"
|
||||||
|
"#endif\n"
|
||||||
|
"C\n");
|
||||||
|
TODO_ASSERT_EQUALS("#if 1\nA\n#else\n\n#endif\nC\n",
|
||||||
|
"#if 1\nA\n#else\nB\n#endif\nC\n", preprocessor.read(code2,"",NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void if0_elif()
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
|
||||||
|
std::istringstream code("#if 0\n"
|
||||||
|
"A\n"
|
||||||
|
"#elif 1\n"
|
||||||
|
"B\n"
|
||||||
|
"#endif\n"
|
||||||
|
"C\n");
|
||||||
|
TODO_ASSERT_EQUALS("#if 0\n\n#elif 1\nB\n#endif\nC\n",
|
||||||
|
"#if 0\n\n\n\n#endif\nC\n", preprocessor.read(code,"",NULL));
|
||||||
|
}
|
||||||
|
|
||||||
void if0_include_1()
|
void if0_include_1()
|
||||||
{
|
{
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
@ -650,7 +723,7 @@ private:
|
||||||
"#include \"a.h\"\n"
|
"#include \"a.h\"\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"AB\n");
|
"AB\n");
|
||||||
ASSERT_EQUALS("\n\n\nAB\n", preprocessor.read(code,"",NULL));
|
ASSERT_EQUALS("#if 0\n\n#endif\nAB\n", preprocessor.read(code,"",NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
void if0_include_2()
|
void if0_include_2()
|
||||||
|
@ -665,7 +738,7 @@ private:
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"AB\n");
|
"AB\n");
|
||||||
ASSERT_EQUALS("\n\n\n\n\n\nAB\n", preprocessor.read(code,"",NULL));
|
ASSERT_EQUALS("#if 0\n\n#ifdef WIN32\n#else\n#endif\n#endif\nAB\n", preprocessor.read(code,"",NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
void includeguard1()
|
void includeguard1()
|
||||||
|
|
|
@ -80,6 +80,7 @@ private:
|
||||||
TEST_CASE(ifAddBraces12);
|
TEST_CASE(ifAddBraces12);
|
||||||
TEST_CASE(ifAddBraces13);
|
TEST_CASE(ifAddBraces13);
|
||||||
TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{}
|
TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{}
|
||||||
|
TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if
|
||||||
|
|
||||||
TEST_CASE(whileAddBraces);
|
TEST_CASE(whileAddBraces);
|
||||||
TEST_CASE(doWhileAddBraces);
|
TEST_CASE(doWhileAddBraces);
|
||||||
|
@ -305,7 +306,10 @@ private:
|
||||||
// Tokenize JAVA
|
// Tokenize JAVA
|
||||||
TEST_CASE(java);
|
TEST_CASE(java);
|
||||||
|
|
||||||
TEST_CASE(simplifyOperatorName);
|
TEST_CASE(simplifyOperatorName1);
|
||||||
|
TEST_CASE(simplifyOperatorName2);
|
||||||
|
TEST_CASE(simplifyOperatorName3);
|
||||||
|
TEST_CASE(simplifyOperatorName4);
|
||||||
|
|
||||||
// Some simple cleanups of unhandled macros in the global scope
|
// Some simple cleanups of unhandled macros in the global scope
|
||||||
TEST_CASE(removeMacrosInGlobalScope);
|
TEST_CASE(removeMacrosInGlobalScope);
|
||||||
|
@ -858,6 +862,12 @@ private:
|
||||||
tokenizeAndStringify("if()<{}", false);
|
tokenizeAndStringify("if()<{}", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ifAddBraces15()
|
||||||
|
{
|
||||||
|
// ticket #2616 - unknown macro before if
|
||||||
|
ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void whileAddBraces()
|
void whileAddBraces()
|
||||||
{
|
{
|
||||||
|
@ -2043,17 +2053,45 @@ private:
|
||||||
|
|
||||||
void simplifyKnownVariables42()
|
void simplifyKnownVariables42()
|
||||||
{
|
{
|
||||||
const char code[] = "void f() {\n"
|
{
|
||||||
" char str1[10], str2[10];\n"
|
const char code[] = "void f() {\n"
|
||||||
" strcpy(str1, \"abc\");\n"
|
" char str1[10], str2[10];\n"
|
||||||
" strcpy(str2, str1);\n"
|
" strcpy(str1, \"abc\");\n"
|
||||||
"}";
|
" strcpy(str2, str1);\n"
|
||||||
const char expected[] = "void f ( ) {\n"
|
|
||||||
"char str1 [ 10 ] ; char str2 [ 10 ] ;\n"
|
|
||||||
"strcpy ( str1 , \"abc\" ) ;\n"
|
|
||||||
"strcpy ( str2 , \"abc\" ) ;\n"
|
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
const char expected[] = "void f ( ) {\n"
|
||||||
|
"char str1 [ 10 ] ; char str2 [ 10 ] ;\n"
|
||||||
|
"strcpy ( str1 , \"abc\" ) ;\n"
|
||||||
|
"strcpy ( str2 , \"abc\" ) ;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "void f() {"
|
||||||
|
" char *s = malloc(10);"
|
||||||
|
" strcpy(s, \"\");"
|
||||||
|
" free(s);"
|
||||||
|
"}";
|
||||||
|
const char expected[] = "void f ( ) {"
|
||||||
|
" char * s ; s = malloc ( 10 ) ;"
|
||||||
|
" strcpy ( s , \"\" ) ;"
|
||||||
|
" free ( s ) ; "
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "void f(char *p, char *q) {"
|
||||||
|
" strcpy(p, \"abc\");"
|
||||||
|
" q = p;"
|
||||||
|
"}";
|
||||||
|
const char expected[] = "void f ( char * p , char * q ) {"
|
||||||
|
" strcpy ( p , \"abc\" ) ;"
|
||||||
|
" q = p ; "
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyKnownVariablesBailOutAssign()
|
void simplifyKnownVariablesBailOutAssign()
|
||||||
|
@ -5118,6 +5156,12 @@ private:
|
||||||
|
|
||||||
const char code3[] = "struct A { bool : true; };";
|
const char code3[] = "struct A { bool : true; };";
|
||||||
ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3,false));
|
ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3,false));
|
||||||
|
|
||||||
|
const char code4[] = "void f(int a) { switch (a) { case b: break; } }";
|
||||||
|
ASSERT_EQUALS("void f ( int a ) { switch ( a ) { case b : ; break ; } }", tokenizeAndStringify(code4,true));
|
||||||
|
|
||||||
|
const char code5[] = "void f(int a) { switch (a) { default: break; } }";
|
||||||
|
ASSERT_EQUALS("void f ( int a ) { switch ( a ) { default : ; break ; } }", tokenizeAndStringify(code5,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void microsoftMFC()
|
void microsoftMFC()
|
||||||
|
@ -5312,36 +5356,56 @@ private:
|
||||||
ASSERT_EQUALS("void f ( ) { }", javatest("void f() throws Exception { }"));
|
ASSERT_EQUALS("void f ( ) { }", javatest("void f() throws Exception { }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyOperatorName()
|
void simplifyOperatorName1()
|
||||||
{
|
{
|
||||||
// make sure C code doesn't get changed
|
// make sure C code doesn't get changed
|
||||||
const char code1[] = "void operator () {}"
|
const char code[] = "void operator () {}"
|
||||||
"int main()"
|
"int main()"
|
||||||
"{"
|
"{"
|
||||||
" operator();"
|
" operator();"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const char result1 [] = "void operator ( ) { } "
|
const char result [] = "void operator ( ) { } "
|
||||||
"int main ( ) "
|
"int main ( ) "
|
||||||
"{ "
|
"{ "
|
||||||
"operator ( ) ; "
|
"operator ( ) ; "
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false));
|
ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
|
||||||
|
}
|
||||||
|
|
||||||
const char code2[] = "class Fred"
|
void simplifyOperatorName2()
|
||||||
"{"
|
{
|
||||||
" Fred(const Fred & f) { operator = (f); }"
|
const char code[] = "class Fred"
|
||||||
" operator = ();"
|
"{"
|
||||||
"}";
|
" Fred(const Fred & f) { operator = (f); }"
|
||||||
|
" operator = ();"
|
||||||
|
"}";
|
||||||
|
|
||||||
const char result2 [] = "class Fred "
|
const char result [] = "class Fred "
|
||||||
"{ "
|
"{ "
|
||||||
"Fred ( const Fred & f ) { operator= ( f ) ; } "
|
"Fred ( const Fred & f ) { operator= ( f ) ; } "
|
||||||
"operator= ( ) ; "
|
"operator= ( ) ; "
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false));
|
ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyOperatorName3()
|
||||||
|
{
|
||||||
|
// #2615
|
||||||
|
const char code[] = "void f() {"
|
||||||
|
"static_cast<ScToken*>(xResult.operator->())->GetMatrix();"
|
||||||
|
"}";
|
||||||
|
const char result[] = "void f ( ) { static_cast < ScToken * > ( xResult . operator. ( ) ) . GetMatrix ( ) ; }";
|
||||||
|
ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyOperatorName4()
|
||||||
|
{
|
||||||
|
const char code[] = "void operator==() { }";
|
||||||
|
const char result[] = "void operator== ( ) { }";
|
||||||
|
ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeMacrosInGlobalScope()
|
void removeMacrosInGlobalScope()
|
||||||
|
|
Loading…
Reference in New Issue