Remove simplifyKnownVariables() (#4232)
* Remove simplifyKnownVariables() * Add some test cases back * Remove unused functions * Format
This commit is contained in:
parent
11860cce4b
commit
63e567eb50
|
@ -1037,23 +1037,6 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string MathLib::incdec(const std::string & var, const std::string & op)
|
||||
{
|
||||
#ifdef TEST_MATHLIB_VALUE
|
||||
if (op == "++")
|
||||
return value(var).add(1).str();
|
||||
else if (op == "--")
|
||||
return value(var).add(-1).str();
|
||||
#else
|
||||
if (op == "++")
|
||||
return MathLib::add(var, "1");
|
||||
else if (op == "--")
|
||||
return MathLib::subtract(var, "1");
|
||||
#endif
|
||||
|
||||
throw InternalError(nullptr, std::string("Unexpected operation '") + op + "' in MathLib::incdec(). Please report this to Cppcheck developers.");
|
||||
}
|
||||
|
||||
std::string MathLib::divide(const std::string &first, const std::string &second)
|
||||
{
|
||||
#ifdef TEST_MATHLIB_VALUE
|
||||
|
|
|
@ -106,7 +106,6 @@ public:
|
|||
static std::string multiply(const std::string & first, const std::string & second);
|
||||
static std::string divide(const std::string & first, const std::string & second);
|
||||
static std::string mod(const std::string & first, const std::string & second);
|
||||
static std::string incdec(const std::string & var, const std::string & op);
|
||||
static std::string calculate(const std::string & first, const std::string & second, char action);
|
||||
|
||||
static std::string sin(const std::string & tok);
|
||||
|
|
828
lib/tokenize.cpp
828
lib/tokenize.cpp
|
@ -5178,8 +5178,6 @@ bool Tokenizer::simplifyTokenList2()
|
|||
return false;
|
||||
|
||||
modified = false;
|
||||
modified |= simplifyKnownVariables();
|
||||
|
||||
modified |= simplifyConstTernaryOp();
|
||||
modified |= simplifyCalculations();
|
||||
validate();
|
||||
|
@ -7038,767 +7036,6 @@ Token * Tokenizer::initVar(Token * tok)
|
|||
return tok;
|
||||
}
|
||||
|
||||
|
||||
bool Tokenizer::simplifyKnownVariables()
|
||||
{
|
||||
// return value for function. Set to true if any simplifications are made
|
||||
bool ret = false;
|
||||
|
||||
// constants..
|
||||
{
|
||||
std::unordered_map<int, std::string> constantValues;
|
||||
std::map<int, Token*> constantVars;
|
||||
std::unordered_map<int, std::list<Token*>> constantValueUsages;
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
// Reference to variable
|
||||
if (Token::Match(tok, "%type%|* & %name% = %name% ;")) {
|
||||
Token *start = tok->previous();
|
||||
while (Token::Match(start,"%type%|*|&"))
|
||||
start = start->previous();
|
||||
if (!Token::Match(start,"[;{}]"))
|
||||
continue;
|
||||
const Token *reftok = tok->tokAt(2);
|
||||
const Token *vartok = reftok->tokAt(2);
|
||||
int level = 0;
|
||||
for (Token *tok2 = tok->tokAt(6); tok2; tok2 = tok2->next()) {
|
||||
if (tok2->str() == "{") {
|
||||
++level;
|
||||
} else if (tok2->str() == "}") {
|
||||
if (level <= 0)
|
||||
break;
|
||||
--level;
|
||||
} else if (tok2->varId() == reftok->varId()) {
|
||||
tok2->str(vartok->str());
|
||||
tok2->varId(vartok->varId());
|
||||
}
|
||||
}
|
||||
Token::eraseTokens(start, tok->tokAt(6));
|
||||
tok = start;
|
||||
}
|
||||
|
||||
if (tok->isName() && (Token::Match(tok, "static| const| static| %type% const| %name% = %any% ;") ||
|
||||
Token::Match(tok, "static| const| static| %type% const| %name% ( %any% ) ;"))) {
|
||||
bool isconst = false;
|
||||
for (const Token *tok2 = tok; (tok2->str() != "=") && (tok2->str() != "("); tok2 = tok2->next()) {
|
||||
if (tok2->str() == "const") {
|
||||
isconst = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isconst)
|
||||
continue;
|
||||
|
||||
Token *tok1 = tok;
|
||||
|
||||
// start of statement
|
||||
if (tok != list.front() && !Token::Match(tok->previous(),";|{|}|private:|protected:|public:"))
|
||||
continue;
|
||||
// skip "const" and "static"
|
||||
while (Token::Match(tok, "const|static"))
|
||||
tok = tok->next();
|
||||
// pod type
|
||||
if (!tok->isStandardType())
|
||||
continue;
|
||||
|
||||
Token * const vartok = (tok->next() && tok->next()->str() == "const") ? tok->tokAt(2) : tok->next();
|
||||
const Token * const valuetok = vartok->tokAt(2);
|
||||
if (Token::Match(valuetok, "%bool%|%char%|%num%|%str% )| ;")) {
|
||||
// record a constant value for this variable
|
||||
constantValues[vartok->varId()] = valuetok->str();
|
||||
constantVars[vartok->varId()] = tok1;
|
||||
}
|
||||
} else if (tok->varId()) {
|
||||
// find the entry for the known variable, if any. Exclude the location where the variable is assigned with next == "="
|
||||
if (constantValues.find(tok->varId()) != constantValues.end() && tok->next()->str() != "=") {
|
||||
constantValueUsages[tok->varId()].push_back(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto constantVar = constantVars.rbegin(); constantVar != constantVars.rend(); constantVar++) {
|
||||
bool referenceFound = false;
|
||||
std::list<Token*> usageList = constantValueUsages[constantVar->first];
|
||||
for (Token* usage : usageList) {
|
||||
// check if any usages of each known variable are a reference
|
||||
if (Token::Match(usage->tokAt(-2), "(|[|,|{|return|%op% & %varid%", constantVar->first)) {
|
||||
referenceFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!referenceFound) {
|
||||
// replace all usages of non-referenced known variables with their value
|
||||
for (Token* usage : usageList) {
|
||||
usage->str(constantValues[constantVar->first]);
|
||||
}
|
||||
|
||||
Token* startTok = constantVar->second;
|
||||
// remove variable assignment statement
|
||||
while (startTok->next()->str() != ";")
|
||||
startTok->deleteNext();
|
||||
startTok->deleteNext();
|
||||
|
||||
// #8579 if we can we want another token to delete startTok. if we can't it doesn't matter
|
||||
if (startTok->previous()) {
|
||||
startTok->previous()->deleteNext();
|
||||
} else if (startTok->next()) {
|
||||
startTok->next()->deletePrevious();
|
||||
} else {
|
||||
startTok->deleteThis();
|
||||
}
|
||||
startTok = nullptr;
|
||||
|
||||
constantVar->second = nullptr;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// variable id for local, float/double, array variables
|
||||
std::set<int> localvars;
|
||||
std::set<int> floatvars;
|
||||
std::set<int> arrays;
|
||||
|
||||
// auto variables..
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
// Search for a block of code
|
||||
Token * const start = const_cast<Token *>(startOfExecutableScope(tok));
|
||||
if (!start)
|
||||
continue;
|
||||
|
||||
for (const Token *tok2 = start->previous(); tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->previous()) {
|
||||
if (tok2->varId() != 0)
|
||||
localvars.insert(tok2->varId());
|
||||
}
|
||||
|
||||
tok = start;
|
||||
// parse the block of code..
|
||||
int indentlevel = 0;
|
||||
Token *tok2 = tok;
|
||||
for (; tok2; tok2 = tok2->next()) {
|
||||
if (Token::Match(tok2, "[;{}] %type% %name%|*")) {
|
||||
bool isfloat = false;
|
||||
bool ispointer = false;
|
||||
const Token *vartok = tok2->next();
|
||||
while (Token::Match(vartok, "%name%|* %name%|*")) {
|
||||
if (Token::Match(vartok, "float|double"))
|
||||
isfloat = true;
|
||||
if (vartok->str() == "*")
|
||||
ispointer = true;
|
||||
vartok = vartok->next();
|
||||
}
|
||||
if (Token::Match(vartok, "%var% ;|["))
|
||||
localvars.insert(vartok->varId());
|
||||
if (isfloat && !ispointer && Token::Match(vartok, "%var% ;"))
|
||||
floatvars.insert(vartok->varId());
|
||||
if (Token::Match(vartok, "%var% ["))
|
||||
arrays.insert(vartok->varId());
|
||||
}
|
||||
|
||||
if (tok2->str() == "{")
|
||||
++indentlevel;
|
||||
|
||||
else if (tok2->str() == "}") {
|
||||
--indentlevel;
|
||||
if (indentlevel <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
else if (Token::simpleMatch(tok2, "for ("))
|
||||
tok2 = tok2->next()->link();
|
||||
|
||||
else if (tok2->previous()->str() != "*" && !Token::Match(tok2->tokAt(-2), "* --|++") &&
|
||||
(Token::Match(tok2, "%name% = %bool%|%char%|%num%|%str%|%name% ;") ||
|
||||
Token::Match(tok2, "%name% [ %num%| ] = %str% ;") ||
|
||||
Token::Match(tok2, "%name% = & %name% ;") ||
|
||||
(Token::Match(tok2, "%name% = & %name% [ 0 ] ;") && arrays.find(tok2->tokAt(3)->varId()) != arrays.end()))) {
|
||||
const int varid = tok2->varId();
|
||||
if (varid == 0)
|
||||
continue;
|
||||
|
||||
if (Token::Match(tok2->previous(), "[;{}]") && localvars.find(varid) == localvars.end())
|
||||
continue;
|
||||
|
||||
// initialization of static variable => the value is not *known*
|
||||
{
|
||||
bool isstatic = false;
|
||||
const Token *decl = tok2->previous();
|
||||
while (decl && (decl->isName() || decl->str() == "*")) {
|
||||
if (decl->str() == "static") {
|
||||
isstatic = true;
|
||||
break;
|
||||
}
|
||||
decl = decl->previous();
|
||||
}
|
||||
if (isstatic)
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip loop variable
|
||||
if (Token::Match(tok2->tokAt(-2), "(|:: %type%")) {
|
||||
const Token *tok3 = tok2->previous();
|
||||
do {
|
||||
tok3 = tok3->tokAt(-2);
|
||||
} while (Token::Match(tok3->previous(), ":: %type%"));
|
||||
if (Token::Match(tok3->tokAt(-2), "for ( %type%"))
|
||||
continue;
|
||||
}
|
||||
|
||||
// struct name..
|
||||
if (Token::Match(tok2, "%varid% = &| %varid%", tok2->varId()))
|
||||
continue;
|
||||
|
||||
const std::string structname = Token::Match(tok2->tokAt(-3), "[;{}] %name% .") ?
|
||||
std::string(tok2->strAt(-2) + " .") :
|
||||
std::string();
|
||||
|
||||
const Token * const valueToken = tok2->tokAt(2);
|
||||
|
||||
std::string value;
|
||||
nonneg int valueVarId = 0;
|
||||
|
||||
Token *tok3 = nullptr;
|
||||
bool valueIsPointer = false;
|
||||
|
||||
// there could be a hang here if tok2 is moved back by the function calls below for some reason
|
||||
if (Settings::terminated())
|
||||
return false;
|
||||
|
||||
if (!simplifyKnownVariablesGetData(varid, &tok2, &tok3, value, valueVarId, valueIsPointer, floatvars.find(tok2->varId()) != floatvars.end()))
|
||||
continue;
|
||||
|
||||
if (valueVarId > 0 && arrays.find(valueVarId) != arrays.end())
|
||||
continue;
|
||||
|
||||
ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel);
|
||||
}
|
||||
|
||||
else if (Token::Match(tok2, "strcpy|sprintf ( %name% , %str% ) ;")) {
|
||||
const int varid(tok2->tokAt(2)->varId());
|
||||
if (varid == 0)
|
||||
continue;
|
||||
|
||||
const Token * const valueToken = tok2->tokAt(4);
|
||||
std::string value(valueToken->str());
|
||||
if (tok2->str() == "sprintf") {
|
||||
std::string::size_type n = 0;
|
||||
while ((n = value.find("%%", n)) != std::string::npos) {
|
||||
// Replace "%%" with "%" - erase the first '%' and continue past the second '%'
|
||||
value.erase(n, 1);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
const int valueVarId(0);
|
||||
const bool valueIsPointer(false);
|
||||
Token *tok3 = tok2->tokAt(6);
|
||||
ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, emptyString, value, valueVarId, valueIsPointer, valueToken, indentlevel);
|
||||
|
||||
// there could be a hang here if tok2 was moved back by the function call above for some reason
|
||||
if (Settings::terminated())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok2)
|
||||
tok = tok2->previous();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Tokenizer::simplifyKnownVariablesGetData(nonneg int varid, Token **_tok2, Token **_tok3, std::string &value, nonneg int &valueVarId, bool &valueIsPointer, bool floatvar)
|
||||
{
|
||||
Token *tok2 = *_tok2;
|
||||
Token *tok3 = nullptr;
|
||||
|
||||
if (Token::simpleMatch(tok2->tokAt(-2), "for (")) {
|
||||
// only specific for loops is handled
|
||||
if (!Token::Match(tok2, "%varid% = %num% ; %varid% <|<= %num% ; ++| %varid% ++| ) {", varid))
|
||||
return false;
|
||||
|
||||
// is there a "break" in the for loop?
|
||||
bool hasbreak = false;
|
||||
const Token* end4 = tok2->linkAt(-1)->linkAt(1);
|
||||
for (const Token *tok4 = tok2->previous()->link(); tok4 != end4; tok4 = tok4->next()) {
|
||||
if (tok4->str() == "break") {
|
||||
hasbreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasbreak)
|
||||
return false;
|
||||
|
||||
// no break => the value of the counter value is known after the for loop..
|
||||
const Token* compareTok = tok2->tokAt(5);
|
||||
if (compareTok->str() == "<") {
|
||||
value = compareTok->next()->str();
|
||||
valueVarId = compareTok->next()->varId();
|
||||
} else
|
||||
value = MathLib::toString(MathLib::toLongNumber(compareTok->next()->str()) + 1);
|
||||
|
||||
// Skip for-body..
|
||||
tok3 = tok2->previous()->link()->next()->link()->next();
|
||||
} else {
|
||||
value = tok2->strAt(2);
|
||||
valueVarId = tok2->tokAt(2)->varId();
|
||||
if (tok2->strAt(1) == "[") {
|
||||
value = tok2->next()->link()->strAt(2);
|
||||
valueVarId = 0;
|
||||
} else if (value == "&") {
|
||||
value = tok2->strAt(3);
|
||||
valueVarId = tok2->tokAt(3)->varId();
|
||||
|
||||
// *ptr = &var; *ptr = 5;
|
||||
// equals
|
||||
// var = 5; not *var = 5;
|
||||
if (tok2->strAt(4) == ";")
|
||||
valueIsPointer = true;
|
||||
}
|
||||
|
||||
// Add a '.0' to a decimal value and therefore convert it to an floating point number.
|
||||
else if (MathLib::isDec(tok2->strAt(2)) && floatvar) {
|
||||
value += ".0";
|
||||
}
|
||||
|
||||
// float variable: convert true/false to 1.0 / 0.0
|
||||
else if (tok2->tokAt(2)->isBoolean() && floatvar) {
|
||||
value = (value == "true") ? "1.0" : "0.0";
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(tok2->next(), "= &"))
|
||||
tok2 = tok2->tokAt(3);
|
||||
|
||||
tok3 = tok2->next();
|
||||
}
|
||||
*_tok2 = tok2;
|
||||
*_tok3 = tok3;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, nonneg int varid, const std::string &structname, std::string &value, nonneg int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel) const
|
||||
{
|
||||
const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %name% ["));
|
||||
const bool varIsGlobal = (indentlevel == 0);
|
||||
const bool printDebug = mSettings->debugwarnings;
|
||||
|
||||
if (mErrorLogger && !list.getFiles().empty())
|
||||
mErrorLogger->reportProgress(list.getFiles()[0], "Tokenize (simplifyKnownVariables)", tok3->progressValue());
|
||||
|
||||
if (isMaxTime())
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
Token* bailOutFromLoop = nullptr;
|
||||
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% * %name% ; %name% = & %name% ;") &&
|
||||
(*tok2)->strAt(-5) == (*tok2)->strAt(-3)) {
|
||||
(*tok2) = (*tok2)->tokAt(-4);
|
||||
Token::eraseTokens((*tok2), (*tok2)->tokAt(6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if there is a pointer alias and a shadow variable is
|
||||
// declared in an inner scope (#3058)
|
||||
if (valueIsPointer && tok3->varId() > 0 &&
|
||||
tok3->previous() && (tok3->previous()->isName() || tok3->previous()->str() == "*") &&
|
||||
valueToken->str() == "&" &&
|
||||
valueToken->next() &&
|
||||
valueToken->next()->isName() &&
|
||||
tok3->str() == valueToken->next()->str() &&
|
||||
tok3->varId() > valueToken->next()->varId()) {
|
||||
// more checking if this is a variable declaration
|
||||
bool decl = true;
|
||||
for (const Token *tok4 = tok3->previous(); tok4; tok4 = tok4->previous()) {
|
||||
if (Token::Match(tok4, "[;{}]"))
|
||||
break;
|
||||
|
||||
else if (tok4->isName()) {
|
||||
if (tok4->varId() > 0) {
|
||||
decl = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (!Token::Match(tok4, "[&*]")) {
|
||||
decl = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (decl)
|
||||
break;
|
||||
}
|
||||
|
||||
// Stop if label is found
|
||||
if (Token::Match(tok3, "; %type% : ;"))
|
||||
break;
|
||||
|
||||
// Stop if break/continue is found ..
|
||||
if (Token::Match(tok3, "break|continue"))
|
||||
break;
|
||||
if ((indentlevel3 > 1 || !Token::simpleMatch(Token::findsimplematch(tok3,";"), "; }")) && tok3->str() == "return")
|
||||
ret3 = true;
|
||||
if (ret3 && tok3->str() == ";")
|
||||
break;
|
||||
|
||||
if (pointeralias && Token::Match(tok3, ("!!= " + value).c_str()))
|
||||
break;
|
||||
|
||||
// Stop if a loop is found
|
||||
if (pointeralias && Token::Match(tok3, "do|for|while"))
|
||||
break;
|
||||
|
||||
// Stop if unknown function call is seen and the variable is global: it might be
|
||||
// changed by the function call
|
||||
if (varIsGlobal && tok3->str() == ")" && tok3->link() &&
|
||||
Token::Match(tok3->link()->tokAt(-2), "[;{}] %name% (") &&
|
||||
!Token::Match(tok3->link()->previous(), "if|for|while|switch|BOOST_FOREACH"))
|
||||
break;
|
||||
|
||||
// Stop if something like 'while (--var)' is found
|
||||
if (Token::Match(tok3, "for|while|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 = nullptr;
|
||||
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() &&
|
||||
tok3->previous()->link()->strAt(-1) != "if")
|
||||
bailOutFromLoop = tok3->link();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Variable used in realloc (see Ticket #1649)
|
||||
if (Token::Match(tok3, "%name% = realloc ( %name% ,") &&
|
||||
tok3->varId() == varid &&
|
||||
tok3->tokAt(4)->varId() == varid) {
|
||||
tok3->tokAt(4)->str(value);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// condition "(|&&|%OROR% %varid% )|&&|%OROR%|;
|
||||
if (!Token::Match(tok3->previous(), "( %name% )") &&
|
||||
Token::Match(tok3->previous(), "&&|(|%oror% %varid% &&|%oror%|)|;", varid)) {
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// parameter in function call..
|
||||
if (tok3->varId() == varid && Token::Match(tok3->previous(), "[(,] %name% [,)]")) {
|
||||
// If the parameter is passed by value then simplify it
|
||||
if (isFunctionParameterPassedByValue(tok3)) {
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
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 (printDebug) {
|
||||
// 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(), ". %name% ("))
|
||||
break;
|
||||
|
||||
// suppress debug-warning when assignment
|
||||
if (tok3->strAt(1) == "=")
|
||||
break;
|
||||
|
||||
// taking address of variable..
|
||||
if (Token::Match(tok3->tokAt(-2), "return|= & %name% ;"))
|
||||
break;
|
||||
|
||||
// parameter in function call..
|
||||
if (Token::Match(tok3->tokAt(-2), "%name% ( %name% ,|)") ||
|
||||
Token::Match(tok3->previous(), ", %name% ,|)"))
|
||||
break;
|
||||
|
||||
// conditional increment
|
||||
if (Token::Match(tok3->tokAt(-3), ") { ++|--") ||
|
||||
Token::Match(tok3->tokAt(-2), ") { %name% ++|--"))
|
||||
break;
|
||||
|
||||
reportError(tok3, Severity::debug, "debug",
|
||||
"simplifyKnownVariables: bailing out (variable="+tok3->str()+", value="+value+")");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Using the variable in condition..
|
||||
if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% %cop%|)").c_str(), varid) ||
|
||||
Token::Match(tok3, ("( " + structname + " %varid% %comp%").c_str(), varid) ||
|
||||
Token::Match(tok3, ("%comp%|!|= " + structname + " %varid% %cop%|)|;").c_str(), varid) ||
|
||||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid)) {
|
||||
if (value[0] == '\"' && tok3->previous()->str() != "strlen") {
|
||||
// bail out if value is a string unless if it's just given
|
||||
// as parameter to strlen
|
||||
break;
|
||||
}
|
||||
if (!structname.empty()) {
|
||||
tok3->deleteNext(2);
|
||||
}
|
||||
if (Token::Match(valueToken, "& %name% ;")) {
|
||||
tok3->insertToken("&");
|
||||
tok3 = tok3->next();
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// pointer alias used in condition..
|
||||
if (Token::Match(valueToken,"& %name% ;") && Token::Match(tok3, ("( * " + structname + " %varid% %cop%").c_str(), varid)) {
|
||||
tok3->deleteNext();
|
||||
if (!structname.empty())
|
||||
tok3->deleteNext(2);
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Delete pointer alias
|
||||
if (isCPP() && pointeralias && (tok3->str() == "delete") && tok3->next() &&
|
||||
(Token::Match(tok3->next(), "%varid% ;", varid) ||
|
||||
Token::Match(tok3->next(), "[ ] %varid%", varid))) {
|
||||
tok3 = (tok3->next()->str() == "[") ? tok3->tokAt(3) : tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Variable is used in function call..
|
||||
if (Token::Match(tok3, ("%name% ( " + structname + " %varid% ,").c_str(), varid)) {
|
||||
static const char * const functionName[] = {
|
||||
// always simplify
|
||||
"strcmp", "strdup",
|
||||
// don't simplify buffer value
|
||||
"memcmp","memcpy","memmove","memset","strcpy","strncmp","strncpy"
|
||||
};
|
||||
for (int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i) {
|
||||
if (valueVarId == 0U && i >= 2)
|
||||
break;
|
||||
if (tok3->str() == functionName[i]) {
|
||||
Token *par1 = tok3->tokAt(2);
|
||||
if (!structname.empty()) {
|
||||
par1->deleteNext();
|
||||
par1->deleteThis();
|
||||
}
|
||||
par1->str(value);
|
||||
par1->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variable is used as 2nd parameter in function call..
|
||||
if (Token::Match(tok3, ("%name% ( %any% , " + structname + " %varid% ,|)").c_str(), varid)) {
|
||||
static const char * const functionName[] = {
|
||||
// always simplify
|
||||
"strcmp","strcpy","strncmp","strncpy",
|
||||
// don't simplify buffer value
|
||||
"memcmp","memcpy","memmove"
|
||||
};
|
||||
for (int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i) {
|
||||
if (valueVarId == 0U && i >= 4)
|
||||
break;
|
||||
if (tok3->str() == functionName[i]) {
|
||||
Token *par = tok3->tokAt(4);
|
||||
if (!structname.empty()) {
|
||||
par->deleteNext();
|
||||
par->deleteThis();
|
||||
}
|
||||
par->str(value);
|
||||
par->varId(valueVarId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// array usage
|
||||
if (value[0] != '\"' && Token::Match(tok3, ("[(,] " + structname + " %varid% [|%cop%").c_str(), varid)) {
|
||||
if (!structname.empty()) {
|
||||
tok3->deleteNext(2);
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// The >> operator is sometimes used to assign a variable in C++
|
||||
if (isCPP() && Token::Match(tok3, (">> " + structname + " %varid%").c_str(), varid)) {
|
||||
// bailout for such code: ; std :: cin >> i ;
|
||||
const Token *prev = tok3->previous();
|
||||
while (prev && prev->str() != "return" && Token::Match(prev, "%name%|::|*"))
|
||||
prev = prev->previous();
|
||||
if (Token::Match(prev, ";|{|}|>>"))
|
||||
break;
|
||||
}
|
||||
|
||||
// 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 + " %name% =").c_str())) ||
|
||||
Token::Match(tok3, ("[(=+-*/%^|[] " + structname + " %varid% <<|>>").c_str(), varid) ||
|
||||
Token::Match(tok3, ("<<|>> " + structname + " %varid% %cop%|;|]|)").c_str(), varid) ||
|
||||
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid% !!=").c_str(), varid)) {
|
||||
if (value[0] == '\"')
|
||||
break;
|
||||
if (!structname.empty()) {
|
||||
tok3->deleteNext(2);
|
||||
ret = true;
|
||||
}
|
||||
tok3 = tok3->next();
|
||||
if (tok3->str() != value)
|
||||
ret = true;
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
if (tok3->previous()->str() == "*" && (valueIsPointer || Token::Match(valueToken, "& %name% ;"))) {
|
||||
tok3 = tok3->previous();
|
||||
tok3->deleteThis();
|
||||
ret = true;
|
||||
} else if (Token::Match(valueToken, "& %name% ;"))
|
||||
tok3->insertToken("&", emptyString, true);
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(tok3, "= {")) {
|
||||
const Token* const end4 = tok3->linkAt(1);
|
||||
for (const Token *tok4 = tok3; tok4 != end4; tok4 = tok4->next()) {
|
||||
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 (Token::Match(tok4, "(|)"))
|
||||
break;
|
||||
|
||||
// Replace variable used in condition..
|
||||
if (Token::Match(tok4, "; %name% <|<=|!= %name% ; ++| %name% ++| )")) {
|
||||
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% ;")) {
|
||||
tok3->deleteNext(3);
|
||||
} else {
|
||||
tok3 = tok3->next();
|
||||
tok3->str(value);
|
||||
tok3->varId(valueVarId);
|
||||
tok3->deleteNext();
|
||||
}
|
||||
value = MathLib::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), "[.[]")) {
|
||||
value = MathLib::incdec(value, tok3->next()->str());
|
||||
(*tok2)->tokAt(2)->str(value);
|
||||
(*tok2)->tokAt(2)->varId(valueVarId);
|
||||
if (Token::Match(tok3, "[;{}] %any% %any% ;")) {
|
||||
tok3->deleteNext(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) &&
|
||||
valueToken->str() != "&" &&
|
||||
(tok3->tokAt(2)->isExtendedOp() || tok3->strAt(2) == ";") &&
|
||||
value[0] != '\"') {
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
|
||||
else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid) && value[0] != '\"') {
|
||||
tok3->deleteNext();
|
||||
tok3->next()->str(value);
|
||||
tok3->next()->varId(valueVarId);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Tokenizer::elseif()
|
||||
{
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
|
@ -8162,71 +7399,6 @@ bool Tokenizer::isScopeNoReturn(const Token *endScopeToken, bool *unknown) const
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool Tokenizer::isFunctionParameterPassedByValue(const Token *fpar) const
|
||||
{
|
||||
// TODO: If symbol database is available, use it.
|
||||
const Token *ftok;
|
||||
|
||||
// Look at function call, what parameter number is it?
|
||||
int parameter = 1;
|
||||
for (ftok = fpar->previous(); ftok; ftok = ftok->previous()) {
|
||||
if (ftok->str() == "(")
|
||||
break;
|
||||
else if (ftok->str() == ")")
|
||||
ftok = ftok->link();
|
||||
else if (ftok->str() == ",")
|
||||
++parameter;
|
||||
else if (Token::Match(ftok, "[;{}]"))
|
||||
break;
|
||||
}
|
||||
|
||||
// Is this a function call?
|
||||
if (ftok && Token::Match(ftok->tokAt(-2), "[;{}=] %name% (")) {
|
||||
const std::string& functionName(ftok->previous()->str());
|
||||
|
||||
if (functionName == "return")
|
||||
return true;
|
||||
|
||||
// Locate function declaration..
|
||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||
if (tok->str() == "{")
|
||||
tok = tok->link();
|
||||
else if (Token::Match(tok, "%type% (") && tok->str() == functionName) {
|
||||
// Goto parameter
|
||||
tok = tok->tokAt(2);
|
||||
int par = 1;
|
||||
while (tok && par < parameter) {
|
||||
if (tok->str() == ")")
|
||||
break;
|
||||
if (tok->str() == ",")
|
||||
++par;
|
||||
tok = tok->next();
|
||||
}
|
||||
if (!tok)
|
||||
return false;
|
||||
|
||||
// If parameter was found, determine if it's passed by value
|
||||
if (par == parameter) {
|
||||
bool knowntype = false;
|
||||
while (tok && tok->isName()) {
|
||||
knowntype |= tok->isStandardType();
|
||||
knowntype |= (tok->str() == "struct");
|
||||
tok = tok->next();
|
||||
}
|
||||
if (!tok || !knowntype)
|
||||
return false;
|
||||
if (tok->str() != "," && tok->str() != ")")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void Tokenizer::eraseDeadCode(Token *begin, const Token *end)
|
||||
{
|
||||
if (!begin)
|
||||
|
|
|
@ -329,27 +329,6 @@ public:
|
|||
*/
|
||||
bool simplifyUsing();
|
||||
|
||||
/**
|
||||
* A simplify function that replaces a variable with its value in cases
|
||||
* when the value is known. e.g. "x=10; if(x)" => "x=10;if(10)"
|
||||
*
|
||||
* @return true if modifications to token-list are done.
|
||||
* false if no modifications are done.
|
||||
*/
|
||||
bool simplifyKnownVariables();
|
||||
|
||||
/**
|
||||
* Utility function for simplifyKnownVariables. Get data about an
|
||||
* assigned variable.
|
||||
*/
|
||||
static bool simplifyKnownVariablesGetData(nonneg int varid, Token **_tok2, Token **_tok3, std::string &value, nonneg int &valueVarId, bool &valueIsPointer, bool floatvar);
|
||||
|
||||
/**
|
||||
* utility function for simplifyKnownVariables. Perform simplification
|
||||
* of a given variable
|
||||
*/
|
||||
bool simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, nonneg int varid, const std::string &structname, std::string &value, nonneg int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel) const;
|
||||
|
||||
/** Simplify useless C++ empty namespaces, like: 'namespace %name% { }'*/
|
||||
void simplifyEmptyNamespaces();
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ private:
|
|||
TEST_CASE(array_index_64); // #10878
|
||||
TEST_CASE(array_index_65); // #11066
|
||||
TEST_CASE(array_index_66); // #10740
|
||||
TEST_CASE(array_index_67); // #1596
|
||||
TEST_CASE(array_index_multidim);
|
||||
TEST_CASE(array_index_switch_in_for);
|
||||
TEST_CASE(array_index_for_in_for); // FP: #2634
|
||||
|
@ -1852,6 +1853,25 @@ private:
|
|||
errout.str());
|
||||
}
|
||||
|
||||
void array_index_67() {
|
||||
check("void func(int i) {\n" // #1596
|
||||
" int types[3];\n"
|
||||
" int type_cnt = 0;\n"
|
||||
" if (i == 0) {\n"
|
||||
" types[type_cnt] = 0;\n"
|
||||
" type_cnt++;\n"
|
||||
" types[type_cnt] = 0;\n"
|
||||
" type_cnt++;\n"
|
||||
" types[type_cnt] = 0;\n"
|
||||
" type_cnt++;\n"
|
||||
" } else {\n"
|
||||
" types[type_cnt] = 1;\n"
|
||||
" type_cnt++;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void array_index_multidim() {
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
|
|
|
@ -93,6 +93,7 @@ private:
|
|||
TEST_CASE(assign21); // #10186
|
||||
TEST_CASE(assign22); // #9139
|
||||
TEST_CASE(assign23);
|
||||
TEST_CASE(assign24); // #7440
|
||||
|
||||
TEST_CASE(isAutoDealloc);
|
||||
|
||||
|
@ -504,6 +505,23 @@ private:
|
|||
settings = s;
|
||||
}
|
||||
|
||||
void assign24() { // #7440
|
||||
check("void f() {\n"
|
||||
" char* data = new char[100];\n"
|
||||
" char** dataPtr = &data;\n"
|
||||
" delete[] *dataPtr;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char* data = new char[100];\n"
|
||||
" char** dataPtr = &data;\n"
|
||||
" printf(\"test\");\n"
|
||||
" delete[] *dataPtr;\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void isAutoDealloc() {
|
||||
check("void f() {\n"
|
||||
" char *p = new char[100];"
|
||||
|
|
|
@ -57,7 +57,6 @@ private:
|
|||
TEST_CASE(toDoubleNumber);
|
||||
TEST_CASE(naninf);
|
||||
TEST_CASE(isNullValue);
|
||||
TEST_CASE(incdec);
|
||||
TEST_CASE(sin);
|
||||
TEST_CASE(cos);
|
||||
TEST_CASE(tan);
|
||||
|
@ -1192,27 +1191,6 @@ private:
|
|||
ASSERT_EQUALS(false, MathLib::isNullValue("-ENOMEM"));
|
||||
}
|
||||
|
||||
void incdec() const {
|
||||
// increment
|
||||
{
|
||||
const MathLib::biguint num = ~10U;
|
||||
const std::string op = "++";
|
||||
const std::string strNum = MathLib::incdec(MathLib::toString(num), op);
|
||||
const MathLib::biguint incrementedNum = MathLib::toULongNumber(strNum);
|
||||
ASSERT_EQUALS(num + 1U, incrementedNum);
|
||||
}
|
||||
// decrement
|
||||
{
|
||||
const MathLib::biguint num = ~10U;
|
||||
const std::string op = "--";
|
||||
const std::string strNum = MathLib::incdec(MathLib::toString(num), op);
|
||||
const MathLib::biguint decrementedNum = MathLib::toULongNumber(strNum);
|
||||
ASSERT_EQUALS(num - 1U, decrementedNum);
|
||||
}
|
||||
// invalid operation
|
||||
ASSERT_THROW(MathLib::incdec("1", "x"), InternalError); // throw
|
||||
}
|
||||
|
||||
void sin() const {
|
||||
ASSERT_EQUALS("0.0", MathLib::sin("0"));
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
TEST_CASE(zeroDiv11);
|
||||
TEST_CASE(zeroDiv12);
|
||||
TEST_CASE(zeroDiv13);
|
||||
TEST_CASE(zeroDiv14); // #1169
|
||||
|
||||
TEST_CASE(zeroDivCond); // division by zero / useless condition
|
||||
|
||||
|
@ -587,6 +588,17 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:4]: (error) Division by zero.\n", errout.str());
|
||||
}
|
||||
|
||||
void zeroDiv14() {
|
||||
check("void f() {\n" // #1169
|
||||
" double dx = 1.;\n"
|
||||
" int ix = 1;\n"
|
||||
" int i = 1;\n"
|
||||
" std::cout << ix / (i >> 1) << std::endl;\n"
|
||||
" std::cout << dx / (i >> 1) << std::endl;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (error) Division by zero.\n", errout.str());
|
||||
}
|
||||
|
||||
void zeroDivCond() {
|
||||
check("void f(unsigned int x) {\n"
|
||||
" int y = 17 / x;\n"
|
||||
|
|
|
@ -101,9 +101,7 @@ private:
|
|||
TEST_CASE(simplifyArrayAccessSyntax);
|
||||
|
||||
TEST_CASE(pointeralias1);
|
||||
TEST_CASE(pointeralias2);
|
||||
TEST_CASE(pointeralias3);
|
||||
TEST_CASE(pointeralias4);
|
||||
|
||||
// struct ABC { } abc; => struct ABC { }; ABC abc;
|
||||
TEST_CASE(simplifyStructDecl1);
|
||||
|
@ -137,58 +135,36 @@ private:
|
|||
TEST_CASE(simplifyNamespaceAliases1);
|
||||
TEST_CASE(simplifyNamespaceAliases2); // ticket #10281
|
||||
|
||||
TEST_CASE(simplifyKnownVariables1);
|
||||
TEST_CASE(simplifyKnownVariables2);
|
||||
TEST_CASE(simplifyKnownVariables3);
|
||||
TEST_CASE(simplifyKnownVariables4);
|
||||
TEST_CASE(simplifyKnownVariables5);
|
||||
TEST_CASE(simplifyKnownVariables6);
|
||||
TEST_CASE(simplifyKnownVariables7);
|
||||
TEST_CASE(simplifyKnownVariables8);
|
||||
TEST_CASE(simplifyKnownVariables9);
|
||||
TEST_CASE(simplifyKnownVariables10);
|
||||
TEST_CASE(simplifyKnownVariables11);
|
||||
TEST_CASE(simplifyKnownVariables13);
|
||||
TEST_CASE(simplifyKnownVariables14);
|
||||
TEST_CASE(simplifyKnownVariables15);
|
||||
TEST_CASE(simplifyKnownVariables16);
|
||||
TEST_CASE(simplifyKnownVariables17);
|
||||
TEST_CASE(simplifyKnownVariables18);
|
||||
TEST_CASE(simplifyKnownVariables19);
|
||||
TEST_CASE(simplifyKnownVariables20);
|
||||
TEST_CASE(simplifyKnownVariables21);
|
||||
TEST_CASE(simplifyKnownVariables22);
|
||||
TEST_CASE(simplifyKnownVariables23);
|
||||
TEST_CASE(simplifyKnownVariables25);
|
||||
TEST_CASE(simplifyKnownVariables27);
|
||||
TEST_CASE(simplifyKnownVariables28);
|
||||
// FIXME Does expression id handle these? TEST_CASE(simplifyKnownVariables29); // ticket #1811
|
||||
TEST_CASE(simplifyKnownVariables30);
|
||||
TEST_CASE(simplifyKnownVariables31);
|
||||
TEST_CASE(simplifyKnownVariables32); // const
|
||||
TEST_CASE(simplifyKnownVariables33); // struct variable
|
||||
TEST_CASE(simplifyKnownVariables34);
|
||||
TEST_CASE(simplifyKnownVariables36); // ticket #2304 - known value for strcpy parameter
|
||||
TEST_CASE(simplifyKnownVariables39);
|
||||
TEST_CASE(simplifyKnownVariables41); // p=&x; if (p) ..
|
||||
TEST_CASE(simplifyKnownVariables42); // ticket #2031 - known string value after strcpy
|
||||
TEST_CASE(simplifyKnownVariables43);
|
||||
TEST_CASE(simplifyKnownVariables44); // ticket #3117 - don't simplify static variables
|
||||
TEST_CASE(simplifyKnownVariables45); // ticket #3281 - static constant variable not simplified
|
||||
TEST_CASE(simplifyKnownVariables46); // ticket #3587 - >>
|
||||
TEST_CASE(simplifyKnownVariables47); // ticket #3627 - >>
|
||||
TEST_CASE(simplifyKnownVariables48); // ticket #3754 - wrong simplification in for loop header
|
||||
TEST_CASE(simplifyKnownVariables49); // #3691 - continue in switch
|
||||
TEST_CASE(simplifyKnownVariables50); // #4066 sprintf changes
|
||||
TEST_CASE(simplifyKnownVariables51); // #4409 hang
|
||||
TEST_CASE(simplifyKnownVariables53); // references
|
||||
TEST_CASE(simplifyKnownVariables54); // #4913 'x' is not 0 after *--x=0;
|
||||
TEST_CASE(simplifyKnownVariables55); // pointer alias
|
||||
TEST_CASE(simplifyKnownVariables56); // ticket #5301 - >>
|
||||
TEST_CASE(simplifyKnownVariables57); // ticket #4724
|
||||
TEST_CASE(simplifyKnownVariables58); // ticket #5268
|
||||
TEST_CASE(simplifyKnownVariables59); // skip for header
|
||||
TEST_CASE(simplifyKnownVariables60); // #6829
|
||||
TEST_CASE(simplifyKnownVariables61); // #7805
|
||||
TEST_CASE(simplifyKnownVariables62); // #5666 - p=&str[0]
|
||||
TEST_CASE(simplifyKnownVariables63); // #10798
|
||||
|
@ -203,11 +179,8 @@ private:
|
|||
TEST_CASE(simplifyKnownVariablesClassMember); // #2815 - value of class member may be changed by function call
|
||||
TEST_CASE(simplifyKnownVariablesFunctionCalls); // Function calls (don't assume pass by reference)
|
||||
TEST_CASE(simplifyKnownVariablesGlobalVars);
|
||||
TEST_CASE(simplifyKnownVariablesPointerAliasFunctionCall); // #7440
|
||||
TEST_CASE(simplifyKnownVariablesNamespace); // #10059
|
||||
|
||||
TEST_CASE(simplify_constants2);
|
||||
TEST_CASE(simplify_constants4);
|
||||
TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter
|
||||
TEST_CASE(simplifyVarDeclInitLists);
|
||||
}
|
||||
|
@ -2607,16 +2580,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void pointeralias2() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" int *p = &i;\n"
|
||||
" return *p;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS("void f ( ) { int i ; int * p ; return i ; }", tok(code));
|
||||
}
|
||||
|
||||
void pointeralias3() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -2635,18 +2598,6 @@ private:
|
|||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
void pointeralias4() {
|
||||
const char code[] = "int f()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" int *p = &i;\n"
|
||||
" *p = 5;\n"
|
||||
" return i;\n"
|
||||
"}\n";
|
||||
const char expected[] = "int f ( ) { int i ; int * p ; i = 5 ; return 5 ; }";
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
void simplifyStructDecl1() {
|
||||
{
|
||||
const char code[] = "struct ABC { } abc;";
|
||||
|
@ -3228,37 +3179,9 @@ private:
|
|||
std::istringstream istr(code);
|
||||
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
|
||||
|
||||
(tokenizer.simplifyKnownVariables)();
|
||||
|
||||
return tokenizer.tokens()->stringifyList(nullptr, false);
|
||||
}
|
||||
|
||||
void simplifyKnownVariables1() {
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" int a = 10;\n"
|
||||
" if (a);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void f ( ) { int a ; a = 10 ; if ( 10 ) { ; } }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" int a = 10;\n"
|
||||
" if (!a);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void f ( ) { int a ; a = 10 ; if ( ! 10 ) { ; } }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables2() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -3313,136 +3236,6 @@ private:
|
|||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables6() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" char str[2];"
|
||||
" int a = 4;\n"
|
||||
" str[a] = 0;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void f ( ) { char str [ 2 ] ; int a ; a = 4 ; str [ 4 ] = 0 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables7() {
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int i = 22;\n"
|
||||
" abc[i++] = 1;\n"
|
||||
" abc[++i] = 2;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int i ; i = 24 ; abc [ 22 ] = 1 ; abc [ 24 ] = 2 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables8() {
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int i = 22;\n"
|
||||
" i++;\n"
|
||||
" abc[i] = 0;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int i ; i = 23 ; abc [ 23 ] = 0 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables9() {
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int a = 1, b = 2;\n"
|
||||
" if (a < b)\n"
|
||||
" ;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int a ; a = 1 ; int b ; b = 2 ; if ( 1 < 2 ) { ; } }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables10() {
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" bool b=false;\n"
|
||||
"\n"
|
||||
" {\n"
|
||||
" b = true;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( b )\n"
|
||||
" {\n"
|
||||
" a();\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const std::string expected1("void f ( ) {"
|
||||
" bool b ; b = false ;"
|
||||
" { b = true ; }");
|
||||
|
||||
TODO_ASSERT_EQUALS(
|
||||
expected1 + " if ( true ) { a ( ) ; } }",
|
||||
expected1 + " if ( b ) { a ( ) ; } }",
|
||||
simplifyKnownVariables(code));
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" bool b=false;\n"
|
||||
" { b = false; }\n"
|
||||
" {\n"
|
||||
" b = true;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( b )\n"
|
||||
" {\n"
|
||||
" a();\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
TODO_ASSERT_EQUALS(
|
||||
"void f ( ) { bool b ; b = false ; { b = false ; } { b = true ; } if ( true ) { a ( ) ; } }",
|
||||
"void f ( ) { bool b ; b = false ; { b = false ; } { b = true ; } if ( b ) { a ( ) ; } }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" int b=0;\n"
|
||||
" b = 1;\n"
|
||||
" for( int i = 0; i < 10; i++ )"
|
||||
" {\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return b;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void f ( ) { int b ; b = 0 ; b = 1 ; for ( int i = 0 ; i < 10 ; i ++ ) { } return 1 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables11() {
|
||||
const char code[] = "const int foo = 0;\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" int foo=0;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"int main ( ) { int foo ; foo = 0 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables13() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -3461,32 +3254,6 @@ private:
|
|||
ASSERT_EQUALS(code, simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables15() {
|
||||
{
|
||||
const char code[] = "int main()\n"
|
||||
"{\n"
|
||||
" int x=5;\n"
|
||||
" std::cout << 10 / x << std::endl;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"int main ( ) { int x ; x = 5 ; std :: cout << 10 / 5 << std :: endl ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "int main()\n"
|
||||
"{\n"
|
||||
" int x=5;\n"
|
||||
" std::cout << x / ( x == 1 ) << std::endl;\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"int main ( ) { int x ; x = 5 ; std :: cout << 5 / ( 5 == 1 ) << std :: endl ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables16() {
|
||||
// ticket #807 - segmentation fault when macro isn't found
|
||||
const char code[] = "void f ( ) { int n = 1; DISPATCH(while); }";
|
||||
|
@ -3515,111 +3282,12 @@ private:
|
|||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables20() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
" if (x) {\n"
|
||||
" if (i) i=0;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void f ( ) { int i ; i = 0 ; if ( x ) { if ( 0 ) { i = 0 ; } } }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables21() {
|
||||
const char code[] = "void foo() { int n = 10; for (int i = 0; i < n; ++i) { } }";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int n ; n = 10 ; for ( int i = 0 ; i < 10 ; ++ i ) { } }",
|
||||
simplifyKnownVariables(code));
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( int i ) { int n ; n = i ; for ( i = 0 ; i < n ; ++ i ) { } }",
|
||||
simplifyKnownVariables("void foo(int i) { int n = i; for (i = 0; i < n; ++i) { } }"));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables22() {
|
||||
// This testcase is related to ticket #1169
|
||||
{
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int n = 10;\n"
|
||||
" i = (n >> 1);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int n ; n = 10 ; i = 10 >> 1 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
{
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int n = 10;\n"
|
||||
" i = (n << 1);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int n ; n = 10 ; i = 10 << 1 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
{
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int n = 10;\n"
|
||||
" i = (1 << n);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int n ; n = 10 ; i = 1 << 10 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
{
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int n = 10;\n"
|
||||
" i = (1 >> n);\n"
|
||||
"}\n";
|
||||
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) { int n ; n = 10 ; i = 1 >> 10 ; }",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables23() {
|
||||
// This testcase is related to ticket #1596
|
||||
const char code[] = "void foo(int x)\n"
|
||||
"{\n"
|
||||
" int a[10], c = 0;\n"
|
||||
" if (x) {\n"
|
||||
" a[c] = 0;\n"
|
||||
" c++;\n"
|
||||
" } else {\n"
|
||||
" a[c] = 0;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
TODO_ASSERT_EQUALS(
|
||||
"void foo ( int x ) "
|
||||
"{"
|
||||
" int a [ 10 ] ; int c ; c = 0 ;"
|
||||
" if ( x ) { a [ 0 ] = 0 ; c = 1 ; }"
|
||||
" else { a [ 0 ] = 0 ; } "
|
||||
"}",
|
||||
|
||||
"void foo ( int x ) "
|
||||
"{"
|
||||
" int a [ 10 ] ; int c ; c = 0 ;"
|
||||
" if ( x ) { a [ 0 ] = 0 ; c ++ ; }"
|
||||
" else { a [ c ] = 0 ; } "
|
||||
"}",
|
||||
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables25() {
|
||||
{
|
||||
// This testcase is related to ticket #1646
|
||||
|
@ -3672,43 +3340,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables27() {
|
||||
// This testcase is related to ticket #1633
|
||||
const char code[] = "void foo()\n"
|
||||
"{\n"
|
||||
" int i1 = 1;\n"
|
||||
" int i2 = 2;\n"
|
||||
" int i3 = (i1 + i2) * 3;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( ) "
|
||||
"{"
|
||||
" int i1 ; i1 = 1 ;"
|
||||
" int i2 ; i2 = 2 ;"
|
||||
" int i3 ; i3 = ( 1 + 2 ) * 3 ; "
|
||||
"}",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables28() {
|
||||
const char code[] = "void foo(int g)\n"
|
||||
"{\n"
|
||||
" int i = 2;\n"
|
||||
" if (g) {\n"
|
||||
" }\n"
|
||||
" if (i > 0) {\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(
|
||||
"void foo ( int g ) "
|
||||
"{"
|
||||
" int i ; i = 2 ;"
|
||||
" if ( g ) { }"
|
||||
" if ( 2 > 0 ) { } "
|
||||
"}",
|
||||
simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables29() { // ticket #1811
|
||||
{
|
||||
const char code[] = "int foo(int u, int v)\n"
|
||||
|
@ -4049,48 +3680,6 @@ private:
|
|||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables31() {
|
||||
const char code[] = "void foo(const char str[]) {\n"
|
||||
" const char *p = str;\n"
|
||||
" if (p[0] == 0) {\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
const char expected[] = "void foo ( const char str [ ] ) {\n"
|
||||
"const char * p ; p = str ;\n"
|
||||
"if ( str [ 0 ] == 0 ) {\n"
|
||||
"}\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables32() {
|
||||
{
|
||||
const char code[] = "void foo() {\n"
|
||||
" const int x = 0;\n"
|
||||
" bar(0,x);\n"
|
||||
"}\n";
|
||||
const char expected[] = "void foo ( ) {\n\nbar ( 0 , 0 ) ;\n}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "static int const SZ = 22; char str[SZ];\n";
|
||||
ASSERT_EQUALS("char str [ 22 ] ;", tokenizeAndStringify(code,true));
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyKnownVariables33() {
|
||||
const char code[] = "static void foo(struct Foo *foo) {\n"
|
||||
" foo->a = 23;\n"
|
||||
" x[foo->a] = 0;\n"
|
||||
"}\n";
|
||||
const char expected[] = "static void foo ( struct Foo * foo ) {\n"
|
||||
"foo . a = 23 ;\n"
|
||||
"x [ 23 ] = 0 ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables34() {
|
||||
const char code[] = "void f() {\n"
|
||||
" int x = 10;\n"
|
||||
|
@ -4106,13 +3695,6 @@ private:
|
|||
}
|
||||
|
||||
void simplifyKnownVariables36() {
|
||||
// Ticket #2304
|
||||
const char code[] = "void f() {"
|
||||
" const char *q = \"hello\";"
|
||||
" strcpy(p, q);"
|
||||
"}";
|
||||
const char expected[] = "void f ( ) { const char * q ; q = \"hello\" ; strcpy ( p , \"hello\" ) ; }";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
|
||||
// Ticket #5972
|
||||
const char code2[] = "void f() {"
|
||||
|
@ -4123,50 +3705,7 @@ private:
|
|||
ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables39() {
|
||||
// Ticket #2296 - simplify pointer alias 'delete p;'
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" int *x;\n"
|
||||
" int *y = x;\n"
|
||||
" delete y;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( ) {\nint * x ;\nint * y ; y = x ;\ndelete x ;\n}", tokenizeAndStringify(code, true));
|
||||
}
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" int *x;\n"
|
||||
" int *y = x;\n"
|
||||
" delete [] y;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( ) {\nint * x ;\nint * y ; y = x ;\ndelete [ ] x ;\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 simplifyKnownVariables42() {
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" char str1[10], str2[10];\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 code[] = "void f() {\n"
|
||||
" char a[10];\n"
|
||||
|
@ -4261,20 +3800,6 @@ private:
|
|||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables45() {
|
||||
const char code[] = "class Fred {\n"
|
||||
"private:\n"
|
||||
" const static int NUM = 2;\n"
|
||||
" int array[NUM];\n"
|
||||
"}";
|
||||
const char expected[] = "class Fred {\n"
|
||||
"private:\n"
|
||||
"\n"
|
||||
"int array [ 2 ] ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables46() {
|
||||
const char code[] = "void f() {\n"
|
||||
" int x = 0;\n"
|
||||
|
@ -4335,45 +3860,6 @@ private:
|
|||
}
|
||||
|
||||
void simplifyKnownVariables50() { // #4066
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" char str1[10], str2[10];\n"
|
||||
" sprintf(str1, \"%%\");\n"
|
||||
" strcpy(str2, str1);\n"
|
||||
"}";
|
||||
const char expected[] = "void f ( ) {\n"
|
||||
"char str1 [ 10 ] ; char str2 [ 10 ] ;\n"
|
||||
"sprintf ( str1 , \"%%\" ) ;\n"
|
||||
"strcpy ( str2 , \"%\" ) ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" char str1[25], str2[25];\n"
|
||||
" sprintf(str1, \"abcdef%%%% and %% and %\");\n"
|
||||
" strcpy(str2, str1);\n"
|
||||
"}";
|
||||
const char expected[] = "void f ( ) {\n"
|
||||
"char str1 [ 25 ] ; char str2 [ 25 ] ;\n"
|
||||
"sprintf ( str1 , \"abcdef%%%% and %% and %\" ) ;\n"
|
||||
"strcpy ( str2 , \"abcdef%% and % and %\" ) ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" char str1[10], str2[10];\n"
|
||||
" sprintf(str1, \"abc\");\n"
|
||||
" strcpy(str2, str1);\n"
|
||||
"}";
|
||||
const char expected[] = "void f ( ) {\n"
|
||||
"char str1 [ 10 ] ; char str2 [ 10 ] ;\n"
|
||||
"sprintf ( str1 , \"abc\" ) ;\n"
|
||||
"strcpy ( str2 , \"abc\" ) ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||
}
|
||||
{
|
||||
//don't simplify '&x'!
|
||||
const char code[] = "const char * foo ( ) {\n"
|
||||
|
@ -4425,21 +3911,10 @@ private:
|
|||
ASSERT_THROW(tokenizeAndStringify(code, true), InternalError);
|
||||
}
|
||||
|
||||
void simplifyKnownVariables53() { // references
|
||||
ASSERT_EQUALS("void f ( ) { int x ; x = abc ( ) ; }", tokenizeAndStringify("void f() { int x; int &ref=x; ref=abc(); }", true));
|
||||
ASSERT_EQUALS("void f ( ) { int * p ; p = abc ( ) ; }", tokenizeAndStringify("void f() { int *p; int *&ref=p; ref=abc(); }", true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables54() { // #4913
|
||||
ASSERT_EQUALS("void f ( int * p ) { * -- p = 0 ; * p = 0 ; }", tokenizeAndStringify("void f(int*p) { *--p=0; *p=0; }", true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables55() { // pointer alias
|
||||
ASSERT_EQUALS("void f ( ) { int a ; int * p ; if ( a > 0 ) { } }", tokenizeAndStringify("void f() { int a; int *p=&a; if (*p>0) {} }", true));
|
||||
ASSERT_EQUALS("void f ( ) { int a ; struct AB ab ; ab . a = & a ; if ( a > 0 ) { } }", tokenizeAndStringify("void f() { int a; struct AB ab; ab.a = &a; if (*ab.a>0) {} }", true));
|
||||
ASSERT_EQUALS("void f ( ) { int a ; int * p ; if ( x > a ) { } }", tokenizeAndStringify("void f() { int a; int *p=&a; if (x>*p) {} }", true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables56() { // ticket #5301 - >>
|
||||
ASSERT_EQUALS("void f ( ) { int a ; a = 0 ; int b ; b = 0 ; * p >> a >> b ; return a / b ; }",
|
||||
tokenizeAndStringify("void f() { int a=0,b=0; *p>>a>>b; return a/b; }", true));
|
||||
|
@ -4485,21 +3960,6 @@ private:
|
|||
"}", tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables60() { // #6829
|
||||
const char code[] = "void f() {\n"
|
||||
" int i = 1;\n"
|
||||
" const int * const constPtrToConst = &i;\n"
|
||||
" std::cout << *constPtrToConst << std::endl;\n"
|
||||
" std::cout << constPtrToConst << std::endl;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( ) {\n"
|
||||
"int i ; i = 1 ;\n"
|
||||
"const int * const constPtrToConst ; constPtrToConst = & i ;\n"
|
||||
"std :: cout << i << std :: endl ;\n"
|
||||
"std :: cout << & i << std :: endl ;\n"
|
||||
"}", tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariables61() { // #7805
|
||||
tokenizeAndStringify("static const int XX = 0;\n"
|
||||
"enum E { XX };\n"
|
||||
|
@ -4679,22 +4139,6 @@ private:
|
|||
ASSERT_EQUALS("static int x ; void f ( ) { x = 123 ; while ( ! x ) { dostuff ( ) ; } }", tokenizeAndStringify(code,true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariablesPointerAliasFunctionCall() { // #7440
|
||||
const char code[] = "int main() {\n"
|
||||
" char* data = new char[100];\n"
|
||||
" char** dataPtr = &data;\n"
|
||||
" printf(\"test\");\n"
|
||||
" delete [] *dataPtr;\n"
|
||||
"}";
|
||||
const char exp[] = "int main ( ) {\n"
|
||||
"char * data ; data = new char [ 100 ] ;\n"
|
||||
"char * * dataPtr ; dataPtr = & data ;\n"
|
||||
"printf ( \"test\" ) ;\n"
|
||||
"delete [ ] data ;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS(exp, tokenizeAndStringify(code, /*simplify=*/ true));
|
||||
}
|
||||
|
||||
void simplifyKnownVariablesNamespace() {
|
||||
{ // #10059
|
||||
const char code[] = "namespace N {\n"
|
||||
|
@ -4785,25 +4229,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void simplify_constants2() {
|
||||
const char code[] =
|
||||
"void f( Foo &foo, Foo *foo2 ) {\n"
|
||||
"const int a = 45;\n"
|
||||
"foo.a=a+a;\n"
|
||||
"foo2->a=a;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( Foo & foo , Foo * foo2 ) { foo . a = 90 ; foo2 . a = 45 ; }", tok(code));
|
||||
}
|
||||
|
||||
void simplify_constants4() {
|
||||
const char code[] = "static const int bSize = 4;\n"
|
||||
"static const int aSize = 50;\n"
|
||||
"x = bSize;\n"
|
||||
"y = aSize;\n";
|
||||
ASSERT_EQUALS("x = 4 ; y = 50 ;", tok(code));
|
||||
}
|
||||
|
||||
void simplify_constants6() { // Ticket #5625
|
||||
{
|
||||
const char code[] = "template < class T > struct foo ;\n"
|
||||
|
|
Loading…
Reference in New Issue