Tokenizer::simplifyKnownVariables: Broke out the simplification into a separate function
This commit is contained in:
parent
eddbfbee1e
commit
951a81d0d2
794
lib/tokenize.cpp
794
lib/tokenize.cpp
|
@ -6297,399 +6297,7 @@ bool Tokenizer::simplifyKnownVariables()
|
|||
|
||||
tok3 = tok2->next();
|
||||
}
|
||||
Token* bailOutFromLoop = 0;
|
||||
int indentlevel3 = indentlevel; // indentlevel for tok3
|
||||
bool ret3 = false;
|
||||
for (; tok3; tok3 = tok3->next())
|
||||
{
|
||||
if (tok3->str() == "{")
|
||||
{
|
||||
++indentlevel3;
|
||||
}
|
||||
else if (tok3->str() == "}")
|
||||
{
|
||||
--indentlevel3;
|
||||
if (indentlevel3 < indentlevel)
|
||||
{
|
||||
if (Token::Match(tok2->tokAt(-7), "%type% * %var% ; %var% = & %var% ;") &&
|
||||
tok2->tokAt(-5)->str() == tok2->tokAt(-3)->str())
|
||||
{
|
||||
tok2 = tok2->tokAt(-4);
|
||||
Token::eraseTokens(tok2, tok2->tokAt(5));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if label is found
|
||||
if (Token::Match(tok3, "; %type% : ;"))
|
||||
break;
|
||||
|
||||
// Stop if return or break is found ..
|
||||
if (tok3->str() == "break")
|
||||
break;
|
||||
if ((indentlevel3 > 1 || !Token::simpleMatch(Token::findmatch(tok3,";"), "; }")) && tok3->str() == "return")
|
||||
ret3 = true;
|
||||
if (ret3 && tok3->str() == ";")
|
||||
break;
|
||||
|
||||
if (pointeralias && Token::Match(tok3, ("!!= " + value).c_str()))
|
||||
break;
|
||||
|
||||
// Stop if do is found
|
||||
if (tok3->str() == "do")
|
||||
break;
|
||||
|
||||
// Stop if something like 'while (--var)' is found
|
||||
if (tok3->str() == "for" || tok3->str() == "while" || tok3->str() == "do")
|
||||
{
|
||||
const Token *endpar = tok3->next()->link();
|
||||
if (Token::simpleMatch(endpar, ") {"))
|
||||
endpar = endpar->next()->link();
|
||||
bool bailout = false;
|
||||
for (const Token *tok4 = tok3; tok4 && tok4 != endpar; tok4 = tok4->next())
|
||||
{
|
||||
if (Token::Match(tok4, "++|-- %varid%", varid) ||
|
||||
Token::Match(tok4, "%varid% ++|--|=", varid))
|
||||
{
|
||||
bailout = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bailout)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bailOutFromLoop)
|
||||
{
|
||||
// This could be a loop, skip it, but only if it doesn't contain
|
||||
// the variable we are checking for. If it contains the variable
|
||||
// we will bail out.
|
||||
if (tok3->varId() == varid)
|
||||
{
|
||||
// Continue
|
||||
//tok2 = bailOutFromLoop;
|
||||
break;
|
||||
}
|
||||
else if (tok3 == bailOutFromLoop)
|
||||
{
|
||||
// We have skipped the loop
|
||||
bailOutFromLoop = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (tok3->str() == "{" && tok3->previous()->str() == ")")
|
||||
{
|
||||
// There is a possible loop after the assignment. Try to skip it.
|
||||
if (tok3->previous()->link() &&
|
||||
!Token::simpleMatch(tok3->previous()->link()->previous(), "if"))
|
||||
bailOutFromLoop = tok3->link();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Variable used in realloc (see Ticket #1649)
|
||||
if (Token::Match(tok3, "%var% = realloc ( %var% ,") &&
|
||||
tok3->varId() == varid &&
|
||||
tok3->tokAt(4)->varId() == varid)
|
||||
{
|
||||
tok3->tokAt(4)->str(value);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// condition "(|&&|%OROR% %varid% )|&&|%OROR%
|
||||
if (!Token::Match(tok3->previous(), "( %var% )") &&
|
||||
(Token::Match(tok3->previous(), "&&|(") || tok3->strAt(-1) == "||") &&
|
||||
tok3->varId() == varid &&
|
||||
(Token::Match(tok3->next(), "&&|)") || tok3->strAt(1) == "||"))
|
||||
{
|
||||
tok3->str(value);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used somehow in a non-defined pattern => bail out
|
||||
if (tok3->varId() == varid)
|
||||
{
|
||||
// This is a really generic bailout so let's try to avoid this.
|
||||
// There might be lots of false negatives.
|
||||
if (_settings->debugwarnings)
|
||||
{
|
||||
// FIXME: Fix all the debug warnings for values and then
|
||||
// remove this bailout
|
||||
if (pointeralias)
|
||||
break;
|
||||
|
||||
// suppress debug-warning when calling member function
|
||||
if (Token::Match(tok3->next(), ". %var% ("))
|
||||
break;
|
||||
|
||||
// suppress debug-warning when assignment
|
||||
if (Token::simpleMatch(tok3->next(), "="))
|
||||
break;
|
||||
|
||||
// taking address of variable..
|
||||
if (Token::Match(tok3->tokAt(-2), "return|= & %var% ;"))
|
||||
break;
|
||||
|
||||
// parameter in function call..
|
||||
if (Token::Match(tok3->tokAt(-2), "%var% ( %var% ,|)") ||
|
||||
Token::Match(tok3->previous(), ", %var% ,|)"))
|
||||
break;
|
||||
|
||||
// conditional increment
|
||||
if (Token::Match(tok3->tokAt(-3), ") { ++|--") ||
|
||||
Token::Match(tok3->tokAt(-2), ") { %var% ++|--"))
|
||||
break;
|
||||
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||
loc.line = tok3->linenr();
|
||||
loc.setfile(file(tok3));
|
||||
locationList.push_back(loc);
|
||||
|
||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||
Severity::debug,
|
||||
"simplifyKnownVariables: bailing out (variable="+tok3->str()+", value="+value+")",
|
||||
"debug");
|
||||
|
||||
if (_errorLogger)
|
||||
_errorLogger->reportErr(errmsg);
|
||||
else
|
||||
Check::reportError(errmsg);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Using the variable in condition..
|
||||
if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
||||
Token::Match(tok3, ("( " + structname + " %varid% ==|!=|<|<=|>|>=").c_str(), varid) ||
|
||||
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
||||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Delete pointer alias
|
||||
if (pointeralias && tok3->str() == "delete" &&
|
||||
(Token::Match(tok3, "delete %varid% ;", varid) ||
|
||||
Token::Match(tok3, "delete [ ] %varid%", varid)))
|
||||
{
|
||||
tok3 = (tok3->strAt(1) == "[") ? tok3->tokAt(3) : tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used in function call..
|
||||
if (Token::Match(tok3, ("%var% ( " + structname + " %varid% ,").c_str(), varid))
|
||||
{
|
||||
const char * const functionName[] =
|
||||
{
|
||||
"memcmp","memcpy","memmove","memset",
|
||||
"strcmp","strcpy","strncpy","strdup"
|
||||
};
|
||||
for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i)
|
||||
{
|
||||
if (tok3->str() == functionName[i])
|
||||
{
|
||||
Token *par1 = tok3->next()->next();
|
||||
if (!structname.empty())
|
||||
{
|
||||
par1->deleteThis();
|
||||
par1->deleteThis();
|
||||
}
|
||||
par1->str(value);
|
||||
par1->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variable is used as 2nd parameter in function call..
|
||||
if (Token::Match(tok3, ("%var% ( %any% , " + structname + " %varid% ,|)").c_str(), varid))
|
||||
{
|
||||
const char * const functionName[] =
|
||||
{
|
||||
"memcmp","memcpy","memmove",
|
||||
"strcmp","strcpy","strncmp","strncpy"
|
||||
};
|
||||
for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i)
|
||||
{
|
||||
if (tok3->str() == functionName[i])
|
||||
{
|
||||
Token *par = tok3->tokAt(4);
|
||||
if (!structname.empty())
|
||||
{
|
||||
par->deleteThis();
|
||||
par->deleteThis();
|
||||
}
|
||||
par->str(value);
|
||||
par->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// array usage
|
||||
if (Token::Match(tok3, ("[(,] " + structname + " %varid% [+-*/[]").c_str(), varid))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used in calculation..
|
||||
if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
|
||||
Token::Match(tok3, ("[=+-*/[] " + structname + " %varid% [=?+-*/;])]").c_str(), varid) ||
|
||||
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))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
if (tok3->previous()->str() == "*" && valueIsPointer)
|
||||
{
|
||||
tok3 = tok3->previous();
|
||||
tok3->deleteThis();
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(tok3, "= {"))
|
||||
{
|
||||
unsigned int indentlevel4 = 0;
|
||||
for (const Token *tok4 = tok3; tok4; tok4 = tok4->next())
|
||||
{
|
||||
if (tok4->str() == "{")
|
||||
++indentlevel4;
|
||||
else if (tok4->str() == "}")
|
||||
{
|
||||
if (indentlevel4 <= 1)
|
||||
break;
|
||||
--indentlevel4;
|
||||
}
|
||||
if (Token::Match(tok4, "{|, %varid% ,|}", varid))
|
||||
{
|
||||
tok4->next()->str(value);
|
||||
tok4->next()->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Using the variable in for-condition..
|
||||
if (Token::simpleMatch(tok3, "for ("))
|
||||
{
|
||||
for (Token *tok4 = tok3->tokAt(2); tok4; tok4 = tok4->next())
|
||||
{
|
||||
if (tok4->str() == "(" || tok4->str() == ")")
|
||||
break;
|
||||
|
||||
// Replace variable used in condition..
|
||||
if (Token::Match(tok4, "; %var% <|<=|!= %var% ; ++| %var% ++| )"))
|
||||
{
|
||||
const Token *inctok = tok4->tokAt(5);
|
||||
if (inctok->str() == "++")
|
||||
inctok = inctok->next();
|
||||
if (inctok->varId() == varid)
|
||||
break;
|
||||
|
||||
if (tok4->next()->varId() == varid)
|
||||
{
|
||||
tok4->next()->str(value);
|
||||
tok4->next()->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
if (tok4->tokAt(3)->varId() == varid)
|
||||
{
|
||||
tok4->tokAt(3)->str(value);
|
||||
tok4->tokAt(3)->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indentlevel == indentlevel3 && Token::Match(tok3->next(), "%varid% ++|--", varid) && MathLib::isInt(value))
|
||||
{
|
||||
const std::string op(tok3->strAt(2));
|
||||
if (Token::Match(tok3, "[{};] %any% %any% ;"))
|
||||
{
|
||||
Token::eraseTokens(tok3, tok3->tokAt(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
tok3->deleteNext();
|
||||
}
|
||||
incdec(value, op);
|
||||
if (!Token::simpleMatch(tok2->tokAt(-2), "for ("))
|
||||
{
|
||||
tok2->tokAt(2)->str(value);
|
||||
tok2->tokAt(2)->varId(valueVarId);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (indentlevel == indentlevel3 && Token::Match(tok3->next(), "++|-- %varid%", varid) && MathLib::isInt(value) &&
|
||||
!Token::Match(tok3->tokAt(3), "[.[]"))
|
||||
{
|
||||
incdec(value, tok3->strAt(1));
|
||||
tok2->tokAt(2)->str(value);
|
||||
tok2->tokAt(2)->varId(valueVarId);
|
||||
if (Token::Match(tok3, "[;{}] %any% %any% ;"))
|
||||
{
|
||||
Token::eraseTokens(tok3, tok3->tokAt(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// return variable..
|
||||
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
||||
isOp(tok3->tokAt(2)))
|
||||
{
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
|
||||
else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid))
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
}
|
||||
ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, pointeralias, indentlevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6700,6 +6308,406 @@ bool Tokenizer::simplifyKnownVariables()
|
|||
return ret;
|
||||
}
|
||||
|
||||
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 ret = false;;
|
||||
|
||||
Token* bailOutFromLoop = 0;
|
||||
int indentlevel3 = indentlevel;
|
||||
bool ret3 = false;
|
||||
for (; tok3; tok3 = tok3->next())
|
||||
{
|
||||
if (tok3->str() == "{")
|
||||
{
|
||||
++indentlevel3;
|
||||
}
|
||||
else if (tok3->str() == "}")
|
||||
{
|
||||
--indentlevel3;
|
||||
if (indentlevel3 < indentlevel)
|
||||
{
|
||||
if (Token::Match((*tok2)->tokAt(-7), "%type% * %var% ; %var% = & %var% ;") &&
|
||||
(*tok2)->tokAt(-5)->str() == (*tok2)->tokAt(-3)->str())
|
||||
{
|
||||
(*tok2) = (*tok2)->tokAt(-4);
|
||||
Token::eraseTokens((*tok2), (*tok2)->tokAt(5));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if label is found
|
||||
if (Token::Match(tok3, "; %type% : ;"))
|
||||
break;
|
||||
|
||||
// Stop if return or break is found ..
|
||||
if (tok3->str() == "break")
|
||||
break;
|
||||
if ((indentlevel3 > 1 || !Token::simpleMatch(Token::findmatch(tok3,";"), "; }")) && tok3->str() == "return")
|
||||
ret3 = true;
|
||||
if (ret3 && tok3->str() == ";")
|
||||
break;
|
||||
|
||||
if (pointeralias && Token::Match(tok3, ("!!= " + value).c_str()))
|
||||
break;
|
||||
|
||||
// Stop if do is found
|
||||
if (tok3->str() == "do")
|
||||
break;
|
||||
|
||||
// Stop if something like 'while (--var)' is found
|
||||
if (tok3->str() == "for" || tok3->str() == "while" || tok3->str() == "do")
|
||||
{
|
||||
const Token *endpar = tok3->next()->link();
|
||||
if (Token::simpleMatch(endpar, ") {"))
|
||||
endpar = endpar->next()->link();
|
||||
bool bailout = false;
|
||||
for (const Token *tok4 = tok3; tok4 && tok4 != endpar; tok4 = tok4->next())
|
||||
{
|
||||
if (Token::Match(tok4, "++|-- %varid%", varid) ||
|
||||
Token::Match(tok4, "%varid% ++|--|=", varid))
|
||||
{
|
||||
bailout = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bailout)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bailOutFromLoop)
|
||||
{
|
||||
// This could be a loop, skip it, but only if it doesn't contain
|
||||
// the variable we are checking for. If it contains the variable
|
||||
// we will bail out.
|
||||
if (tok3->varId() == varid)
|
||||
{
|
||||
// Continue
|
||||
//tok2 = bailOutFromLoop;
|
||||
break;
|
||||
}
|
||||
else if (tok3 == bailOutFromLoop)
|
||||
{
|
||||
// We have skipped the loop
|
||||
bailOutFromLoop = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (tok3->str() == "{" && tok3->previous()->str() == ")")
|
||||
{
|
||||
// There is a possible loop after the assignment. Try to skip it.
|
||||
if (tok3->previous()->link() &&
|
||||
!Token::simpleMatch(tok3->previous()->link()->previous(), "if"))
|
||||
bailOutFromLoop = tok3->link();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Variable used in realloc (see Ticket #1649)
|
||||
if (Token::Match(tok3, "%var% = realloc ( %var% ,") &&
|
||||
tok3->varId() == varid &&
|
||||
tok3->tokAt(4)->varId() == varid)
|
||||
{
|
||||
tok3->tokAt(4)->str(value);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// condition "(|&&|%OROR% %varid% )|&&|%OROR%
|
||||
if (!Token::Match(tok3->previous(), "( %var% )") &&
|
||||
(Token::Match(tok3->previous(), "&&|(") || tok3->strAt(-1) == "||") &&
|
||||
tok3->varId() == varid &&
|
||||
(Token::Match(tok3->next(), "&&|)") || tok3->strAt(1) == "||"))
|
||||
{
|
||||
tok3->str(value);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used somehow in a non-defined pattern => bail out
|
||||
if (tok3->varId() == varid)
|
||||
{
|
||||
// This is a really generic bailout so let's try to avoid this.
|
||||
// There might be lots of false negatives.
|
||||
if (_settings->debugwarnings)
|
||||
{
|
||||
// FIXME: Fix all the debug warnings for values and then
|
||||
// remove this bailout
|
||||
if (pointeralias)
|
||||
break;
|
||||
|
||||
// suppress debug-warning when calling member function
|
||||
if (Token::Match(tok3->next(), ". %var% ("))
|
||||
break;
|
||||
|
||||
// suppress debug-warning when assignment
|
||||
if (Token::simpleMatch(tok3->next(), "="))
|
||||
break;
|
||||
|
||||
// taking address of variable..
|
||||
if (Token::Match(tok3->tokAt(-2), "return|= & %var% ;"))
|
||||
break;
|
||||
|
||||
// parameter in function call..
|
||||
if (Token::Match(tok3->tokAt(-2), "%var% ( %var% ,|)") ||
|
||||
Token::Match(tok3->previous(), ", %var% ,|)"))
|
||||
break;
|
||||
|
||||
// conditional increment
|
||||
if (Token::Match(tok3->tokAt(-3), ") { ++|--") ||
|
||||
Token::Match(tok3->tokAt(-2), ") { %var% ++|--"))
|
||||
break;
|
||||
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||
loc.line = tok3->linenr();
|
||||
loc.setfile(file(tok3));
|
||||
locationList.push_back(loc);
|
||||
|
||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||
Severity::debug,
|
||||
"simplifyKnownVariables: bailing out (variable="+tok3->str()+", value="+value+")",
|
||||
"debug");
|
||||
|
||||
if (_errorLogger)
|
||||
_errorLogger->reportErr(errmsg);
|
||||
else
|
||||
Check::reportError(errmsg);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Using the variable in condition..
|
||||
if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
||||
Token::Match(tok3, ("( " + structname + " %varid% ==|!=|<|<=|>|>=").c_str(), varid) ||
|
||||
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
||||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Delete pointer alias
|
||||
if (pointeralias && tok3->str() == "delete" &&
|
||||
(Token::Match(tok3, "delete %varid% ;", varid) ||
|
||||
Token::Match(tok3, "delete [ ] %varid%", varid)))
|
||||
{
|
||||
tok3 = (tok3->strAt(1) == "[") ? tok3->tokAt(3) : tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used in function call..
|
||||
if (Token::Match(tok3, ("%var% ( " + structname + " %varid% ,").c_str(), varid))
|
||||
{
|
||||
const char * const functionName[] =
|
||||
{
|
||||
"memcmp","memcpy","memmove","memset",
|
||||
"strcmp","strcpy","strncpy","strdup"
|
||||
};
|
||||
for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i)
|
||||
{
|
||||
if (tok3->str() == functionName[i])
|
||||
{
|
||||
Token *par1 = tok3->next()->next();
|
||||
if (!structname.empty())
|
||||
{
|
||||
par1->deleteThis();
|
||||
par1->deleteThis();
|
||||
}
|
||||
par1->str(value);
|
||||
par1->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variable is used as 2nd parameter in function call..
|
||||
if (Token::Match(tok3, ("%var% ( %any% , " + structname + " %varid% ,|)").c_str(), varid))
|
||||
{
|
||||
const char * const functionName[] =
|
||||
{
|
||||
"memcmp","memcpy","memmove",
|
||||
"strcmp","strcpy","strncmp","strncpy"
|
||||
};
|
||||
for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i)
|
||||
{
|
||||
if (tok3->str() == functionName[i])
|
||||
{
|
||||
Token *par = tok3->tokAt(4);
|
||||
if (!structname.empty())
|
||||
{
|
||||
par->deleteThis();
|
||||
par->deleteThis();
|
||||
}
|
||||
par->str(value);
|
||||
par->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// array usage
|
||||
if (Token::Match(tok3, ("[(,] " + structname + " %varid% [+-*/[]").c_str(), varid))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used in calculation..
|
||||
if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
|
||||
Token::Match(tok3, ("[=+-*/[] " + structname + " %varid% [=?+-*/;])]").c_str(), varid) ||
|
||||
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))
|
||||
{
|
||||
if (!structname.empty())
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->deleteNext();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
if (tok3->previous()->str() == "*" && valueIsPointer)
|
||||
{
|
||||
tok3 = tok3->previous();
|
||||
tok3->deleteThis();
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(tok3, "= {"))
|
||||
{
|
||||
unsigned int indentlevel4 = 0;
|
||||
for (const Token *tok4 = tok3; tok4; tok4 = tok4->next())
|
||||
{
|
||||
if (tok4->str() == "{")
|
||||
++indentlevel4;
|
||||
else if (tok4->str() == "}")
|
||||
{
|
||||
if (indentlevel4 <= 1)
|
||||
break;
|
||||
--indentlevel4;
|
||||
}
|
||||
if (Token::Match(tok4, "{|, %varid% ,|}", varid))
|
||||
{
|
||||
tok4->next()->str(value);
|
||||
tok4->next()->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Using the variable in for-condition..
|
||||
if (Token::simpleMatch(tok3, "for ("))
|
||||
{
|
||||
for (Token *tok4 = tok3->tokAt(2); tok4; tok4 = tok4->next())
|
||||
{
|
||||
if (tok4->str() == "(" || tok4->str() == ")")
|
||||
break;
|
||||
|
||||
// Replace variable used in condition..
|
||||
if (Token::Match(tok4, "; %var% <|<=|!= %var% ; ++| %var% ++| )"))
|
||||
{
|
||||
const Token *inctok = tok4->tokAt(5);
|
||||
if (inctok->str() == "++")
|
||||
inctok = inctok->next();
|
||||
if (inctok->varId() == varid)
|
||||
break;
|
||||
|
||||
if (tok4->next()->varId() == varid)
|
||||
{
|
||||
tok4->next()->str(value);
|
||||
tok4->next()->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
if (tok4->tokAt(3)->varId() == varid)
|
||||
{
|
||||
tok4->tokAt(3)->str(value);
|
||||
tok4->tokAt(3)->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indentlevel == indentlevel3 && Token::Match(tok3->next(), "%varid% ++|--", varid) && MathLib::isInt(value))
|
||||
{
|
||||
const std::string op(tok3->strAt(2));
|
||||
if (Token::Match(tok3, "[{};] %any% %any% ;"))
|
||||
{
|
||||
Token::eraseTokens(tok3, tok3->tokAt(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
tok3->deleteNext();
|
||||
}
|
||||
incdec(value, op);
|
||||
if (!Token::simpleMatch((*tok2)->tokAt(-2), "for ("))
|
||||
{
|
||||
(*tok2)->tokAt(2)->str(value);
|
||||
(*tok2)->tokAt(2)->varId(valueVarId);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (indentlevel == indentlevel3 && Token::Match(tok3->next(), "++|-- %varid%", varid) && MathLib::isInt(value) &&
|
||||
!Token::Match(tok3->tokAt(3), "[.[]"))
|
||||
{
|
||||
incdec(value, tok3->strAt(1));
|
||||
(*tok2)->tokAt(2)->str(value);
|
||||
(*tok2)->tokAt(2)->varId(valueVarId);
|
||||
if (Token::Match(tok3, "[;{}] %any% %any% ;"))
|
||||
{
|
||||
Token::eraseTokens(tok3, tok3->tokAt(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// return variable..
|
||||
if (Token::Match(tok3, "return %varid% %any%", varid) &&
|
||||
isOp(tok3->tokAt(2)))
|
||||
{
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
|
||||
else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid))
|
||||
{
|
||||
tok3->deleteNext();
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Tokenizer::elseif()
|
||||
{
|
||||
|
|
|
@ -308,6 +308,12 @@ public:
|
|||
*/
|
||||
bool simplifyKnownVariables();
|
||||
|
||||
/**
|
||||
* utility function for simplifyKnownVariables. Perform simplification
|
||||
* 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);
|
||||
|
||||
/** Replace a "goto" with the statements */
|
||||
void simplifyGoto();
|
||||
|
||||
|
|
Loading…
Reference in New Issue