From eed2e829a79931d8631b77763d651acdfb557d7e Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Sat, 30 May 2020 04:23:22 -0500 Subject: [PATCH] Revert "Cleanup: Removed Tokenizer::simplifyTokenList2. As a side-effect, rules for "simple" token list are now executed on normal token list." (#2666) This reverts commit 187cde183dfd7baea8cee270a0fccac18f6a945a. --- cli/cmdlineparser.cpp | 4 + lib/cppcheck.cpp | 18 +- lib/cppcheck.h | 7 + lib/settings.cpp | 1 + lib/settings.h | 3 + lib/tokenize.cpp | 2784 +++++++++++++++++++++++++- lib/tokenize.h | 179 +- test/testcmdlineparser.cpp | 9 + test/testsimplifytokens.cpp | 3654 +++++++++++++++++++++++++++++++++- test/testsimplifytypedef.cpp | 2 +- test/testtokenize.cpp | 2755 ++++++++++++++++++++++--- test/testvalueflow.cpp | 3 +- 12 files changed, 9069 insertions(+), 350 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 6a9206b3c..bd0f04dd3 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -258,6 +258,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strcmp(argv[i], "--debug-bug-hunting") == 0) mSettings->debugBugHunting = true; + // Flag used for various purposes during debugging + else if (std::strcmp(argv[i], "--debug-simplified") == 0) + mSettings->debugSimplified = true; + // Show template information else if (std::strcmp(argv[i], "--debug-template") == 0) mSettings->debugtemplate = true; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index bc210bf00..0b4349eb8 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -249,6 +249,7 @@ CppCheck::CppCheck(ErrorLogger &errorLogger, , mSuppressInternalErrorFound(false) , mUseGlobalSuppressions(useGlobalSuppressions) , mTooManyConfigs(false) + , mSimplify(true) , mExecuteCommand(executeCommand) { } @@ -384,7 +385,7 @@ unsigned int CppCheck::check(const std::string &path) clangimport::parseClangAstDump(&tokenizer, ast); ValueFlow::setValues(&tokenizer.list, const_cast(tokenizer.getSymbolDatabase()), this, &mSettings); if (mSettings.debugnormal) - tokenizer.printDebugOutput(); + tokenizer.printDebugOutput(1); checkNormalTokens(tokenizer); return mExitCode; } @@ -755,8 +756,18 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string checkUnusedFunctions.parseTokens(mTokenizer, filename.c_str(), &mSettings); // simplify more if required, skip rest of iteration if failed - if (hasRule("simple")) { - std::cout << "Handling of \"simple\" rules was removed in Cppcheck 2.1. Rule is executed on normal token list instead." << std::endl; + if (mSimplify && hasRule("simple")) { + std::cout << "Handling of \"simple\" rules is deprecated and will be removed in Cppcheck 2.5." << std::endl; + + // if further simplification fails then skip rest of iteration + Timer timer3("Tokenizer::simplifyTokenList2", mSettings.showtime, &s_timerResults); + result = mTokenizer.simplifyTokenList2(); + timer3.stop(); + if (!result) + continue; + + if (!Settings::terminated()) + executeRules("simple", mTokenizer); } } catch (const simplecpp::Output &o) { @@ -960,7 +971,6 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer) } executeRules("normal", tokenizer); - executeRules("simple", tokenizer); } } diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 6854beccc..fbdd95b18 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -128,6 +128,10 @@ public: void tooManyConfigsError(const std::string &file, const std::size_t numberOfConfigurations); void purgedConfigurationMessage(const std::string &file, const std::string& configuration); + void dontSimplify() { + mSimplify = false; + } + /** Analyse whole program, run this after all TUs has been scanned. * This is deprecated and the plan is to remove this when * .analyzeinfo is good enough. @@ -223,6 +227,9 @@ private: /** Are there too many configs? */ bool mTooManyConfigs; + /** Simplify code? true by default */ + bool mSimplify; + /** File info used for whole program analysis */ std::list mFileInfo; diff --git a/lib/settings.cpp b/lib/settings.cpp index aa3ae18e7..dd7760950 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -41,6 +41,7 @@ Settings::Settings() daca(false), debugBugHunting(false), debugnormal(false), + debugSimplified(false), debugtemplate(false), debugwarnings(false), dump(false), diff --git a/lib/settings.h b/lib/settings.h index 910e0a860..725885ddd 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -130,6 +130,9 @@ public: /** @brief Is --debug-normal given? */ bool debugnormal; + /** @brief Is --debug-simplified given? */ + bool debugSimplified; + /** @brief Is --debug-template given? */ bool debugtemplate; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6a78d5954..dc770111e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2375,7 +2375,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) mSymbolDatabase->setArrayDimensionsUsingValueFlow(); - printDebugOutput(); + printDebugOutput(1); return true; } @@ -4109,6 +4109,200 @@ void Tokenizer::sizeofAddParentheses() } } +bool Tokenizer::simplifySizeof() +{ + // Locate variable declarations and calculate the size + std::map sizeOfVar; + std::map declTokOfVar; + for (const Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->varId() != 0 && sizeOfVar.find(tok->varId()) == sizeOfVar.end()) { + const int varId = tok->varId(); + if (Token::Match(tok->tokAt(-3), "[;{}(,] %type% * %name% [;,)]") || + Token::Match(tok->tokAt(-4), "[;{}(,] const %type% * %name% [;),]") || + Token::Match(tok->tokAt(-2), "[;{}(,] %type% %name% [;),]") || + Token::Match(tok->tokAt(-3), "[;{}(,] const %type% %name% [;),]")) { + const int size = sizeOfType(tok->previous()); + if (size == 0) { + continue; + } + + sizeOfVar[varId] = size; + declTokOfVar[varId] = tok; + } + + else if (Token::Match(tok->previous(), "%type% %name% [ %num% ] [[;=]") || + Token::Match(tok->tokAt(-2), "%type% * %name% [ %num% ] [[;=]")) { + int size = sizeOfType(tok->previous()); + if (size == 0) + continue; + + const Token* tok2 = tok->next(); + do { + const MathLib::bigint num = MathLib::toLongNumber(tok2->strAt(1)); + if (num<0) + break; + size *= num; + tok2 = tok2->tokAt(3); + } while (Token::Match(tok2, "[ %num% ]")); + if (Token::Match(tok2, "[;=]")) { + sizeOfVar[varId] = size; + declTokOfVar[varId] = tok; + } + if (!tok2) { + syntaxError(tok); + } + tok = tok2; + } + + else if (Token::Match(tok->previous(), "%type% %name% [ %num% ] [,)]") || + Token::Match(tok->tokAt(-2), "%type% * %name% [ %num% ] [,)]")) { + Token tempTok; + tempTok.str("*"); + sizeOfVar[varId] = sizeOfType(&tempTok); + declTokOfVar[varId] = tok; + } + } + } + + bool ret = false; + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() != "sizeof") + continue; + + if (Token::simpleMatch(tok->next(), "...")) { + //tok->deleteNext(3); + tok->deleteNext(); + } + + // sizeof('x') + if (Token::Match(tok->next(), "( %char% )")) { + tok->deleteNext(); + tok->deleteThis(); + tok->deleteNext(); + std::ostringstream sz; + sz << ((isC()) ? mSettings->sizeof_int : 1); + tok->str(sz.str()); + ret = true; + continue; + } + + // sizeof ("text") + if (Token::Match(tok->next(), "( %str% )")) { + tok->deleteNext(); + tok->deleteThis(); + tok->deleteNext(); + std::ostringstream ostr; + ostr << (Token::getStrLength(tok) + 1); + tok->str(ostr.str()); + ret = true; + continue; + } + + // sizeof(type *) => sizeof(*) + if (Token::Match(tok->next(), "( %type% * )")) { + tok->next()->deleteNext(); + } + + if (Token::simpleMatch(tok->next(), "( * )")) { + tok->str(MathLib::toString(sizeOfType(tok->tokAt(2)))); + tok->deleteNext(3); + ret = true; + } + + // sizeof( a ) + else if (Token::Match(tok->next(), "( %var% )")) { + const std::map::const_iterator sizeOfVarPos = sizeOfVar.find(tok->tokAt(2)->varId()); + if (sizeOfVarPos != sizeOfVar.end()) { + tok->deleteNext(); + tok->deleteThis(); + tok->deleteNext(); + tok->str(MathLib::toString(sizeOfVarPos->second)); + ret = true; + } else { + // don't try to replace size of variable if variable has + // similar name with type (#329) + } + } + + else if (Token::Match(tok->next(), "( %type% )")) { + const int size = sizeOfType(tok->tokAt(2)); + if (size > 0) { + tok->str(MathLib::toString(size)); + tok->deleteNext(3); + ret = true; + } + } + + else if (Token::simpleMatch(tok->next(), "( *") || Token::Match(tok->next(), "( %name% [")) { + int derefs = 0; + + const Token* nametok = tok->tokAt(2); + if (nametok->str() == "*") { + do { + nametok = nametok->next(); + derefs++; + } while (nametok && nametok->str() == "*"); + + if (!Token::Match(nametok, "%name% )")) + continue; + } else { + const Token* tok2 = nametok->next(); + do { + tok2 = tok2->link()->next(); + derefs++; + } while (tok2 && tok2->str() == "["); + + if (!tok2 || tok2->str() != ")") + continue; + } + + // Some default value + MathLib::biguint size = 0; + + const int varid = nametok->varId(); + if (derefs != 0 && varid != 0 && declTokOfVar.find(varid) != declTokOfVar.end()) { + // Try to locate variable declaration.. + const Token *decltok = declTokOfVar[varid]; + if (Token::Match(decltok->previous(), "%type%|* %name% [")) { + size = sizeOfType(decltok->previous()); + } else if (Token::Match(decltok->tokAt(-2), "%type% * %name%")) { + size = sizeOfType(decltok->tokAt(-2)); + } + // Multi-dimensional array.. + if (Token::Match(decltok, "%name% [") && Token::simpleMatch(decltok->linkAt(1), "] [")) { + const Token *tok2 = decltok; + for (int i = 0; i < derefs; i++) + tok2 = tok2->linkAt(1); // Skip all dimensions that are dereferenced before the sizeof call + while (Token::Match(tok2, "] [ %num% ]")) { + size *= MathLib::toULongNumber(tok2->strAt(2)); + tok2 = tok2->linkAt(1); + } + if (Token::simpleMatch(tok2, "] [")) + continue; + } + } else if (nametok->strAt(1) == "[" && nametok->isStandardType()) { + size = sizeOfType(nametok); + if (size == 0) + continue; + const Token *tok2 = nametok->next(); + while (Token::Match(tok2, "[ %num% ]")) { + size *= MathLib::toULongNumber(tok2->strAt(1)); + tok2 = tok2->link()->next(); + } + if (!tok2 || tok2->str() != ")") + continue; + } + + if (size > 0) { + tok->str(MathLib::toString(size)); + Token::eraseTokens(tok, tok->next()->link()->next()); + ret = true; + } + } + } + return ret; +} + bool Tokenizer::simplifyTokenList1(const char FileName[]) { if (Settings::terminated()) @@ -4526,11 +4720,161 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) return true; } +bool Tokenizer::simplifyTokenList2() +{ + // clear the _functionList so it can't contain dead pointers + deleteSymbolDatabase(); + + // Clear AST,ValueFlow. These will be created again at the end of this function. + for (Token *tok = list.front(); tok; tok = tok->next()) { + tok->clearAst(); + tok->clearValueFlow(); + } + + // Convert e.g. atol("0") into 0 + simplifyMathFunctions(); + + // f(x=g()) => x=g(); f(x) + simplifyAssignmentInFunctionCall(); + + // ";a+=b;" => ";a=a+b;" + simplifyCompoundAssignment(); + + simplifyCharAt(); + + // simplify references + simplifyReference(); + + simplifyStd(); + + if (Settings::terminated()) + return false; + + simplifySizeof(); + + simplifyUndefinedSizeArray(); + + simplifyCasts(); + + // Simplify simple calculations before replace constants, this allows the replacement of constants that are calculated + // e.g. const static int value = sizeof(X)/sizeof(Y); + simplifyCalculations(); + + if (Settings::terminated()) + return false; + + // Replace "*(ptr + num)" => "ptr[num]" + simplifyOffsetPointerDereference(); + + // Replace "&str[num]" => "(str + num)" + simplifyOffsetPointerReference(); + + removeRedundantAssignment(); + + simplifyRealloc(); + + // Change initialisation of variable to assignment + simplifyInitVar(); + + // Simplify variable declarations + simplifyVarDecl(false); + + simplifyErrNoInWhile(); + simplifyIfAndWhileAssign(); + simplifyRedundantParentheses(); + simplifyNestedStrcat(); + simplifyFuncInWhile(); + + simplifyIfAndWhileAssign(); + + // replace strlen(str) + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "strlen ( %str% )")) { + tok->str(MathLib::toString(Token::getStrLength(tok->tokAt(2)))); + tok->deleteNext(3); + } + } + + bool modified = true; + while (modified) { + if (Settings::terminated()) + return false; + + modified = false; + modified |= simplifyConditions(); + modified |= simplifyFunctionReturn(); + modified |= simplifyKnownVariables(); + modified |= simplifyStrlen(); + + modified |= removeRedundantConditions(); + modified |= simplifyRedundantParentheses(); + modified |= simplifyConstTernaryOp(); + modified |= simplifyCalculations(); + validate(); + } + + // simplify redundant loops + simplifyWhile0(); + removeRedundantFor(); + + // Remove redundant parentheses in return.. + for (Token *tok = list.front(); tok; tok = tok->next()) { + while (Token::simpleMatch(tok, "return (")) { + Token *tok2 = tok->next()->link(); + if (Token::simpleMatch(tok2, ") ;")) { + tok->deleteNext(); + tok2->deleteThis(); + } else { + break; + } + } + } + + simplifyReturnStrncat(); + + removeRedundantAssignment(); + + simplifyComma(); + + removeRedundantSemicolons(); + + simplifyFlowControl(); + + simplifyRedundantConsecutiveBraces(); + + simplifyEmptyNamespaces(); + + simplifyMathFunctions(); + + validate(); + + Token::assignProgressValues(list.front()); + + list.createAst(); + // needed for #7208 (garbage code) and #7724 (ast max depth limit) + list.validateAst(); + + // Create symbol database and then remove const keywords + createSymbolDatabase(); + mSymbolDatabase->setValueTypeInTokenList(true); + + ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings); + + if (Settings::terminated()) + return false; + + printDebugOutput(2); + + return true; +} //--------------------------------------------------------------------------- -void Tokenizer::printDebugOutput() const +void Tokenizer::printDebugOutput(int simplification) const { - if (list.front() && mSettings->debugnormal) { + const bool debug = (simplification != 1U && mSettings->debugSimplified) || + (simplification != 2U && mSettings->debugnormal); + + if (debug && list.front()) { list.front()->printOut(nullptr, list.getFiles()); if (mSettings->xml) @@ -4553,7 +4897,7 @@ void Tokenizer::printDebugOutput() const std::cout << "" << std::endl; } - if (mSymbolDatabase && mSettings->debugwarnings) { + if (mSymbolDatabase && simplification == 2U && mSettings->debugwarnings) { printUnknownTypes(); // the typeStartToken() should come before typeEndToken() @@ -4912,6 +5256,104 @@ void Tokenizer::addSemicolonAfterUnknownMacro() } //--------------------------------------------------------------------------- +void Tokenizer::removeRedundantAssignment() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() == "{") + tok = tok->link(); + + const Token * const start = const_cast(startOfExecutableScope(tok)); + if (start) { + tok = start->previous(); + // parse in this function.. + std::set localvars; + const Token * const end = tok->next()->link(); + for (Token * tok2 = tok->next(); tok2 && tok2 != end; tok2 = tok2->next()) { + // skip local class or struct + if (Token::Match(tok2, "class|struct %type% {|:")) { + // skip to '{' + tok2 = tok2->tokAt(2); + while (tok2 && tok2->str() != "{") + tok2 = tok2->next(); + + if (tok2) + tok2 = tok2->link(); // skip local class or struct + else + return; + } else if (Token::Match(tok2, "[;{}] %type% * %name% ;") && tok2->next()->str() != "return") { + tok2 = tok2->tokAt(3); + localvars.insert(tok2->varId()); + } else if (Token::Match(tok2, "[;{}] %type% %name% ;") && tok2->next()->isStandardType()) { + tok2 = tok2->tokAt(2); + localvars.insert(tok2->varId()); + } else if (tok2->varId() && + !Token::Match(tok2->previous(), "[;{}] %name% = %char%|%num%|%name% ;")) { + localvars.erase(tok2->varId()); + } + } + localvars.erase(0); + if (!localvars.empty()) { + for (Token *tok2 = tok->next(); tok2 && tok2 != end;) { + if (Token::Match(tok2, "[;{}] %type% %name% ;") && localvars.find(tok2->tokAt(2)->varId()) != localvars.end()) { + tok2->deleteNext(3); + } else if ((Token::Match(tok2, "[;{}] %type% * %name% ;") && + localvars.find(tok2->tokAt(3)->varId()) != localvars.end()) || + (Token::Match(tok2, "[;{}] %name% = %any% ;") && + localvars.find(tok2->next()->varId()) != localvars.end())) { + tok2->deleteNext(4); + } else + tok2 = tok2->next(); + } + } + } + } +} + +void Tokenizer::simplifyRealloc() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "(|[") || + (tok->str() == "{" && tok->previous() && tok->previous()->str() == "=")) + tok = tok->link(); + else if (Token::Match(tok, "[;{}] %name% = realloc (")) { + tok = tok->tokAt(3); + if (Token::simpleMatch(tok->next(), "( 0 ,")) { + //no "x = realloc(0,);" + if (!Token::simpleMatch(tok->next()->link(), ") ;") || tok->next()->link()->previous() == tok->tokAt(3)) + continue; + + // delete "0 ," + tok->next()->deleteNext(2); + + // Change function name "realloc" to "malloc" + tok->str("malloc"); + tok = tok->next()->link(); + } else { + Token *tok2 = tok->next()->link()->tokAt(-2); + //no "x = realloc(,0);" + if (!Token::simpleMatch(tok2, ", 0 ) ;") || tok2 == tok->tokAt(2)) + continue; + + //remove ", 0" + tok2 = tok2->previous(); + tok2->deleteNext(2); + //change "realloc" to "free" + tok->str("free"); + //insert "0" after "var =" + tok = tok->previous(); + tok->insertToken("0"); + //move "var = 0" between "free(...)" and ";" + tok2 = tok2->next(); + Token::move(tok->previous(), tok->next(), tok2); + //add missing ";" after "free(...)" + tok2->insertToken(";"); + //goto before last ";" and continue + tok = tok->next(); + } + } + } +} + void Tokenizer::simplifyEmptyNamespaces() { if (isC()) @@ -4945,6 +5387,231 @@ void Tokenizer::simplifyEmptyNamespaces() } } +void Tokenizer::simplifyFlowControl() +{ + for (Token *begin = list.front(); begin; begin = begin->next()) { + + if (Token::Match(begin, "(|[") || + (begin->str() == "{" && begin->previous() && begin->strAt(-1) == "=")) + begin = begin->link(); + + //function scope + if (!Token::simpleMatch(begin, ") {") && !Token::Match(begin, ") %name% {")) + continue; + + Token* end = begin->linkAt(1+(begin->next()->str() == "{" ? 0 : 1)); + int indentLevel = 0; + bool stilldead = false; + + for (Token *tok = begin; tok && tok != end; tok = tok->next()) { + if (Token::Match(tok, "(|[")) { + tok = tok->link(); + continue; + } + + if (tok->str() == "{") { + if (tok->previous() && tok->previous()->str() == "=") { + tok = tok->link(); + continue; + } + ++indentLevel; + } else if (tok->str() == "}") { + if (indentLevel == 0) + break; + --indentLevel; + if (stilldead) { + eraseDeadCode(tok, nullptr); + if (indentLevel == 1 || tok->next()->str() != "}" || !Token::Match(tok->next()->link()->previous(), ";|{|}|do {")) + stilldead = false; + continue; + } + } + + if (indentLevel == 0) + continue; + + if (Token::Match(tok,"continue|break ;")) { + tok = tok->next(); + eraseDeadCode(tok, nullptr); + + } else if (Token::Match(tok,"return|goto") || + (Token::Match(tok->previous(), "[;{}] %name% (") && + mSettings->library.isnoreturn(tok)) || + (isCPP() && tok->str() == "throw")) { + if (tok->next()->str() == "}") + syntaxError(tok->next()); // invalid code like in #6731 + //TODO: ensure that we exclude user-defined 'exit|abort|throw', except for 'noreturn' + //catch the first ';' + for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { + if (Token::Match(tok2, "(|[")) { + tok2 = tok2->link(); + } else if (tok2->str() == ";") { + tok = tok2; + eraseDeadCode(tok, nullptr); + break; + } else if (Token::Match(tok2, "[{}]")) + break; + } + //if everything is removed, then remove also the code after an inferior scope + //only if the actual scope is not special + if (indentLevel > 1 && tok->next()->str() == "}" && Token::Match(tok->next()->link()->previous(), ";|{|}|do {")) + stilldead = true; + } + } + begin = end; + } +} + + +bool Tokenizer::removeRedundantConditions() +{ + // Return value for function. Set to true if there are any simplifications + bool ret = false; + + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!Token::Match(tok, "if ( %bool% ) {")) + continue; + + // Find matching else + Token *elseTag = tok->linkAt(4)->next(); + + const bool boolValue = (tok->strAt(2) == "true"); + + // Handle if with else + if (Token::simpleMatch(elseTag, "else {")) { + // Handle else + if (!boolValue) { + // Convert "if( false ) {aaa;} else {bbb;}" => "{bbb;}" + + //remove '(false)' + tok->deleteNext(3); + //delete dead code inside scope + eraseDeadCode(tok, elseTag); + //remove 'else' + elseTag->deleteThis(); + //remove 'if' + tok->deleteThis(); + } else { + // Convert "if( true ) {aaa;} else {bbb;}" => "{aaa;}" + const Token *end = elseTag->next()->link()->next(); + + // Remove "else { bbb; }" + elseTag = elseTag->previous(); + eraseDeadCode(elseTag, end); + + // Remove "if( true )" + tok->deleteNext(3); + tok->deleteThis(); + } + + ret = true; + } + + // Handle if without else + else { + if (!boolValue) { + //remove '(false)' + tok->deleteNext(3); + //delete dead code inside scope + eraseDeadCode(tok, elseTag); + //remove 'if' + tok->deleteThis(); + } else { + // convert "if( true ) {aaa;}" => "{aaa;}" + tok->deleteNext(3); + tok->deleteThis(); + } + + ret = true; + } + } + + return ret; +} + +void Tokenizer::removeRedundantFor() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "[;{}] for ( %name% = %num% ; %name% < %num% ; ++| %name% ++| ) {") || + Token::Match(tok, "[;{}] for ( %type% %name% = %num% ; %name% < %num% ; ++| %name% ++| ) {")) { + // Same variable name.. + const Token* varTok = tok->tokAt(3); + const bool type = varTok->next()->isName(); + if (type) + varTok = varTok->next(); + const std::string varname(varTok->str()); + const int varid(varTok->varId()); + if (varname != varTok->strAt(4)) + continue; + const Token *vartok2 = tok->linkAt(2)->previous(); + if (vartok2->str() == "++") + vartok2 = vartok2->previous(); + else if (vartok2->strAt(-1) != "++") + continue; + if (varname != vartok2->str()) + continue; + + // Check that the difference of the numeric values is 1 + const MathLib::bigint num1(MathLib::toLongNumber(varTok->strAt(2))); + const MathLib::bigint num2(MathLib::toLongNumber(varTok->strAt(6))); + if (num1 + 1 != num2) + continue; + + // check how loop variable is used in loop.. + bool read = false; + bool write = false; + const Token* end = tok->linkAt(2)->next()->link(); + for (const Token *tok2 = tok->linkAt(2); tok2 != end; tok2 = tok2->next()) { + if (tok2->str() == varname) { + if (tok2->previous()->isArithmeticalOp() && + tok2->next() && + (tok2->next()->isArithmeticalOp() || tok2->next()->str() == ";")) { + read = true; + } else { + read = write = true; + break; + } + } + } + + // Simplify loop if loop variable isn't written + if (!write) { + Token* bodyBegin = tok->linkAt(2)->next(); + // remove "for (" + tok->deleteNext(2); + + // If loop variable is read then keep assignment before + // loop body.. + if (type) { + tok->insertToken("{"); + Token::createMutualLinks(tok->next(), bodyBegin->link()); + bodyBegin->deleteThis(); + tok = tok->tokAt(6); + } else if (read) { + // goto ";" + tok = tok->tokAt(4); + } else { + // remove "x = 0 ;" + tok->deleteNext(4); + } + + // remove "x < 1 ; x ++ )" + tok->deleteNext(7); + + if (!type) { + // Add assignment after the loop body so the loop variable + // get the correct end value + Token *tok2 = tok->next()->link(); + tok2->insertToken(";"); + tok2->insertToken(MathLib::toString(num2)); + tok2->insertToken("="); + tok2->insertToken(varname); + tok2->next()->varId(varid); + } + } + } + } +} void Tokenizer::removeRedundantSemicolons() @@ -5101,6 +5768,476 @@ Token *Tokenizer::simplifyAddBracesPair(Token *tok, bool commandWithCondition) return tokBracesEnd; } +void Tokenizer::simplifyCompoundAssignment() +{ + // Simplify compound assignments: + // "a+=b" => "a = a + b" + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!Token::Match(tok, "[;{}] (| *| (| %name%")) + continue; + if (tok->next()->str() == "return") + continue; + // backup current token.. + Token * const tok1 = tok; + + if (tok->next()->str() == "*") + tok = tok->next(); + + if (tok->next() && tok->next()->str() == "(") { + tok = tok->next()->link()->next(); + } else { + // variable.. + tok = tok->tokAt(2); + while (Token::Match(tok, ". %name%") || + Token::Match(tok, "[|(")) { + if (tok->str() == ".") + tok = tok->tokAt(2); + else { + // goto "]" or ")" + tok = tok->link(); + + // goto next token.. + tok = tok ? tok->next() : nullptr; + } + } + } + if (!tok) + break; + + // Is current token at a compound assignment: +=|-=|.. ? + const std::string &str = tok->str(); + std::string op; // operator used in assignment + if (tok->isAssignmentOp() && str.size() == 2) + op = str.substr(0, 1); + else if (tok->isAssignmentOp() && str.size() == 3) + op = str.substr(0, 2); + else { + tok = tok1; + continue; + } + + // Remove the whole statement if it says: "+=0;", "-=0;", "*=1;" or "/=1;" + if (Token::Match(tok, "+=|-= 0 ;") || + Token::simpleMatch(tok, "|= 0 ;") || + Token::Match(tok, "*=|/= 1 ;")) { + tok = tok1; + while (tok->next()->str() != ";") + tok->deleteNext(); + } else { + // Enclose the rhs in parentheses.. + if (!Token::Match(tok->tokAt(2), "[;)]")) { + // Only enclose rhs in parentheses if there is some operator + bool someOperator = false; + for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { + if (tok2->link() && Token::Match(tok2, "{|[|(")) + tok2 = tok2->link(); + + if (Token::Match(tok2->next(), "[;)]")) { + if (someOperator) { + tok->insertToken("("); + tok2->insertToken(")"); + Token::createMutualLinks(tok->next(), tok2->next()); + } + break; + } + + someOperator |= (tok2->isOp() || tok2->str() == "?"); + } + } + + // simplify the compound assignment.. + tok->str("="); + tok->insertToken(op); + + std::stack tokend; + for (Token *tok2 = tok->previous(); tok2 && tok2 != tok1; tok2 = tok2->previous()) { + // Don't duplicate ++ and --. Put preincrement in lhs. Put + // postincrement in rhs. + if (tok2->tokType() == Token::eIncDecOp) { + // pre increment/decrement => don't copy + if (tok2->next()->isName()) { + continue; + } + + // post increment/decrement => move from lhs to rhs + tok->insertToken(tok2->str()); + tok2->deleteThis(); + continue; + } + + // Copy token from lhs to rhs + tok->insertToken(tok2->str()); + tok->next()->varId(tok2->varId()); + if (Token::Match(tok->next(), "]|)|}")) + tokend.push(tok->next()); + else if (Token::Match(tok->next(), "(|[|{")) { + Token::createMutualLinks(tok->next(), tokend.top()); + tokend.pop(); + } + } + } + } +} + +bool Tokenizer::simplifyConditions() +{ + bool ret = false; + + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "! %bool%|%num%")) { + tok->deleteThis(); + if (Token::Match(tok, "0|false")) + tok->str("true"); + else + tok->str("false"); + + ret = true; + } + + if (Token::simpleMatch(tok, "&& true &&")) { + tok->deleteNext(2); + ret = true; + } + + else if (Token::simpleMatch(tok, "|| false ||")) { + tok->deleteNext(2); + ret = true; + } + + else if (Token::Match(tok, "(|&& true && true &&|)")) { + tok->deleteNext(2); + ret = true; + } + + else if (Token::Match(tok, "%oror%|( false %oror% false %oror%|)")) { + tok->deleteNext(2); + ret = true; + } + + else if (Token::simpleMatch(tok, "( true ||") || + Token::simpleMatch(tok, "( false &&")) { + Token::eraseTokens(tok->next(), tok->link()); + ret = true; + } + + else if (Token::simpleMatch(tok, "|| true )") || + Token::simpleMatch(tok, "&& false )")) { + tok = tok->next(); + Token::eraseTokens(tok->next()->link(), tok); + ret = true; + } + + else if (Token::simpleMatch(tok, "&& false &&") || + Token::simpleMatch(tok, "|| true ||")) { + //goto '(' + Token *tok2 = tok; + while (tok2 && tok2->previous()) { + if (tok2->previous()->str() == ")") + tok2 = tok2->previous()->link(); + else { + tok2 = tok2->previous(); + if (tok2->str() == "(") + break; + } + } + if (!tok2) + continue; + //move tok to 'true|false' position + tok = tok->next(); + //remove everything before 'true|false' + Token::eraseTokens(tok2, tok); + //remove everything after 'true|false' + Token::eraseTokens(tok, tok2->link()); + ret = true; + } + + // Change numeric constant in condition to "true" or "false" + if (Token::Match(tok, "if|while ( %num% )|%oror%|&&")) { + tok->tokAt(2)->str((tok->strAt(2) != "0") ? "true" : "false"); + ret = true; + } + if (Token::Match(tok, "&&|%oror% %num% )|%oror%|&&")) { + tok->next()->str((tok->next()->str() != "0") ? "true" : "false"); + ret = true; + } + + // Reduce "(%num% == %num%)" => "(true)"/"(false)" + if (Token::Match(tok, "&&|%oror%|(") && + (Token::Match(tok->next(), "%num% %any% %num%") || + Token::Match(tok->next(), "%bool% %any% %bool%")) && + Token::Match(tok->tokAt(4), "&&|%oror%|)|?")) { + std::string cmp = tok->strAt(2); + bool result = false; + if (tok->next()->isNumber()) { + // Compare numbers + + if (cmp == "==" || cmp == "!=") { + const std::string& op1(tok->next()->str()); + const std::string& op2(tok->strAt(3)); + + bool eq = false; + if (MathLib::isInt(op1) && MathLib::isInt(op2)) + eq = (MathLib::toLongNumber(op1) == MathLib::toLongNumber(op2)); + else { + eq = (op1 == op2); + + // It is inconclusive whether two unequal float representations are numerically equal + if (!eq && MathLib::isFloat(op1)) + cmp.clear(); + } + + if (cmp == "==") + result = eq; + else + result = !eq; + } else { + const double op1 = MathLib::toDoubleNumber(tok->next()->str()); + const double op2 = MathLib::toDoubleNumber(tok->strAt(3)); + if (cmp == ">=") + result = (op1 >= op2); + else if (cmp == ">") + result = (op1 > op2); + else if (cmp == "<=") + result = (op1 <= op2); + else if (cmp == "<") + result = (op1 < op2); + else + cmp.clear(); + } + } else { + // Compare boolean + const bool op1 = (tok->next()->str() == std::string("true")); + const bool op2 = (tok->strAt(3) == std::string("true")); + + if (cmp == "==") + result = (op1 == op2); + else if (cmp == "!=") + result = (op1 != op2); + else if (cmp == ">=") + result = (op1 >= op2); + else if (cmp == ">") + result = (op1 > op2); + else if (cmp == "<=") + result = (op1 <= op2); + else if (cmp == "<") + result = (op1 < op2); + else + cmp.clear(); + } + + if (! cmp.empty()) { + tok = tok->next(); + tok->deleteNext(2); + + tok->str(result ? "true" : "false"); + ret = true; + } + } + } + + return ret; +} + +bool Tokenizer::simplifyConstTernaryOp() +{ + bool ret = false; + const Token *templateParameterEnd = nullptr; // The end of the current template parameter list, if any + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() == "<" && TemplateSimplifier::templateParameters(tok)) + templateParameterEnd = tok->findClosingBracket(); + if (tok == templateParameterEnd) + templateParameterEnd = nullptr; // End of the current template parameter list + if (tok->str() != "?") + continue; + + if (!Token::Match(tok->tokAt(-2), "<|=|,|(|[|{|}|;|case|return %bool%|%num%") && + !Token::Match(tok->tokAt(-4), "<|=|,|(|[|{|}|;|case|return ( %bool%|%num% )")) + continue; + + const int offset = (tok->previous()->str() == ")") ? 2 : 1; + + if (tok->strAt(-2*offset) == "<") { + if (isC() || !TemplateSimplifier::templateParameters(tok->tokAt(-2*offset))) + continue; // '<' is less than; the condition is not a constant + } + + // Find the token ":" then go to the next token + Token *colon = skipTernaryOp(tok); + if (!colon || colon->previous()->str() != ":" || !colon->next()) + continue; + + //handle the GNU extension: "x ? : y" <-> "x ? x : y" + if (colon->previous() == tok->next()) + tok->insertToken(tok->strAt(-offset)); + + // go back before the condition, if possible + tok = tok->tokAt(-2); + if (offset == 2) { + // go further back before the "(" + tok = tok->tokAt(-2); + //simplify the parentheses + tok->deleteNext(); + tok->next()->deleteNext(); + } + + if (Token::Match(tok->next(), "false|0")) { + // Use code after colon, remove code before it. + Token::eraseTokens(tok, colon); + + tok = tok->next(); + ret = true; + } + + // The condition is true. Delete the operator after the ":".. + else { + // delete the condition token and the "?" + tok->deleteNext(2); + + int ternaryOplevel = 0; + for (const Token *endTok = colon; endTok; endTok = endTok->next()) { + if (Token::Match(endTok, "(|[|{")) + endTok = endTok->link(); + else if (endTok->str() == "<" && (endTok->strAt(1) == ">" || TemplateSimplifier::templateParameters(endTok))) + endTok = endTok->findClosingBracket(); + else if (endTok->str() == "?") + ++ternaryOplevel; + else if (Token::Match(endTok, ")|}|]|;|,|:|>")) { + if (endTok->str() == ":" && ternaryOplevel) + --ternaryOplevel; + else if (endTok->str() == ">" && !templateParameterEnd) + ; + else { + Token::eraseTokens(colon->tokAt(-2), endTok); + ret = true; + break; + } + } + } + } + } + return ret; +} + +void Tokenizer::simplifyUndefinedSizeArray() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "%type%")) { + Token *tok2 = tok->next(); + while (tok2 && tok2->str() == "*") + tok2 = tok2->next(); + if (!Token::Match(tok2, "%name% [ ] ;|[")) + continue; + + tok = tok2->previous(); + Token *end = tok2->next(); + int count = 0; + do { + end = end->tokAt(2); + ++count; + } while (Token::Match(end, "[ ] [;=[]")); + if (Token::Match(end, "[;=]")) { + do { + tok2->deleteNext(2); + tok->insertToken("*"); + } while (--count); + tok = end; + } else + tok = tok->tokAt(3); + } + } +} + +void Tokenizer::simplifyCasts() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + // Don't remove cast in such cases: + // *((char *)a + 1) = 0; + // Remove cast when casting a function pointer: + // (*(void (*)(char *))fp)(x); + if (!tok->isName() && + Token::simpleMatch(tok->next(), "* (") && + !Token::Match(tok->linkAt(2), ") %name%|&")) { + tok = tok->linkAt(2); + continue; + } + // #3935 : don't remove cast in such cases: + // ((char *)a)[1] = 0; + if (tok->str() == "(" && Token::simpleMatch(tok->link(), ") [")) { + tok = tok->link(); + continue; + } + // #4164 : ((unsigned char)1) => (1) + if (Token::Match(tok->next(), "( %type% ) %num%") && tok->next()->link()->previous()->isStandardType()) { + const MathLib::bigint value = MathLib::toLongNumber(tok->next()->link()->next()->str()); + int bits = mSettings->char_bit * mTypeSize[tok->next()->link()->previous()->str()]; + if (!tok->tokAt(2)->isUnsigned() && bits > 0) + bits--; + if (bits < 31 && value >= 0 && value < (1LL << bits)) { + tok->linkAt(1)->next()->isCast(true); + Token::eraseTokens(tok, tok->next()->link()->next()); + } + continue; + } + + while ((Token::Match(tok->next(), "( %type% *| *| *|&| ) *|&| %name%") && (tok->str() != ")" || tok->tokAt(2)->isStandardType())) || + Token::Match(tok->next(), "( const| %type% * *| *|&| ) *|&| %name%") || + Token::Match(tok->next(), "( const| %type% %type% *| *| *|&| ) *|&| %name%") || + (!tok->isName() && (Token::Match(tok->next(), "( %type% * *| *|&| ) (") || + Token::Match(tok->next(), "( const| %type% %type% * *| *|&| ) (")))) { + if (tok->isName() && tok->str() != "return") + break; + + if (isCPP() && tok->strAt(-1) == "operator") + break; + + // Remove cast.. + Token::eraseTokens(tok, tok->next()->link()->next()); + + // Set isCasted flag. + Token *tok2 = tok->next(); + if (!Token::Match(tok2, "%name% [|.")) + tok2->isCast(true); + else { + // TODO: handle more complex expressions + tok2->next()->isCast(true); + } + + // Remove '* &' + if (Token::simpleMatch(tok, "* &")) { + tok->deleteNext(); + tok->deleteThis(); + } + + if (tok->str() == ")" && tok->link()->previous()) { + // If there was another cast before this, go back + // there to check it also. e.g. "(int)(char)x" + tok = tok->link()->previous(); + } + } + + // Replace pointer casts of 0.. "(char *)0" => "0" + while (Token::Match(tok->next(), "( %type% %type%| * *| ) 0")) { + tok->linkAt(1)->next()->isCast(true); + Token::eraseTokens(tok, tok->next()->link()->next()); + if (tok->str() == ")" && tok->link()->previous()) { + // If there was another cast before this, go back + // there to check it also. e.g. "(char*)(char*)0" + tok = tok->link()->previous(); + } + } + + if (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) { + Token *tok2 = tok->linkAt(2); + if (!Token::simpleMatch(tok2, "> (")) + break; + + tok2->tokAt(2)->isCast(true); + Token::eraseTokens(tok, tok2->next()); + } + } +} + + void Tokenizer::simplifyFunctionParameters() { for (Token *tok = list.front(); tok; tok = tok->next()) { @@ -5396,6 +6533,40 @@ void Tokenizer::simplifyFunctionPointers() } +bool Tokenizer::simplifyFunctionReturn() +{ + std::map functions; + + for (const Token *tok = tokens(); tok; tok = tok->next()) { + if (tok->str() == "{") + tok = tok->link(); + + else if (Token::Match(tok, "%name% ( ) { return %bool%|%char%|%num%|%str% ; }") && tok->strAt(-1) != "::") { + const Token* const any = tok->tokAt(5); + functions[tok->str()] = any; + tok = any; + } + } + + if (functions.empty()) + return false; + + bool ret = false; + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "(|[|=|return|%op% %name% ( ) ;|]|)|%cop%")) { + tok = tok->next(); + auto it = functions.find(tok->str()); + if (it != functions.cend()) { + tok->str(it->second->str()); + tok->deleteNext(2); + ret = true; + } + } + } + + return ret; +} + void Tokenizer::simplifyVarDecl(const bool only_k_r_fpar) { simplifyVarDecl(list.front(), nullptr, only_k_r_fpar); @@ -5769,6 +6940,123 @@ void Tokenizer::simplifyStaticConst() } } +void Tokenizer::simplifyIfAndWhileAssign() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!Token::Match(tok->next(), "if|while (")) + continue; + + const Token* tokAt3 = tok->tokAt(3); + if (!Token::Match(tokAt3, "!| (| %name% =") && + !Token::Match(tokAt3, "!| (| %name% . %name% =") && + !Token::Match(tokAt3, "0 == (| %name% =") && + !Token::Match(tokAt3, "0 == (| %name% . %name% =")) + continue; + + // simplifying a "while(cond) { }" condition ? + const bool iswhile(tok->next()->str() == "while"); + + // simplifying a "do { } while(cond);" condition ? + const bool isDoWhile = iswhile && Token::simpleMatch(tok, "}") && Token::simpleMatch(tok->link()->previous(), "do"); + Token* openBraceTok = tok->link(); + + // delete the "if|while" + tok->deleteNext(); + + // Remember if there is a "!" or not. And delete it if there are. + const bool isNot(Token::Match(tok->tokAt(2), "!|0")); + if (isNot) + tok->next()->deleteNext((tok->strAt(2) == "0") ? 2 : 1); + + // Delete parentheses.. and remember how many there are with + // their links. + std::stack braces; + while (tok->next()->str() == "(") { + braces.push(tok->next()->link()); + tok->deleteNext(); + } + + // Skip the "%name% = ..." + Token *tok2; + for (tok2 = tok->next(); tok2; tok2 = tok2->next()) { + if (tok2->str() == "(") + tok2 = tok2->link(); + else if (tok2->str() == ")") + break; + } + + // Insert "; if|while ( .." + tok2 = tok2->previous(); + if (tok->strAt(2) == ".") { + tok2->insertToken(tok->strAt(3)); + tok2->next()->varId(tok->tokAt(3)->varId()); + tok2->insertToken("."); + } + tok2->insertToken(tok->next()->str()); + tok2->next()->varId(tok->next()->varId()); + + while (! braces.empty()) { + tok2->insertToken("("); + Token::createMutualLinks(tok2->next(), braces.top()); + braces.pop(); + } + + if (isNot) + tok2->next()->insertToken("!"); + tok2->insertToken(iswhile ? "while" : "if"); + if (isDoWhile) { + tok2->insertToken("}"); + Token::createMutualLinks(openBraceTok, tok2->next()); + } + + tok2->insertToken(";"); + + // delete the extra "}" + if (isDoWhile) + tok->deleteThis(); + + // If it's a while loop, insert the assignment in the loop + if (iswhile && !isDoWhile) { + int indentlevel = 0; + Token *tok3 = tok2; + + for (; tok3; tok3 = tok3->next()) { + if (tok3->str() == "{") + ++indentlevel; + else if (tok3->str() == "}") { + if (indentlevel <= 1) + break; + --indentlevel; + } + } + + if (tok3 && indentlevel == 1) { + tok3 = tok3->previous(); + std::stack braces2; + + for (tok2 = tok2->next(); tok2 && tok2 != tok; tok2 = tok2->previous()) { + tok3->insertToken(tok2->str()); + Token *newTok = tok3->next(); + + newTok->varId(tok2->varId()); + newTok->fileIndex(tok2->fileIndex()); + newTok->linenr(tok2->linenr()); + + // link() new tokens manually + if (tok2->link()) { + if (Token::Match(newTok, "}|)|]|>")) { + braces2.push(newTok); + } else { + Token::createMutualLinks(newTok, braces2.top()); + braces2.pop(); + } + } + } + } + } + } +} + void Tokenizer::simplifyVariableMultipleAssign() { for (Token *tok = list.front(); tok; tok = tok->next()) { @@ -5963,6 +7251,766 @@ Token * Tokenizer::initVar(Token * tok) } +bool Tokenizer::simplifyKnownVariables() +{ + // return value for function. Set to true if any simplifications are made + bool ret = false; + + // constants.. + { + std::unordered_map constantValues; + std::map constantVars; + std::unordered_map> 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 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 localvars; + std::set floatvars; + std::set arrays; + + // auto variables.. + for (Token *tok = list.front(); tok; tok = tok->next()) { + // Search for a block of code + Token * const start = const_cast(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()) { @@ -6200,11 +8248,177 @@ void Tokenizer::simplifyTypeIntrinsics() } } +void Tokenizer::simplifyCharAt() +{ + // Replace "string"[0] with 's' + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "%str% [ %num% ]")) { + const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(2)); + // Check within range + if (index >= 0 && index <= Token::getStrLength(tok)) { + tok->str("'" + Token::getCharAt(tok, index) + "'"); + tok->deleteNext(3); + } + } + } +} + +void Tokenizer::simplifyReference() +{ + if (isC()) + return; + + for (Token *tok = list.front(); tok; tok = tok->next()) { + // starting executable scope.. + Token *start = const_cast(startOfExecutableScope(tok)); + if (start) { + tok = start; + // replace references in this scope.. + Token * const end = tok->link(); + for (Token *tok2 = tok; tok2 && tok2 != end; tok2 = tok2->next()) { + // found a reference.. + if (Token::Match(tok2, "[;{}] %type% & %name% (|= %name% )| ;")) { + const int refId = tok2->tokAt(3)->varId(); + if (!refId) + continue; + + // replace reference in the code.. + for (Token *tok3 = tok2->tokAt(7); tok3 && tok3 != end; tok3 = tok3->next()) { + if (tok3->varId() == refId) { + tok3->str(tok2->strAt(5)); + tok3->varId(tok2->tokAt(5)->varId()); + } + } + + tok2->deleteNext(6+(tok2->strAt(6)==")" ? 1 : 0)); + } + } + tok = end; + } + } +} bool Tokenizer::simplifyCalculations() { return mTemplateSimplifier->simplifyCalculations(nullptr, nullptr, false); } + +void Tokenizer::simplifyOffsetPointerDereference() +{ + // Replace "*(str + num)" => "str[num]" and + // Replace "*(str - num)" => "str[-num]" + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!tok->isName() && !tok->isLiteral() + && !Token::Match(tok, "]|)|++|--") + && Token::Match(tok->next(), "* ( %name% +|- %num%|%name% )")) { + + // remove '* (' + tok->deleteNext(2); + + // '+'->'[' + tok = tok->tokAt(2); + Token* const openBraceTok = tok; + const bool isNegativeIndex = (tok->str() == "-"); + tok->str("["); + + // Insert a "-" in front of the number or variable + if (isNegativeIndex) { + if (tok->next()->isName()) { + tok->insertToken("-"); + tok = tok->next(); + } else + tok->next()->str(std::string("-") + tok->next()->str()); + } + + tok = tok->tokAt(2); + tok->str("]"); + Token::createMutualLinks(openBraceTok, tok); + } + } +} + +void Tokenizer::simplifyOffsetPointerReference() +{ + std::set pod; + for (const Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->isStandardType()) { + tok = tok->next(); + while (tok && (tok->str() == "*" || tok->isName())) { + if (tok->varId() > 0) { + pod.insert(tok->varId()); + break; + } + tok = tok->next(); + } + if (!tok) + break; + } + } + + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!Token::Match(tok, "%num%|%name%|]|)") && + (Token::Match(tok->next(), "& %name% [ %num%|%name% ] !!["))) { + tok = tok->next(); + + if (tok->next()->varId()) { + if (pod.find(tok->next()->varId()) == pod.end()) { + tok = tok->tokAt(5); + if (!tok) + syntaxError(tok); + continue; + } + } + + // '&' => '(' + tok->str("("); + + tok = tok->next(); + // '[' => '+' + tok->deleteNext(); + tok->insertToken("+"); + + tok = tok->tokAt(3); + //remove ']' + tok->str(")"); + Token::createMutualLinks(tok->tokAt(-4), tok); + } + } +} + +void Tokenizer::simplifyNestedStrcat() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (! Token::Match(tok, "[;{}] strcat ( strcat (")) { + continue; + } + + // find inner strcat call + Token *tok2 = tok->tokAt(3); + while (Token::simpleMatch(tok2, "strcat ( strcat")) + tok2 = tok2->tokAt(2); + + if (tok2->strAt(3) != ",") + continue; + + // If we have this code: + // strcat(strcat(dst, foo), bar); + // We move this part of code before all strcat() calls: strcat(dst, foo) + // And place "dst" token where the code was. + Token *prevTok = tok2->previous(); + + // Move tokens to new place + Token::move(tok2, tok2->next()->link(), tok); + tok = tok2->next()->link(); + + // Insert the "dst" token + prevTok->insertToken(tok2->strAt(2)); + prevTok->next()->varId(tok2->tokAt(2)->varId()); + + // Insert semicolon after the moved strcat() + tok->insertToken(";"); + } +} + // Check if this statement is a duplicate definition. A duplicate // definition will hide the enumerator within it's scope so just // skip the entire scope of the duplicate. @@ -6284,6 +8498,33 @@ bool Tokenizer::duplicateDefinition(Token ** tokPtr) return false; } +static const std::set stdFunctionsPresentInC = { + "strcat", + "strcpy", + "strncat", + "strncpy", + "free", + "malloc", + "strdup" +}; + +void Tokenizer::simplifyStd() +{ + if (isC()) + return; + + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() != "std") + continue; + + if (Token::Match(tok->previous(), "[(,{};] std :: %name% (") && + stdFunctionsPresentInC.find(tok->strAt(2)) != stdFunctionsPresentInC.end()) { + tok->deleteNext(); + tok->deleteThis(); + } + } +} + //--------------------------------------------------------------------------- // Helper functions for handling the tokens list //--------------------------------------------------------------------------- @@ -6581,13 +8822,13 @@ void Tokenizer::eraseDeadCode(Token *begin, const Token *end) void Tokenizer::syntaxError(const Token *tok, const std::string &code) const { - printDebugOutput(); + printDebugOutput(0); throw InternalError(tok, code.empty() ? "syntax error" : "syntax error: " + code, InternalError::SYNTAX); } void Tokenizer::unmatchedToken(const Token *tok) const { - printDebugOutput(); + printDebugOutput(0); throw InternalError(tok, "Unmatched '" + tok->str() + "'. Configuration: '" + mConfiguration + "'.", InternalError::SYNTAX); @@ -6595,13 +8836,13 @@ void Tokenizer::unmatchedToken(const Token *tok) const void Tokenizer::syntaxErrorC(const Token *tok, const std::string &what) const { - printDebugOutput(); + printDebugOutput(0); throw InternalError(tok, "Code '"+what+"' is invalid C code. Use --std or --language to configure the language.", InternalError::SYNTAX); } void Tokenizer::unknownMacroError(const Token *tok1) const { - printDebugOutput(); + printDebugOutput(0); throw InternalError(tok1, "There is an unknown macro here somewhere. Configuration is required. If " + tok1->str() + " is a macro then please configure it.", InternalError::UNKNOWN_MACRO); } @@ -6627,7 +8868,7 @@ void Tokenizer::macroWithSemicolonError(const Token *tok, const std::string &mac void Tokenizer::cppcheckError(const Token *tok) const { - printDebugOutput(); + printDebugOutput(0); throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL); } /** @@ -6684,6 +8925,312 @@ bool Tokenizer::isTwoNumber(const std::string &s) return isNumberOneOf(s, 2L, "2.0"); } +// ------------------------------------------------------ +// Simplify math functions. +// It simplifies the following functions: atol(), fmin(), +// fminl(), fminf(), fmax(), fmaxl(), fmaxf(), pow(), +// powf(), powl(), cbrt(), cbrtl(), cbtrf(), sqrt(), +// sqrtf(), sqrtl(), exp(), expf(), expl(), exp2(), +// exp2f(), exp2l(), log2(), log2f(), log2l(), log1p(), +// log1pf(), log1pl(), log10(), log10l(), log10f(), +// log(), logf(), logl(), logb(), logbf(), logbl(), acosh() +// acoshf(), acoshl(), acos(), acosf(), acosl(), cosh() +// coshf(), coshf(), cos(), cosf(), cosl(), erfc(), +// erfcf(), erfcl(), ilogb(), ilogbf(), ilogbf(), erf(), +// erfl(), erff(), asin(), asinf(), asinf(), asinh(), +// asinhf(), asinhl(), tan(), tanf(), tanl(), tanh(), +// tanhf(), tanhl(), atan(), atanf(), atanl(), atanh(), +// atanhf(), atanhl(), expm1(), expm1l(), expm1f(), sin(), +// sinf(), sinl(), sinh(), sinhf(), sinhl() +// in the tokenlist. +// +// Reference: +// - http://www.cplusplus.com/reference/cmath/ +// ------------------------------------------------------ +void Tokenizer::simplifyMathFunctions() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->isName() && !tok->varId() && tok->strAt(1) == "(") { // precondition for function + bool simplifcationMade = false; + if (Token::Match(tok, "atol ( %str% )")) { //@todo Add support for atoll() + if (Token::simpleMatch(tok->tokAt(-2), "std ::")) { + tok = tok->tokAt(-2);// set token index two steps back + tok->deleteNext(2); // delete "std ::" + } + const std::string& strNumber = tok->tokAt(2)->strValue(); // get number + const bool isNotAnInteger = (!MathLib::isInt(strNumber));// check: is not an integer + if (strNumber.empty() || isNotAnInteger) { + // Ignore strings which we can't convert + continue; + } + // Convert string into a number and insert into token list + tok->str(MathLib::toString(MathLib::toLongNumber(strNumber))); + // remove ( %num% ) + tok->deleteNext(3); + simplifcationMade = true; + } else if (Token::Match(tok, "sqrt|sqrtf|sqrtl|cbrt|cbrtf|cbrtl ( %num% )")) { + // Simplify: sqrt(0) = 0 and cbrt(0) == 0 + // sqrt(1) = 1 and cbrt(1) == 1 + // get number string + const std::string& parameter(tok->strAt(2)); + // is parameter 0 ? + if (isZeroNumber(parameter)) { + tok->deleteNext(3); // delete tokens + tok->str("0"); // insert result into token list + simplifcationMade = true; + } else if (isOneNumber(parameter)) { + tok->deleteNext(3); // delete tokens + tok->str("1"); // insert result into token list + simplifcationMade = true; + } + } else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l|cos|cosf|cosl|cosh|coshf|coshl|erfc|erfcf|erfcl ( %num% )")) { + // Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1 + // cosh[f|l](0) = 1 and cos[f|l](0) = 1 + // erfc[f|l](0) = 1 + // get number string + const std::string& parameter(tok->strAt(2)); + // is parameter 0 ? + if (isZeroNumber(parameter)) { + tok->deleteNext(3); // delete tokens + tok->str("1"); // insert result into token list + simplifcationMade = true; + } + } else if (Token::Match(tok, "log1p|log1pf|log1pl|sin|sinf|sinl|sinh|sinhf|sinhl|erf|erff|erfl|asin|asinf|asinl|asinh|asinhf|asinhl|tan|tanf|tanl|tanh|tanhf|tanhl|atan|atanf|atanl|atanh|atanhf|atanhl|expm1|expm1f|expm1l ( %num% )")) { + // Simplify: log1p[f|l](0) = 0 and sin[f|l](0) = 0 + // sinh[f|l](0) = 0 and erf[f|l](0) = 0 + // asin[f|l](0) = 0 and sinh[f|l](0) = 0 + // tan[f|l](0) = 0 and tanh[f|l](0) = 0 + // atan[f|l](0) = 0 and atanh[f|l](0)= 0 + // expm1[f|l](0) = 0 + // get number string + const std::string& parameter(tok->strAt(2)); + // is parameter 0 ? + if (isZeroNumber(parameter)) { + tok->deleteNext(3); // delete tokens + tok->str("0"); // insert result into token list + simplifcationMade = true; + } + } else if (Token::Match(tok, "log2|log2f|log2l|log|logf|logl|log10|log10f|log10l|logb|logbf|logbl|acosh|acoshf|acoshl|acos|acosf|acosl|ilogb|ilogbf|ilogbl ( %num% )")) { + // Simplify: log2[f|l](1) = 0 , log10[f|l](1) = 0 + // log[f|l](1) = 0 , logb10[f|l](1) = 0 + // acosh[f|l](1) = 0 , acos[f|l](1) = 0 + // ilogb[f|l](1) = 0 + // get number string + const std::string& parameter(tok->strAt(2)); + // is parameter 1 ? + if (isOneNumber(parameter)) { + tok->deleteNext(3); // delete tokens + tok->str("0"); // insert result into token list + simplifcationMade = true; + } + } else if (Token::Match(tok, "fmin|fminl|fminf ( %num% , %num% )")) { + // @todo if one of the parameters is NaN the other is returned + // e.g. printf ("fmin (NaN, -1.0) = %f\n", fmin(NaN,-1.0)); + // e.g. printf ("fmin (-1.0, NaN) = %f\n", fmin(-1.0,NaN)); + const std::string& strLeftNumber(tok->strAt(2)); + const std::string& strRightNumber(tok->strAt(4)); + const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); + // case: left <= right ==> insert left + if (isLessEqual) { + tok->str(strLeftNumber); // insert e.g. -1.0 + tok->deleteNext(5); // delete e.g. fmin ( -1.0, 1.0 ) + simplifcationMade = true; + } else { // case left > right ==> insert right + tok->str(strRightNumber); // insert e.g. 0.0 + tok->deleteNext(5); // delete e.g. fmin ( 1.0, 0.0 ) + simplifcationMade = true; + } + } else if (Token::Match(tok, "fmax|fmaxl|fmaxf ( %num% , %num% )")) { + // @todo if one of the parameters is NaN the other is returned + // e.g. printf ("fmax (NaN, -1.0) = %f\n", fmax(NaN,-1.0)); + // e.g. printf ("fmax (-1.0, NaN) = %f\n", fmax(-1.0,NaN)); + const std::string& strLeftNumber(tok->strAt(2)); + const std::string& strRightNumber(tok->strAt(4)); + const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); + // case: left <= right ==> insert right + if (isLessEqual) { + tok->str(strRightNumber);// insert e.g. 1.0 + tok->deleteNext(5); // delete e.g. fmax ( -1.0, 1.0 ) + simplifcationMade = true; + } else { // case left > right ==> insert left + tok->str(strLeftNumber); // insert e.g. 1.0 + tok->deleteNext(5); // delete e.g. fmax ( 1.0, 0.0 ) + simplifcationMade = true; + } + } else if (Token::Match(tok, "pow|powf|powl (")) { + if (Token::Match(tok->tokAt(2), "%num% , %num% )")) { + // In case of pow ( 0 , anyNumber > 0): It can be simplified to 0 + // In case of pow ( 0 , 0 ): It simplified to 1 + // In case of pow ( 1 , anyNumber ): It simplified to 1 + const std::string& leftNumber(tok->strAt(2)); // get the left parameter + const std::string& rightNumber(tok->strAt(4)); // get the right parameter + const bool isLeftNumberZero = isZeroNumber(leftNumber); + const bool isLeftNumberOne = isOneNumber(leftNumber); + const bool isRightNumberZero = isZeroNumber(rightNumber); + if (isLeftNumberZero && !isRightNumberZero && MathLib::isPositive(rightNumber)) { // case: 0^(y) = 0 and y > 0 + tok->deleteNext(5); // delete tokens + tok->str("0"); // insert simplified result + simplifcationMade = true; + } else if (isLeftNumberZero && isRightNumberZero) { // case: 0^0 = 1 + tok->deleteNext(5); // delete tokens + tok->str("1"); // insert simplified result + simplifcationMade = true; + } else if (isLeftNumberOne) { // case 1^(y) = 1 + tok->deleteNext(5); // delete tokens + tok->str("1"); // insert simplified result + simplifcationMade = true; + } + } + if (Token::Match(tok->tokAt(2), "%any% , %num% )")) { + // In case of pow( x , 1 ): It can be simplified to x. + const std::string& leftParameter(tok->strAt(2)); // get the left parameter + const std::string& rightNumber(tok->strAt(4)); // get right number + if (isOneNumber(rightNumber)) { // case: x^(1) = x + tok->str(leftParameter); // insert simplified result + tok->deleteNext(5); // delete tokens + simplifcationMade = true; + } else if (isZeroNumber(rightNumber)) { // case: x^(0) = 1 + tok->deleteNext(5); // delete tokens + tok->str("1"); // insert simplified result + simplifcationMade = true; + } + } + } + // Jump back to begin of statement if a simplification was performed + if (simplifcationMade) { + while (tok->previous() && tok->str() != ";") { + tok = tok->previous(); + } + } + } + } +} + +void Tokenizer::simplifyComma() +{ + bool inReturn = false; + + for (Token *tok = list.front(); tok; tok = tok->next()) { + + // skip enums + if (Token::Match(tok, "enum class|struct| %name%| :|{")) { + skipEnumBody(&tok); + } + if (!tok) + syntaxError(nullptr); // invalid code like in #4195 + + if (Token::Match(tok, "(|[") || Token::Match(tok->previous(), "%name%|= {")) { + tok = tok->link(); + continue; + } + + if (Token::simpleMatch(tok, "= (") && Token::simpleMatch(tok->linkAt(1), ") {")) { + tok = tok->linkAt(1)->linkAt(1); + continue; + } + + // Skip unhandled template specifiers.. + if (tok->link() && tok->str() == "<") + tok = tok->link(); + + if (tok->str() == "return" && Token::Match(tok->previous(), "[;{}]")) + inReturn = true; + + if (inReturn && Token::Match(tok, "[;{}?:]")) + inReturn = false; + + if (!tok->next() || tok->str() != ",") + continue; + + // We must not accept just any keyword, e.g. accepting int + // would cause function parameters to corrupt. + if (isCPP() && tok->strAt(1) == "delete") { + // Handle "delete a, delete b;" + tok->str(";"); + } + + if (isCPP() && Token::Match(tok->tokAt(-2), "delete %name% , %name% ;") && + tok->next()->varId() != 0) { + // Handle "delete a, b;" - convert to delete a; b; + tok->str(";"); + } else if (!inReturn && tok->tokAt(-2)) { + bool replace = false; + for (Token *tok2 = tok->previous(); tok2; tok2 = tok2->previous()) { + if (tok2->str() == "=") { + // Handle "a = 0, b = 0;" + replace = true; + } else if (isCPP() && (Token::Match(tok2, "delete %name%") || + Token::Match(tok2, "delete [ ] %name%"))) { + // Handle "delete a, a = 0;" + replace = true; + } else if (Token::Match(tok2, "[?:;,{}()]")) { + if (replace && Token::Match(tok2, "[;{}]")) + tok->str(";"); + break; + } + } + } + + // find token where return ends and also count commas + if (inReturn) { + Token *startFrom = nullptr; // "[;{}]" token before "return" + Token *endAt = nullptr; // first ";" token after "[;{}] return" + + // find "; return" pattern before comma + for (Token *tok2 = tok->previous(); tok2; tok2 = tok2->previous()) { + if (tok2->str() == "return") { + startFrom = tok2->previous(); + break; + } + } + if (!startFrom) + // to be very sure... + return; + int commaCounter = 0; + for (Token *tok2 = startFrom->next(); tok2; tok2 = tok2->next()) { + if (tok2->str() == ";") { + endAt = tok2; + break; + + } else if (Token::Match(tok2, "(|[") || + (tok2->str() == "{" && tok2->previous() && tok2->previous()->str() == "=")) { + tok2 = tok2->link(); + + } else if (tok2->str() == ",") { + ++commaCounter; + } + } + + if (!endAt) + //probably a syntax error + return; + + if (commaCounter) { + // change tokens: + // "; return a ( ) , b ( ) , c ;" + // to + // "; a ( ) ; b ( ) ; return c ;" + + // remove "return" + startFrom->deleteNext(); + for (Token *tok2 = startFrom->next(); tok2 != endAt; tok2 = tok2->next()) { + if (Token::Match(tok2, "(|[") || + (tok2->str() == "{" && tok2->previous() && tok2->previous()->str() == "=")) { + tok2 = tok2->link(); + + } else if (tok2->str() == ",") { + tok2->str(";"); + --commaCounter; + if (commaCounter == 0) { + tok2->insertToken("return"); + } + } + } + tok = endAt; + } + } + } +} void Tokenizer::checkConfiguration() const { @@ -7205,6 +9752,125 @@ std::string Tokenizer::simplifyString(const std::string &source) return str; } +void Tokenizer::simplifyWhile0() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + // while (0) + const bool while0(Token::Match(tok->previous(), "[{};] while ( 0|false )")); + + // for (0) - not banal, ticket #3140 + const bool for0((Token::Match(tok->previous(), "[{};] for ( %name% = %num% ; %name% < %num% ;") && + tok->strAt(2) == tok->strAt(6) && tok->strAt(4) == tok->strAt(8)) || + (Token::Match(tok->previous(), "[{};] for ( %type% %name% = %num% ; %name% < %num% ;") && + tok->strAt(3) == tok->strAt(7) && tok->strAt(5) == tok->strAt(9))); + + if (!while0 && !for0) + continue; + + if (while0 && tok->previous()->str() == "}") { + // find "do" + Token *tok2 = tok->previous()->link(); + tok2 = tok2->previous(); + if (tok2 && tok2->str() == "do") { + const bool flowmatch = Token::findmatch(tok2, "continue|break", tok) != nullptr; + // delete "do ({)" + tok2->deleteThis(); + if (!flowmatch) + tok2->deleteThis(); + + // delete "(}) while ( 0 ) (;)" + tok = tok->previous(); + tok->deleteNext(4); // while ( 0 ) + if (tok->next() && tok->next()->str() == ";") + tok->deleteNext(); // ; + if (!flowmatch) + tok->deleteThis(); // } + + continue; + } + } + + // remove "while (0) { .. }" + if (Token::simpleMatch(tok->next()->link(), ") {")) { + Token *end = tok->next()->link(), *old_prev = tok->previous(); + end = end->next()->link(); + if (Token::Match(tok, "for ( %name% =")) + old_prev = end->link(); + eraseDeadCode(old_prev, end->next()); + if (old_prev && old_prev->next()) + tok = old_prev->next(); + else + break; + } + } +} + +void Tokenizer::simplifyErrNoInWhile() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() != "errno") + continue; + + Token *endpar = nullptr; + if (Token::Match(tok->previous(), "&& errno == EINTR ) { ;| }")) + endpar = tok->tokAt(3); + else if (Token::Match(tok->tokAt(-2), "&& ( errno == EINTR ) ) { ;| }")) + endpar = tok->tokAt(4); + else + continue; + + if (Token::simpleMatch(endpar->link()->previous(), "while (")) { + Token *tok1 = tok->previous(); + if (tok1->str() == "(") + tok1 = tok1->previous(); + + // erase "&& errno == EINTR" + tok1 = tok1->previous(); + Token::eraseTokens(tok1, endpar); + + // tok is invalid.. move to endpar + tok = endpar; + } + } +} + + +void Tokenizer::simplifyFuncInWhile() +{ + int count = 0; + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (!Token::Match(tok, "while ( %name% ( %name% ) ) {")) + continue; + + Token *func = tok->tokAt(2); + const Token * const var = tok->tokAt(4); + Token * const end = tok->next()->link()->next()->link(); + + const int varid = ++mVarId; // Create new variable + const std::string varname("cppcheck:r" + MathLib::toString(++count)); + tok->str("int"); + tok->next()->insertToken(varname); + tok->tokAt(2)->varId(varid); + tok->insertToken("while"); + tok->insertToken(";"); + tok->insertToken(")"); + tok->insertToken(var->str()); + tok->next()->varId(var->varId()); + tok->insertToken("("); + tok->insertToken(func->str()); + tok->insertToken("="); + tok->insertToken(varname); + tok->next()->varId(varid); + Token::createMutualLinks(tok->tokAt(4), tok->tokAt(6)); + end->previous()->insertToken(varname); + end->previous()->varId(varid); + end->previous()->insertToken("="); + Token::move(func, func->tokAt(3), end->previous()); + end->previous()->insertToken(";"); + + tok = end; + } +} void Tokenizer::simplifyStructDecl() { @@ -7699,6 +10365,45 @@ void Tokenizer::simplifyKeyword() } } +void Tokenizer::simplifyAssignmentInFunctionCall() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() == "(") + tok = tok->link(); + + // Find 'foo(var='. Exclude 'assert(var=' to allow tests to check that assert(...) does not contain side-effects + else if (Token::Match(tok, "[;{}] %name% ( %name% =") && + Token::simpleMatch(tok->linkAt(2), ") ;") && + !Token::Match(tok->next(), "assert|while")) { + const std::string& funcname(tok->next()->str()); + Token* const vartok = tok->tokAt(3); + + // Goto ',' or ')'.. + for (Token *tok2 = vartok->tokAt(2); tok2; tok2 = tok2->next()) { + if (tok2->link() && Token::Match(tok2, "(|[|{")) + tok2 = tok2->link(); + else if (tok2->str() == ";") + break; + else if (Token::Match(tok2, ")|,")) { + tok2 = tok2->previous(); + + tok2->insertToken(vartok->str()); + tok2->next()->varId(vartok->varId()); + + tok2->insertToken("("); + Token::createMutualLinks(tok2->next(), tok->linkAt(2)); + + tok2->insertToken(funcname); + tok2->insertToken(";"); + + Token::eraseTokens(tok, vartok); + break; + } + } + } + } +} + void Tokenizer::simplifyAssignmentBlock() { for (Token *tok = list.front(); tok; tok = tok->next()) { @@ -8526,6 +11231,53 @@ void Tokenizer::removeUnnecessaryQualification() } } +void Tokenizer::simplifyReturnStrncat() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::simpleMatch(tok, "return strncat (") && + Token::simpleMatch(tok->linkAt(2), ") ;") && + tok->strAt(3) != ")" && tok->strAt(3) != ",") { + + //first argument + Token *tok2 = tok->tokAt(3); + + //check if there are at least three arguments + for (int i = 0; i < 2; ++i) { + tok2 = tok2->nextArgument(); + if (!tok2) { + tok = tok->linkAt(2)->next(); + break; + } + } + if (!tok2) + continue; + + tok2 = tok2->nextArgument(); + //we want only three arguments + if (tok2) { + tok = tok->linkAt(2)->next(); + continue; + } + + // Remove 'return' + tok->deleteThis(); + + // Add 'return arg1 ;' after 'strncat(arg1, arg2, arg3);' + tok = tok->next(); + + tok2 = tok->link()->next(); + tok2->insertToken(";"); + + //the last token of the first argument before ',' + const Token * const end = tok->next()->nextArgument()->tokAt(-2); + + //all the first argument is copied + TokenList::copyTokens(tok2, tok->next(), end); + tok2->insertToken("return"); + } + } +} + void Tokenizer::printUnknownTypes() const { if (!mSymbolDatabase) @@ -8694,6 +11446,20 @@ void Tokenizer::simplifyMathExpressions() } } +bool Tokenizer::simplifyStrlen() +{ + // replace strlen(str) + bool modified=false; + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "strlen ( %str% )")) { + tok->str(MathLib::toString(Token::getStrLength(tok->tokAt(2)))); + tok->deleteNext(3); + modified=true; + } + } + return modified; +} + void Tokenizer::prepareTernaryOpForAST() { // http://en.cppreference.com/w/cpp/language/operator_precedence says about ternary operator: diff --git a/lib/tokenize.h b/lib/tokenize.h index 91e72cdf9..da236ecf4 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -155,6 +155,14 @@ public: */ bool simplifyTokenList1(const char FileName[]); + /** + * Most aggressive simplification of tokenlist + * + * @return false if there is an error that requires aborting + * the checking of this file. + */ + bool simplifyTokenList2(); + /** * If --check-headers=no has been given; then remove unneeded code in headers. * - All executable code. @@ -200,6 +208,10 @@ public: */ bool isFunctionParameterPassedByValue(const Token *fpar) const; + /** Simplify assignment in function call "f(x=g());" => "x=g();f(x);" + */ + void simplifyAssignmentInFunctionCall(); + /** Simplify assignment where rhs is a block : "x=({123;});" => "{x=123;}" */ void simplifyAssignmentBlock(); @@ -210,6 +222,19 @@ public: */ bool simplifyCalculations(); + /** + * Simplify dereferencing a pointer offset by a number: + * "*(ptr + num)" => "ptr[num]" + * "*(ptr - num)" => "ptr[-num]" + */ + void simplifyOffsetPointerDereference(); + + /** + * Simplify referencing a pointer offset: + * "Replace "&str[num]" => "(str + num)" + */ + void simplifyOffsetPointerReference(); + /** Insert array size where it isn't given */ void arraySize(); @@ -235,9 +260,25 @@ public: /** Remove unknown macro in variable declarations: PROGMEM char x; */ void removeMacroInVarDecl(); + /** Remove redundant assignment */ + void removeRedundantAssignment(); + + /** Simplifies some realloc usage like + * 'x = realloc (0, n);' => 'x = malloc(n);' + * 'x = realloc (y, 0);' => 'x = 0; free(y);' + */ + void simplifyRealloc(); + /** Add parentheses for sizeof: sizeof x => sizeof(x) */ void sizeofAddParentheses(); + /** + * Replace sizeof() to appropriate size. + * @return true if modifications to token-list are done. + * false if no modifications are done. + */ + bool simplifySizeof(); + /** * Simplify variable declarations (split up) * \param only_k_r_fpar Only simplify K&R function parameters @@ -252,6 +293,20 @@ public: void simplifyInitVar(); Token * initVar(Token * tok); + /** + * Simplify easy constant '?:' operation + * Example: 0 ? (2/0) : 0 => 0 + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyConstTernaryOp(); + + /** + * Simplify compound assignments + * Example: ";a+=b;" => ";a=a+b;" + */ + void simplifyCompoundAssignment(); + /** * Simplify the location of "static" and "const" qualifiers in * a variable declaration or definition. @@ -260,6 +315,14 @@ public: */ void simplifyStaticConst(); + /** + * Simplify assignments in "if" and "while" conditions + * Example: "if(a=b);" => "a=b;if(a);" + * Example: "while(a=b) { f(a); }" => "a = b; while(a){ f(a); a = b; }" + * Example: "do { f(a); } while(a=b);" => "do { f(a); a = b; } while(a);" + */ + void simplifyIfAndWhileAssign(); + /** * Simplify multiple assignments. * Example: "a = b = c = 0;" => "a = 0; b = 0; c = 0;" @@ -275,6 +338,14 @@ public: */ bool simplifyCAlternativeTokens(); + /** + * Simplify comma into a semicolon when possible: + * - "delete a, delete b" => "delete a; delete b;" + * - "a = 0, b = 0;" => "a = 0; b = 0;" + * - "return a(), b;" => "a(); return b;" + */ + void simplifyComma(); + /** Add braces to an if-block, for-block, etc. * @return true if no syntax errors */ @@ -317,18 +388,82 @@ public: */ bool simplifyUsing(); + /** + * Simplify casts + */ + void simplifyCasts(); + + /** + * Change (multiple) arrays to (multiple) pointers. + */ + void simplifyUndefinedSizeArray(); + + /** + * 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(); + /** Simplify redundant code placed after control flow statements : + * 'return', 'throw', 'goto', 'break' and 'continue' + */ + void simplifyFlowControl(); + + /** Expand nested strcat() calls. */ + void simplifyNestedStrcat(); + /** Simplify "if else" */ void elseif(); + /** Simplify conditions + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyConditions(); + + /** Remove redundant code, e.g. if( false ) { int a; } should be + * removed, because it is never executed. + * @return true if something is modified + * false if nothing is done. + */ + bool removeRedundantConditions(); + + /** + * Remove redundant for: + * "for (x=0;x<1;x++) { }" => "{ x = 1; }" + */ + void removeRedundantFor(); + /** * Reduces "; ;" to ";", except in "( ; ; )" */ void removeRedundantSemicolons(); + /** Simplify function calls - constant return value + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyFunctionReturn(); + /** Struct simplification * "struct S { } s;" => "struct S { }; S s;" */ @@ -346,6 +481,11 @@ public: */ bool simplifyRedundantParentheses(); + void simplifyCharAt(); + + /** Simplify references */ + void simplifyReference(); + /** * Simplify functions like "void f(x) int x; {" * into "void f(int x) {" @@ -385,6 +525,11 @@ public: void findComplicatedSyntaxErrorsInTemplates(); + /** + * Simplify e.g. 'atol("0")' into '0' + */ + void simplifyMathFunctions(); + /** * Simplify e.g. 'sin(0)' into '0' */ @@ -417,6 +562,26 @@ public: private: + /** + * simplify "while (0)" + */ + void simplifyWhile0(); + + /** + * Simplify while(func() && errno==EINTR) + */ + void simplifyErrNoInWhile(); + + /** + * Simplify while(func(f)) + */ + void simplifyFuncInWhile(); + + /** + * Remove "std::" before some function names + */ + void simplifyStd(); + /** Simplify pointer to standard type (C only) */ void simplifyPointerToStandardType(); @@ -573,6 +738,12 @@ private: */ void simplifyCPPAttribute(); + /** + * Replace strlen(str) + * @return true if any replacement took place, false else + * */ + bool simplifyStrlen(); + /** * Convert namespace aliases */ @@ -619,6 +790,12 @@ private: std::map >& structMembers, nonneg int *varId_); + /** + * Simplify e.g. 'return(strncat(temp,"a",1));' into + * strncat(temp,"a",1); return temp; + */ + void simplifyReturnStrncat(); + /** * Output list of unknown types. */ @@ -653,7 +830,7 @@ public: * 1=1st simplifications * 2=2nd simplifications */ - void printDebugOutput() const; + void printDebugOutput(int simplification) const; void dump(std::ostream &out) const; diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 05cc2f92f..2aa276d33 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -52,6 +52,7 @@ private: TEST_CASE(optionwithoutfile); TEST_CASE(verboseshort); TEST_CASE(verboselong); + TEST_CASE(debugSimplified); TEST_CASE(debugwarnings); TEST_CASE(forceshort); TEST_CASE(forcelong); @@ -223,6 +224,14 @@ private: ASSERT_EQUALS(true, settings.verbose); } + void debugSimplified() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-simplified", "file.cpp"}; + settings.debugSimplified = false; + ASSERT(defParser.parseFromArgs(3, argv)); + ASSERT_EQUALS(true, settings.debugSimplified); + } + void debugwarnings() { REDIRECT; const char * const argv[] = {"cppcheck", "--debug-warnings", "file.cpp"}; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e25970906..f7e1b4452 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -35,6 +35,7 @@ public: private: Settings settings0; + Settings settings1; Settings settings_std; Settings settings_windows; @@ -42,8 +43,54 @@ private: LOAD_LIB_2(settings_std.library, "std.cfg"); LOAD_LIB_2(settings_windows.library, "windows.cfg"); settings0.addEnabled("portability"); + settings1.addEnabled("style"); settings_windows.addEnabled("portability"); + // Make sure the Tokenizer::simplifyTokenList works. + // The order of the simplifications is important. So this test + // case shall make sure the simplifications are done in the + // correct order + TEST_CASE(simplifyTokenList1); + + TEST_CASE(simplifyMathFunctions_sqrt); + TEST_CASE(simplifyMathFunctions_cbrt); + TEST_CASE(simplifyMathFunctions_exp); + TEST_CASE(simplifyMathFunctions_exp2); + TEST_CASE(simplifyMathFunctions_logb); + TEST_CASE(simplifyMathFunctions_log1p); + TEST_CASE(simplifyMathFunctions_ilogb); + TEST_CASE(simplifyMathFunctions_log10); + TEST_CASE(simplifyMathFunctions_log); + TEST_CASE(simplifyMathFunctions_log2); + TEST_CASE(simplifyMathFunctions_pow); + TEST_CASE(simplifyMathFunctions_fmin); + TEST_CASE(simplifyMathFunctions_fmax); + TEST_CASE(simplifyMathFunctions_acosh); + TEST_CASE(simplifyMathFunctions_acos); + TEST_CASE(simplifyMathFunctions_cosh); + TEST_CASE(simplifyMathFunctions_cos); + TEST_CASE(simplifyMathFunctions_erfc); + TEST_CASE(simplifyMathFunctions_erf); + TEST_CASE(simplifyMathFunctions_sin); + TEST_CASE(simplifyMathFunctions_sinh); + TEST_CASE(simplifyMathFunctions_asin); + TEST_CASE(simplifyMathFunctions_asinh); + TEST_CASE(simplifyMathFunctions_tan); + TEST_CASE(simplifyMathFunctions_tanh); + TEST_CASE(simplifyMathFunctions_atan); + TEST_CASE(simplifyMathFunctions_atanh); + TEST_CASE(simplifyMathFunctions_expm1); + TEST_CASE(simplifyMathExpressions); //ticket #1620 + + // foo(p = new char[10]); => p = new char[10]; foo(p); + TEST_CASE(simplifyAssignmentInFunctionCall); + + // ";a+=b;" => ";a=a+b;" + TEST_CASE(simplifyCompoundAssignment); + + TEST_CASE(cast); + TEST_CASE(iftruefalse); + TEST_CASE(combine_strings); TEST_CASE(combine_wstrings); TEST_CASE(combine_ustrings); @@ -54,14 +101,55 @@ private: TEST_CASE(double_plus); TEST_CASE(redundant_plus); TEST_CASE(redundant_plus_numbers); + TEST_CASE(parentheses1); + TEST_CASE(parenthesesVar); // Remove redundant parentheses around variable .. "( %name% )" TEST_CASE(declareVar); TEST_CASE(declareArray); + TEST_CASE(dontRemoveIncrement); + TEST_CASE(removePostIncrement); + TEST_CASE(removePreIncrement); + TEST_CASE(elseif1); + TEST_CASE(sizeof_array); + TEST_CASE(sizeof5); + TEST_CASE(sizeof6); + TEST_CASE(sizeof7); + TEST_CASE(sizeof8); + TEST_CASE(sizeof9); + TEST_CASE(sizeof10); + TEST_CASE(sizeof11); + TEST_CASE(sizeof12); + TEST_CASE(sizeof13); + TEST_CASE(sizeof14); + TEST_CASE(sizeof15); + TEST_CASE(sizeof16); + TEST_CASE(sizeof17); + TEST_CASE(sizeof18); + TEST_CASE(sizeof19); // #1891 - sizeof 'x' + TEST_CASE(sizeof20); // #2024 - sizeof a) + TEST_CASE(sizeof21); // #2232 - sizeof...(Args) + TEST_CASE(sizeof22); + TEST_CASE(sizeofsizeof); + TEST_CASE(casting); + + TEST_CASE(strlen1); + TEST_CASE(strlen2); + TEST_CASE(namespaces); + // Assignment in condition.. + TEST_CASE(ifassign1); + TEST_CASE(ifAssignWithCast); + TEST_CASE(whileAssign1); + TEST_CASE(whileAssign2); + TEST_CASE(whileAssign3); // varid + TEST_CASE(whileAssign4); // links + TEST_CASE(doWhileAssign); // varid + TEST_CASE(test_4881); // similar to doWhileAssign (#4911), taken from #4881 with full code + // Simplify "not" to "!" (#345) TEST_CASE(not1); @@ -74,20 +162,62 @@ private: TEST_CASE(cAlternativeTokens); TEST_CASE(comma_keyword); + TEST_CASE(remove_comma); + + // Simplify "?:" + TEST_CASE(simplifyConditionOperator); // Simplify calculations TEST_CASE(calculations); + TEST_CASE(comparisons); + + //remove dead code after flow control statements + TEST_CASE(simplifyFlowControl); + TEST_CASE(flowControl); + + // Simplify nested strcat() calls + TEST_CASE(strcat1); + TEST_CASE(strcat2); + + TEST_CASE(simplifyAtol); TEST_CASE(simplifyOperator1); TEST_CASE(simplifyOperator2); TEST_CASE(simplifyArrayAccessSyntax); + TEST_CASE(simplify_numeric_condition); + TEST_CASE(simplify_condition); + + TEST_CASE(pointeralias1); + TEST_CASE(pointeralias2); + TEST_CASE(pointeralias3); + TEST_CASE(pointeralias4); + + // simplify "while (0)" + TEST_CASE(while0); + // ticket #3140 + TEST_CASE(while0for); TEST_CASE(duplicateDefinition); // ticket #3565 + // remove "std::" on some standard functions + TEST_CASE(removestd); + // Tokenizer::simplifyInitVar TEST_CASE(simplifyInitVar); + // Tokenizer::simplifyReference + TEST_CASE(simplifyReference); + + // x = realloc(y,0); => free(y);x=0; + TEST_CASE(simplifyRealloc); + + // while(f() && errno==EINTR) { } => while (f()) { } + TEST_CASE(simplifyErrNoInWhile); + + // while(fclose(f)); => r = fclose(f); while(r){r=fclose(f);} + TEST_CASE(simplifyFuncInWhile); + // struct ABC { } abc; => struct ABC { }; ABC abc; TEST_CASE(simplifyStructDecl1); TEST_CASE(simplifyStructDecl2); // ticket #2579 @@ -115,8 +245,19 @@ private: // void foo(void) -> void foo() TEST_CASE(removeVoidFromFunction); + TEST_CASE(return_strncat); // ticket # 2860 Returning value of strncat() reported as memory leak + + // #3069 : for loop with 1 iteration + // for (x=0;x<1;x++) { .. } + // The for is redundant + TEST_CASE(removeRedundantFor); + TEST_CASE(consecutiveBraces); + TEST_CASE(undefinedSizeArray); + + TEST_CASE(simplifyArrayAddress); // Replace "&str[num]" => "(str + num)" + TEST_CASE(simplifyCharAt); TEST_CASE(simplifyOverride); // ticket #5069 TEST_CASE(simplifyNestedNamespace); TEST_CASE(simplifyNamespaceAliases); @@ -130,12 +271,9 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); - bool modified = true; - while (modified) { - modified = false; - modified |= tokenizer.simplifyCalculations(); - modified |= tokenizer.simplifyRedundantParentheses(); - } + + if (simplify) + tokenizer.simplifyTokenList2(); return tokenizer.tokens()->stringifyList(nullptr, !simplify); } @@ -149,16 +287,21 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); + if (simplify) + tokenizer.simplifyTokenList2(); + return tokenizer.tokens()->stringifyList(nullptr, !simplify); } - std::string tok(const char code[], const char filename[]) { + std::string tok(const char code[], const char filename[], bool simplify = true) { errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); + if (simplify) + tokenizer.simplifyTokenList2(); return tokenizer.tokens()->stringifyList(nullptr, false); } @@ -170,6 +313,7 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); + tokenizer.simplifyTokenList2(); return tokenizer.tokens()->stringifyList(false, false, false, true, false); } @@ -181,21 +325,1462 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); + tokenizer.simplifyTokenList2(); return tokenizer.tokens()->stringifyList(nullptr, false); } - std::string tokenizeDebugListing(const char code[], const char filename[] = "test.cpp") { + std::string tokenizeDebugListing(const char code[], bool simplify = false, const char filename[] = "test.cpp") { errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); + if (simplify) + tokenizer.simplifyTokenList2(); + // result.. return tokenizer.tokens()->stringifyList(true); } + void simplifyTokenList1() { + // #1717 : The simplifyErrNoInWhile needs to be used before simplifyIfAndWhileAssign.. + ASSERT_EQUALS("{ x = f ( ) ; while ( x == -1 ) { x = f ( ) ; } }", + tok("{ while((x=f())==-1 && errno==EINTR){}}",true)); + } + + + void simplifyMathFunctions_erfc() { + // verify erfc(), erfcf(), erfcl() - simplifcation + const char code_erfc[] ="void f(int x) {\n" + " std::cout << erfc(x);\n" // do not simplify + " std::cout << erfc(0L);\n" // simplify to 1 + "}"; + const char expected_erfc[] = "void f ( int x ) {\n" + "std :: cout << erfc ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_erfc, tokWithNewlines(code_erfc)); + + const char code_erfcf[] ="void f(float x) {\n" + " std::cout << erfcf(x);\n" // do not simplify + " std::cout << erfcf(0.0f);\n" // simplify to 1 + "}"; + const char expected_erfcf[] = "void f ( float x ) {\n" + "std :: cout << erfcf ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_erfcf, tokWithNewlines(code_erfcf)); + + const char code_erfcl[] ="void f(long double x) {\n" + " std::cout << erfcl(x);\n" // do not simplify + " std::cout << erfcl(0.0f);\n" // simplify to 1 + "}"; + const char expected_erfcl[] = "void f ( double x ) {\n" + "std :: cout << erfcl ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_erfcl, tokWithNewlines(code_erfcl)); + } + + void simplifyMathFunctions_cos() { + // verify cos(), cosf(), cosl() - simplifcation + const char code_cos[] ="void f(int x) {\n" + " std::cout << cos(x);\n" // do not simplify + " std::cout << cos(0L);\n" // simplify to 1 + "}"; + const char expected_cos[] = "void f ( int x ) {\n" + "std :: cout << cos ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cos, tokWithNewlines(code_cos)); + + const char code_cosf[] ="void f(float x) {\n" + " std::cout << cosf(x);\n" // do not simplify + " std::cout << cosf(0.0f);\n" // simplify to 1 + "}"; + const char expected_cosf[] = "void f ( float x ) {\n" + "std :: cout << cosf ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cosf, tokWithNewlines(code_cosf)); + + const char code_cosl[] ="void f(long double x) {\n" + " std::cout << cosl(x);\n" // do not simplify + " std::cout << cosl(0.0f);\n" // simplify to 1 + "}"; + const char expected_cosl[] = "void f ( double x ) {\n" + "std :: cout << cosl ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cosl, tokWithNewlines(code_cosl)); + } + + void simplifyMathFunctions_cosh() { + // verify cosh(), coshf(), coshl() - simplifcation + const char code_cosh[] ="void f(int x) {\n" + " std::cout << cosh(x);\n" // do not simplify + " std::cout << cosh(0L);\n" // simplify to 1 + "}"; + const char expected_cosh[] = "void f ( int x ) {\n" + "std :: cout << cosh ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cosh, tokWithNewlines(code_cosh)); + + const char code_coshf[] ="void f(float x) {\n" + " std::cout << coshf(x);\n" // do not simplify + " std::cout << coshf(0.0f);\n" // simplify to 1 + "}"; + const char expected_coshf[] = "void f ( float x ) {\n" + "std :: cout << coshf ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_coshf, tokWithNewlines(code_coshf)); + + const char code_coshl[] ="void f(long double x) {\n" + " std::cout << coshl(x);\n" // do not simplify + " std::cout << coshl(0.0f);\n" // simplify to 1 + "}"; + const char expected_coshl[] = "void f ( double x ) {\n" + "std :: cout << coshl ( x ) ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_coshl, tokWithNewlines(code_coshl)); + } + + void simplifyMathFunctions_acos() { + // verify acos(), acosf(), acosl() - simplifcation + const char code_acos[] ="void f(int x) {\n" + " std::cout << acos(x);\n" // do not simplify + " std::cout << acos(1L);\n" // simplify to 0 + "}"; + const char expected_acos[] = "void f ( int x ) {\n" + "std :: cout << acos ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acos, tokWithNewlines(code_acos)); + + const char code_acosf[] ="void f(float x) {\n" + " std::cout << acosf(x);\n" // do not simplify + " std::cout << acosf(1.0f);\n" // simplify to 0 + "}"; + const char expected_acosf[] = "void f ( float x ) {\n" + "std :: cout << acosf ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acosf, tokWithNewlines(code_acosf)); + + const char code_acosl[] ="void f(long double x) {\n" + " std::cout << acosl(x);\n" // do not simplify + " std::cout << acosl(1.0f);\n" // simplify to 0 + "}"; + const char expected_acosl[] = "void f ( double x ) {\n" + "std :: cout << acosl ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acosl, tokWithNewlines(code_acosl)); + } + + void simplifyMathFunctions_acosh() { + // verify acosh(), acoshf(), acoshl() - simplifcation + const char code_acosh[] ="void f(int x) {\n" + " std::cout << acosh(x);\n" // do not simplify + " std::cout << acosh(1L);\n" // simplify to 0 + "}"; + const char expected_acosh[] = "void f ( int x ) {\n" + "std :: cout << acosh ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acosh, tokWithNewlines(code_acosh)); + + const char code_acoshf[] ="void f(float x) {\n" + " std::cout << acoshf(x);\n" // do not simplify + " std::cout << acoshf(1.0f);\n" // simplify to 0 + "}"; + const char expected_acoshf[] = "void f ( float x ) {\n" + "std :: cout << acoshf ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acoshf, tokWithNewlines(code_acoshf)); + + const char code_acoshl[] ="void f(long double x) {\n" + " std::cout << acoshl(x);\n" // do not simplify + " std::cout << acoshl(1.0f);\n" // simplify to 0 + "}"; + const char expected_acoshl[] = "void f ( double x ) {\n" + "std :: cout << acoshl ( x ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_acoshl, tokWithNewlines(code_acoshl)); + } + + void simplifyMathFunctions_sqrt() { + // verify sqrt(), sqrtf(), sqrtl() - simplifcation + const char code_sqrt[] ="void f(int x) {\n" + " std::cout << sqrt(x);\n" // do not simplify + " std::cout << sqrt(-1);\n" // do not simplify + " std::cout << sqrt(0L);\n" // simplify to 0 + " std::cout << sqrt(1L);\n" // simplify to 1 + "}"; + const char expected_sqrt[] = "void f ( int x ) {\n" + "std :: cout << sqrt ( x ) ;\n" + "std :: cout << sqrt ( -1 ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_sqrt, tokWithNewlines(code_sqrt)); + + const char code_sqrtf[] ="void f(float x) {\n" + " std::cout << sqrtf(x);\n" // do not simplify + " std::cout << sqrtf(-1.0f);\n" // do not simplify + " std::cout << sqrtf(0.0f);\n" // simplify to 0 + " std::cout << sqrtf(1.0);\n" // simplify to 1 + "}"; + const char expected_sqrtf[] = "void f ( float x ) {\n" + "std :: cout << sqrtf ( x ) ;\n" + "std :: cout << sqrtf ( -1.0f ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_sqrtf, tokWithNewlines(code_sqrtf)); + + const char code_sqrtl[] ="void f(long double x) {\n" + " std::cout << sqrtf(x);\n" // do not simplify + " std::cout << sqrtf(-1.0);\n" // do not simplify + " std::cout << sqrtf(0.0);\n" // simplify to 0 + " std::cout << sqrtf(1.0);\n" // simplify to 1 + "}"; + const char expected_sqrtl[] = "void f ( double x ) {\n" + "std :: cout << sqrtf ( x ) ;\n" + "std :: cout << sqrtf ( -1.0 ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_sqrtl, tokWithNewlines(code_sqrtl)); + } + + void simplifyMathFunctions_cbrt() { + // verify cbrt(), cbrtf(), cbrtl() - simplifcation + const char code_cbrt[] ="void f(int x) {\n" + " std::cout << cbrt(x);\n" // do not simplify + " std::cout << cbrt(-1);\n" // do not simplify + " std::cout << cbrt(0L);\n" // simplify to 0 + " std::cout << cbrt(1L);\n" // simplify to 1 + "}"; + const char expected_cbrt[] = "void f ( int x ) {\n" + "std :: cout << cbrt ( x ) ;\n" + "std :: cout << cbrt ( -1 ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cbrt, tokWithNewlines(code_cbrt)); + + const char code_cbrtf[] ="void f(float x) {\n" + " std::cout << cbrtf(x);\n" // do not simplify + " std::cout << cbrtf(-1.0f);\n" // do not simplify + " std::cout << cbrtf(0.0f);\n" // simplify to 0 + " std::cout << cbrtf(1.0);\n" // simplify to 1 + "}"; + const char expected_cbrtf[] = "void f ( float x ) {\n" + "std :: cout << cbrtf ( x ) ;\n" + "std :: cout << cbrtf ( -1.0f ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cbrtf, tokWithNewlines(code_cbrtf)); + + const char code_cbrtl[] ="void f(long double x) {\n" + " std::cout << cbrtl(x);\n" // do not simplify + " std::cout << cbrtl(-1.0);\n" // do not simplify + " std::cout << cbrtl(0.0);\n" // simplify to 0 + " std::cout << cbrtl(1.0);\n" // simplify to 1 + "}"; + const char expected_cbrtl[] = "void f ( double x ) {\n" + "std :: cout << cbrtl ( x ) ;\n" + "std :: cout << cbrtl ( -1.0 ) ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_cbrtl, tokWithNewlines(code_cbrtl)); + } + + void simplifyMathFunctions_exp2() { + // verify exp2(), exp2f(), exp2l() - simplifcation + const char code_exp2[] ="void f(int x) {\n" + " std::cout << exp2(x);\n" // do not simplify + " std::cout << exp2(-1);\n" // do not simplify + " std::cout << exp2(0L);\n" // simplify to 0 + " std::cout << exp2(1L);\n" // do not simplify + "}"; + const char expected_exp2[] = "void f ( int x ) {\n" + "std :: cout << exp2 ( x ) ;\n" + "std :: cout << exp2 ( -1 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << exp2 ( 1L ) ;\n" + "}"; + ASSERT_EQUALS(expected_exp2, tokWithNewlines(code_exp2)); + + const char code_exp2f[] ="void f(float x) {\n" + " std::cout << exp2f(x);\n" // do not simplify + " std::cout << exp2f(-1.0);\n" // do not simplify + " std::cout << exp2f(0.0);\n" // simplify to 1 + " std::cout << exp2f(1.0);\n" // do not simplify + "}"; + const char expected_exp2f[] = "void f ( float x ) {\n" + "std :: cout << exp2f ( x ) ;\n" + "std :: cout << exp2f ( -1.0 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << exp2f ( 1.0 ) ;\n" + "}"; + ASSERT_EQUALS(expected_exp2f, tokWithNewlines(code_exp2f)); + + const char code_exp2l[] ="void f(long double x) {\n" + " std::cout << exp2l(x);\n" // do not simplify + " std::cout << exp2l(-1.0);\n" // do not simplify + " std::cout << exp2l(0.0);\n" // simplify to 1 + " std::cout << exp2l(1.0);\n" // do not simplify + "}"; + const char expected_exp2l[] = "void f ( double x ) {\n" + "std :: cout << exp2l ( x ) ;\n" + "std :: cout << exp2l ( -1.0 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << exp2l ( 1.0 ) ;\n" + "}"; + ASSERT_EQUALS(expected_exp2l, tokWithNewlines(code_exp2l)); + } + + void simplifyMathFunctions_exp() { + // verify exp(), expf(), expl() - simplifcation + const char code_exp[] ="void f(int x) {\n" + " std::cout << exp(x);\n" // do not simplify + " std::cout << exp(-1);\n" // do not simplify + " std::cout << exp(0L);\n" // simplify to 1 + " std::cout << exp(1L);\n" // do not simplify + "}"; + const char expected_exp[] = "void f ( int x ) {\n" + "std :: cout << exp ( x ) ;\n" + "std :: cout << exp ( -1 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << exp ( 1L ) ;\n" + "}"; + ASSERT_EQUALS(expected_exp, tokWithNewlines(code_exp)); + + const char code_expf[] ="void f(float x) {\n" + " std::cout << expf(x);\n" // do not simplify + " std::cout << expf(-1.0);\n" // do not simplify + " std::cout << expf(0.0);\n" // simplify to 1 + " std::cout << expf(1.0);\n" // do not simplify + "}"; + const char expected_expf[] = "void f ( float x ) {\n" + "std :: cout << expf ( x ) ;\n" + "std :: cout << expf ( -1.0 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << expf ( 1.0 ) ;\n" + "}"; + ASSERT_EQUALS(expected_expf, tokWithNewlines(code_expf)); + + const char code_expl[] ="void f(long double x) {\n" + " std::cout << expl(x);\n" // do not simplify + " std::cout << expl(-1.0);\n" // do not simplify + " std::cout << expl(0.0);\n" // simplify to 1 + " std::cout << expl(1.0);\n" // do not simplify + "}"; + const char expected_expl[] = "void f ( double x ) {\n" + "std :: cout << expl ( x ) ;\n" + "std :: cout << expl ( -1.0 ) ;\n" + "std :: cout << 1 ;\n" + "std :: cout << expl ( 1.0 ) ;\n" + "}"; + ASSERT_EQUALS(expected_expl, tokWithNewlines(code_expl)); + } + + void simplifyMathFunctions_erf() { + // verify erf(), erff(), erfl() - simplifcation + const char code_erf[] ="void f(int x) {\n" + " std::cout << erf(x);\n" // do not simplify + " std::cout << erf(10);\n" // do not simplify + " std::cout << erf(0L);\n" // simplify to 0 + "}"; + const char expected_erf[] = "void f ( int x ) {\n" + "std :: cout << erf ( x ) ;\n" + "std :: cout << erf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_erf, tokWithNewlines(code_erf)); + + const char code_erff[] ="void f(float x) {\n" + " std::cout << erff(x);\n" // do not simplify + " std::cout << erff(10);\n" // do not simplify + " std::cout << erff(0.0f);\n" // simplify to 0 + "}"; + const char expected_erff[] = "void f ( float x ) {\n" + "std :: cout << erff ( x ) ;\n" + "std :: cout << erff ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_erff, tokWithNewlines(code_erff)); + + const char code_erfl[] ="void f(long double x) {\n" + " std::cout << erfl(x);\n" // do not simplify + " std::cout << erfl(10.0f);\n" // do not simplify + " std::cout << erfl(0.0f);\n" // simplify to 0 + "}"; + const char expected_erfl[] = "void f ( double x ) {\n" + "std :: cout << erfl ( x ) ;\n" + "std :: cout << erfl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_erfl, tokWithNewlines(code_erfl)); + } + + void simplifyMathFunctions_atanh() { + // verify atanh(), atanhf(), atanhl() - simplifcation + const char code_atanh[] ="void f(int x) {\n" + " std::cout << atanh(x);\n" // do not simplify + " std::cout << atanh(10);\n" // do not simplify + " std::cout << atanh(0L);\n" // simplify to 0 + "}"; + const char expected_atanh[] = "void f ( int x ) {\n" + "std :: cout << atanh ( x ) ;\n" + "std :: cout << atanh ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atanh, tokWithNewlines(code_atanh)); + + const char code_atanhf[] ="void f(float x) {\n" + " std::cout << atanhf(x);\n" // do not simplify + " std::cout << atanhf(10);\n" // do not simplify + " std::cout << atanhf(0.0f);\n" // simplify to 0 + "}"; + const char expected_atanhf[] = "void f ( float x ) {\n" + "std :: cout << atanhf ( x ) ;\n" + "std :: cout << atanhf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atanhf, tokWithNewlines(code_atanhf)); + + const char code_atanhl[] ="void f(long double x) {\n" + " std::cout << atanhl(x);\n" // do not simplify + " std::cout << atanhl(10.0f);\n" // do not simplify + " std::cout << atanhl(0.0d);\n" // do not simplify - invalid number! + " std::cout << atanhl(0.0f);\n" // simplify to 0 + "}"; + const char expected_atanhl[] = "void f ( double x ) {\n" + "std :: cout << atanhl ( x ) ;\n" + "std :: cout << atanhl ( 10.0f ) ;\n" + "std :: cout << atanhl ( 0.0d ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atanhl, tokWithNewlines(code_atanhl)); + } + + void simplifyMathFunctions_atan() { + // verify atan(), atanf(), atanl() - simplifcation + const char code_atan[] ="void f(int x) {\n" + " std::cout << atan(x);\n" // do not simplify + " std::cout << atan(10);\n" // do not simplify + " std::cout << atan(0L);\n" // simplify to 0 + "}"; + const char expected_atan[] = "void f ( int x ) {\n" + "std :: cout << atan ( x ) ;\n" + "std :: cout << atan ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atan, tokWithNewlines(code_atan)); + + const char code_atanf[] ="void f(float x) {\n" + " std::cout << atanf(x);\n" // do not simplify + " std::cout << atanf(10);\n" // do not simplify + " std::cout << atanf(0.0f);\n" // simplify to 0 + "}"; + const char expected_atanf[] = "void f ( float x ) {\n" + "std :: cout << atanf ( x ) ;\n" + "std :: cout << atanf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atanf, tokWithNewlines(code_atanf)); + + const char code_atanl[] ="void f(long double x) {\n" + " std::cout << atanl(x);\n" // do not simplify + " std::cout << atanl(10.0f);\n" // do not simplify + " std::cout << atanl(0.0f);\n" // simplify to 0 + "}"; + const char expected_atanl[] = "void f ( double x ) {\n" + "std :: cout << atanl ( x ) ;\n" + "std :: cout << atanl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_atanl, tokWithNewlines(code_atanl)); + } + + void simplifyMathFunctions_tanh() { + // verify tanh(), tanhf(), tanhl() - simplifcation + const char code_tanh[] ="void f(int x) {\n" + " std::cout << tanh(x);\n" // do not simplify + " std::cout << tanh(10);\n" // do not simplify + " std::cout << tanh(0L);\n" // simplify to 0 + "}"; + const char expected_tanh[] = "void f ( int x ) {\n" + "std :: cout << tanh ( x ) ;\n" + "std :: cout << tanh ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tanh, tokWithNewlines(code_tanh)); + + const char code_tanhf[] ="void f(float x) {\n" + " std::cout << tanhf(x);\n" // do not simplify + " std::cout << tanhf(10);\n" // do not simplify + " std::cout << tanhf(0.0f);\n" // simplify to 0 + "}"; + const char expected_tanhf[] = "void f ( float x ) {\n" + "std :: cout << tanhf ( x ) ;\n" + "std :: cout << tanhf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tanhf, tokWithNewlines(code_tanhf)); + + const char code_tanhl[] ="void f(long double x) {\n" + " std::cout << tanhl(x);\n" // do not simplify + " std::cout << tanhl(10.0f);\n" // do not simplify + " std::cout << tanhl(0.0f);\n" // simplify to 0 + "}"; + const char expected_tanhl[] = "void f ( double x ) {\n" + "std :: cout << tanhl ( x ) ;\n" + "std :: cout << tanhl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tanhl, tokWithNewlines(code_tanhl)); + } + + void simplifyMathFunctions_tan() { + // verify tan(), tanf(), tanl() - simplifcation + const char code_tan[] ="void f(int x) {\n" + " std::cout << tan(x);\n" // do not simplify + " std::cout << tan(10);\n" // do not simplify + " std::cout << tan(0L);\n" // simplify to 0 + "}"; + const char expected_tan[] = "void f ( int x ) {\n" + "std :: cout << tan ( x ) ;\n" + "std :: cout << tan ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tan, tokWithNewlines(code_tan)); + + const char code_tanf[] ="void f(float x) {\n" + " std::cout << tanf(x);\n" // do not simplify + " std::cout << tanf(10);\n" // do not simplify + " std::cout << tanf(0.0f);\n" // simplify to 0 + "}"; + const char expected_tanf[] = "void f ( float x ) {\n" + "std :: cout << tanf ( x ) ;\n" + "std :: cout << tanf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tanf, tokWithNewlines(code_tanf)); + + const char code_tanl[] ="void f(long double x) {\n" + " std::cout << tanl(x);\n" // do not simplify + " std::cout << tanl(10.0f);\n" // do not simplify + " std::cout << tanl(0.0f);\n" // simplify to 0 + "}"; + const char expected_tanl[] = "void f ( double x ) {\n" + "std :: cout << tanl ( x ) ;\n" + "std :: cout << tanl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_tanl, tokWithNewlines(code_tanl)); + } + + void simplifyMathFunctions_expm1() { + // verify expm1(), expm1f(), expm1l() - simplifcation + const char code_expm1[] ="void f(int x) {\n" + " std::cout << expm1(x);\n" // do not simplify + " std::cout << expm1(10);\n" // do not simplify + " std::cout << expm1(0L);\n" // simplify to 0 + "}"; + const char expected_expm1[] = "void f ( int x ) {\n" + "std :: cout << expm1 ( x ) ;\n" + "std :: cout << expm1 ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_expm1, tokWithNewlines(code_expm1)); + + const char code_expm1f[] ="void f(float x) {\n" + " std::cout << expm1f(x);\n" // do not simplify + " std::cout << expm1f(10);\n" // do not simplify + " std::cout << expm1f(0.0f);\n" // simplify to 0 + "}"; + const char expected_expm1f[] = "void f ( float x ) {\n" + "std :: cout << expm1f ( x ) ;\n" + "std :: cout << expm1f ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_expm1f, tokWithNewlines(code_expm1f)); + + const char code_expm1l[] ="void f(long double x) {\n" + " std::cout << expm1l(x);\n" // do not simplify + " std::cout << expm1l(10.0f);\n" // do not simplify + " std::cout << expm1l(0.0f);\n" // simplify to 0 + "}"; + const char expected_expm1l[] = "void f ( double x ) {\n" + "std :: cout << expm1l ( x ) ;\n" + "std :: cout << expm1l ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_expm1l, tokWithNewlines(code_expm1l)); + } + + void simplifyMathFunctions_asinh() { + // verify asinh(), asinhf(), asinhl() - simplifcation + const char code_asinh[] ="void f(int x) {\n" + " std::cout << asinh(x);\n" // do not simplify + " std::cout << asinh(10);\n" // do not simplify + " std::cout << asinh(0L);\n" // simplify to 0 + "}"; + const char expected_asinh[] = "void f ( int x ) {\n" + "std :: cout << asinh ( x ) ;\n" + "std :: cout << asinh ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asinh, tokWithNewlines(code_asinh)); + + const char code_asinhf[] ="void f(float x) {\n" + " std::cout << asinhf(x);\n" // do not simplify + " std::cout << asinhf(10);\n" // do not simplify + " std::cout << asinhf(0.0f);\n" // simplify to 0 + "}"; + const char expected_asinhf[] = "void f ( float x ) {\n" + "std :: cout << asinhf ( x ) ;\n" + "std :: cout << asinhf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asinhf, tokWithNewlines(code_asinhf)); + + const char code_asinhl[] ="void f(long double x) {\n" + " std::cout << asinhl(x);\n" // do not simplify + " std::cout << asinhl(10.0f);\n" // do not simplify + " std::cout << asinhl(0.0f);\n" // simplify to 0 + "}"; + const char expected_asinhl[] = "void f ( double x ) {\n" + "std :: cout << asinhl ( x ) ;\n" + "std :: cout << asinhl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asinhl, tokWithNewlines(code_asinhl)); + } + + void simplifyMathFunctions_asin() { + // verify asin(), asinf(), asinl() - simplifcation + const char code_asin[] ="void f(int x) {\n" + " std::cout << asin(x);\n" // do not simplify + " std::cout << asin(10);\n" // do not simplify + " std::cout << asin(0L);\n" // simplify to 0 + "}"; + const char expected_asin[] = "void f ( int x ) {\n" + "std :: cout << asin ( x ) ;\n" + "std :: cout << asin ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asin, tokWithNewlines(code_asin)); + + const char code_asinf[] ="void f(float x) {\n" + " std::cout << asinf(x);\n" // do not simplify + " std::cout << asinf(10);\n" // do not simplify + " std::cout << asinf(0.0f);\n" // simplify to 0 + "}"; + const char expected_asinf[] = "void f ( float x ) {\n" + "std :: cout << asinf ( x ) ;\n" + "std :: cout << asinf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asinf, tokWithNewlines(code_asinf)); + + const char code_asinl[] ="void f(long double x) {\n" + " std::cout << asinl(x);\n" // do not simplify + " std::cout << asinl(10.0f);\n" // do not simplify + " std::cout << asinl(0.0f);\n" // simplify to 0 + "}"; + const char expected_asinl[] = "void f ( double x ) {\n" + "std :: cout << asinl ( x ) ;\n" + "std :: cout << asinl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_asinl, tokWithNewlines(code_asinl)); + } + + void simplifyMathFunctions_sinh() { + // verify sinh(), sinhf(), sinhl() - simplifcation + const char code_sinh[] ="void f(int x) {\n" + " std::cout << sinh(x);\n" // do not simplify + " std::cout << sinh(10);\n" // do not simplify + " std::cout << sinh(0L);\n" // simplify to 0 + "}"; + const char expected_sinh[] = "void f ( int x ) {\n" + "std :: cout << sinh ( x ) ;\n" + "std :: cout << sinh ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sinh, tokWithNewlines(code_sinh)); + + const char code_sinhf[] ="void f(float x) {\n" + " std::cout << sinhf(x);\n" // do not simplify + " std::cout << sinhf(10);\n" // do not simplify + " std::cout << sinhf(0.0f);\n" // simplify to 0 + "}"; + const char expected_sinhf[] = "void f ( float x ) {\n" + "std :: cout << sinhf ( x ) ;\n" + "std :: cout << sinhf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sinhf, tokWithNewlines(code_sinhf)); + + const char code_sinhl[] ="void f(long double x) {\n" + " std::cout << sinhl(x);\n" // do not simplify + " std::cout << sinhl(10.0f);\n" // do not simplify + " std::cout << sinhl(0.0f);\n" // simplify to 0 + "}"; + const char expected_sinhl[] = "void f ( double x ) {\n" + "std :: cout << sinhl ( x ) ;\n" + "std :: cout << sinhl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sinhl, tokWithNewlines(code_sinhl)); + } + + void simplifyMathFunctions_sin() { + // verify sin(), sinf(), sinl() - simplifcation + const char code_sin[] ="void f(int x) {\n" + " std::cout << sin(x);\n" // do not simplify + " std::cout << sin(10);\n" // do not simplify + " std::cout << sin(0L);\n" // simplify to 0 + "}"; + const char expected_sin[] = "void f ( int x ) {\n" + "std :: cout << sin ( x ) ;\n" + "std :: cout << sin ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sin, tokWithNewlines(code_sin)); + + const char code_sinf[] ="void f(float x) {\n" + " std::cout << sinf(x);\n" // do not simplify + " std::cout << sinf(10);\n" // do not simplify + " std::cout << sinf(0.0f);\n" // simplify to 0 + "}"; + const char expected_sinf[] = "void f ( float x ) {\n" + "std :: cout << sinf ( x ) ;\n" + "std :: cout << sinf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sinf, tokWithNewlines(code_sinf)); + + const char code_sinl[] ="void f(long double x) {\n" + " std::cout << sinl(x);\n" // do not simplify + " std::cout << sinl(10.0f);\n" // do not simplify + " std::cout << sinl(0.0f);\n" // simplify to 0 + "}"; + const char expected_sinl[] = "void f ( double x ) {\n" + "std :: cout << sinl ( x ) ;\n" + "std :: cout << sinl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_sinl, tokWithNewlines(code_sinl)); + + // #6629 + const char code[] = "class Foo { int sinf; Foo() : sinf(0) {} };"; + const char expected[] = "class Foo { int sinf ; Foo ( ) : sinf ( 0 ) { } } ;"; + ASSERT_EQUALS(expected, tokWithNewlines(code)); + } + + void simplifyMathFunctions_ilogb() { + // verify ilogb(), ilogbf(), ilogbl() - simplifcation + const char code_ilogb[] ="void f(int x) {\n" + " std::cout << ilogb(x);\n" // do not simplify + " std::cout << ilogb(10);\n" // do not simplify + " std::cout << ilogb(1L);\n" // simplify to 0 + "}"; + const char expected_ilogb[] = "void f ( int x ) {\n" + "std :: cout << ilogb ( x ) ;\n" + "std :: cout << ilogb ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_ilogb, tokWithNewlines(code_ilogb)); + + const char code_ilogbf[] ="void f(float x) {\n" + " std::cout << ilogbf(x);\n" // do not simplify + " std::cout << ilogbf(10);\n" // do not simplify + " std::cout << ilogbf(1.0f);\n" // simplify to 0 + "}"; + const char expected_ilogbf[] = "void f ( float x ) {\n" + "std :: cout << ilogbf ( x ) ;\n" + "std :: cout << ilogbf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_ilogbf, tokWithNewlines(code_ilogbf)); + + const char code_ilogbl[] ="void f(long double x) {\n" + " std::cout << ilogbl(x);\n" // do not simplify + " std::cout << ilogbl(10.0f);\n" // do not simplify + " std::cout << ilogbl(1.0f);\n" // simplify to 0 + "}"; + const char expected_ilogbl[] = "void f ( double x ) {\n" + "std :: cout << ilogbl ( x ) ;\n" + "std :: cout << ilogbl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_ilogbl, tokWithNewlines(code_ilogbl)); + } + + void simplifyMathFunctions_logb() { + // verify logb(), logbf(), logbl() - simplifcation + const char code_logb[] ="void f(int x) {\n" + " std::cout << logb(x);\n" // do not simplify + " std::cout << logb(10);\n" // do not simplify + " std::cout << logb(1L);\n" // simplify to 0 + "}"; + const char expected_logb[] = "void f ( int x ) {\n" + "std :: cout << logb ( x ) ;\n" + "std :: cout << logb ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_logb, tokWithNewlines(code_logb)); + + const char code_logbf[] ="void f(float x) {\n" + " std::cout << logbf(x);\n" // do not simplify + " std::cout << logbf(10);\n" // do not simplify + " std::cout << logbf(1.0f);\n" // simplify to 0 + "}"; + const char expected_logbf[] = "void f ( float x ) {\n" + "std :: cout << logbf ( x ) ;\n" + "std :: cout << logbf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_logbf, tokWithNewlines(code_logbf)); + + const char code_logbl[] ="void f(long double x) {\n" + " std::cout << logbl(x);\n" // do not simplify + " std::cout << logbl(10.0f);\n" // do not simplify + " std::cout << logbl(1.0f);\n" // simplify to 0 + "}"; + const char expected_logbl[] = "void f ( double x ) {\n" + "std :: cout << logbl ( x ) ;\n" + "std :: cout << logbl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_logbl, tokWithNewlines(code_logbl)); + } + + void simplifyMathFunctions_log1p() { + // verify log1p(), log1pf(), log1pl() - simplifcation + const char code_log1p[] ="void f(int x) {\n" + " std::cout << log1p(x);\n" // do not simplify + " std::cout << log1p(10);\n" // do not simplify + " std::cout << log1p(0L);\n" // simplify to 0 + "}"; + const char expected_log1p[] = "void f ( int x ) {\n" + "std :: cout << log1p ( x ) ;\n" + "std :: cout << log1p ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log1p, tokWithNewlines(code_log1p)); + + const char code_log1pf[] ="void f(float x) {\n" + " std::cout << log1pf(x);\n" // do not simplify + " std::cout << log1pf(10);\n" // do not simplify + " std::cout << log1pf(0.0f);\n" // simplify to 0 + "}"; + const char expected_log1pf[] = "void f ( float x ) {\n" + "std :: cout << log1pf ( x ) ;\n" + "std :: cout << log1pf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log1pf, tokWithNewlines(code_log1pf)); + + const char code_log1pl[] ="void f(long double x) {\n" + " std::cout << log1pl(x);\n" // do not simplify + " std::cout << log1pl(10.0f);\n" // do not simplify + " std::cout << log1pl(0.0f);\n" // simplify to 0 + "}"; + const char expected_log1pl[] = "void f ( double x ) {\n" + "std :: cout << log1pl ( x ) ;\n" + "std :: cout << log1pl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log1pl, tokWithNewlines(code_log1pl)); + } + + void simplifyMathFunctions_log10() { + // verify log10(), log10f(), log10l() - simplifcation + const char code_log10[] ="void f(int x) {\n" + " std::cout << log10(x);\n" // do not simplify + " std::cout << log10(10);\n" // do not simplify + " std::cout << log10(1L);\n" // simplify to 0 + "}"; + const char expected_log10[] = "void f ( int x ) {\n" + "std :: cout << log10 ( x ) ;\n" + "std :: cout << log10 ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log10, tokWithNewlines(code_log10)); + + const char code_log10f[] ="void f(float x) {\n" + " std::cout << log10f(x);\n" // do not simplify + " std::cout << log10f(10);\n" // do not simplify + " std::cout << log10f(1.0f);\n" // simplify to 0 + "}"; + const char expected_log10f[] = "void f ( float x ) {\n" + "std :: cout << log10f ( x ) ;\n" + "std :: cout << log10f ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log10f, tokWithNewlines(code_log10f)); + + const char code_log10l[] ="void f(long double x) {\n" + " std::cout << log10l(x);\n" // do not simplify + " std::cout << log10l(10.0f);\n" // do not simplify + " std::cout << log10l(1.0f);\n" // simplify to 0 + "}"; + const char expected_log10l[] = "void f ( double x ) {\n" + "std :: cout << log10l ( x ) ;\n" + "std :: cout << log10l ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log10l, tokWithNewlines(code_log10l)); + + } + void simplifyMathFunctions_log() { + // verify log(), logf(), logl() - simplifcation + const char code_log[] ="void f(int x) {\n" + " std::cout << log(x);\n" // do not simplify + " std::cout << log(10);\n" // do not simplify + " std::cout << log(1L);\n" // simplify to 0 + "}"; + const char expected_log[] = "void f ( int x ) {\n" + "std :: cout << log ( x ) ;\n" + "std :: cout << log ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log, tokWithNewlines(code_log)); + + const char code_logf[] ="void f(float x) {\n" + " std::cout << logf(x);\n" // do not simplify + " std::cout << logf(10);\n" // do not simplify + " std::cout << logf(1.0f);\n" // simplify to 0 + "}"; + const char expected_logf[] = "void f ( float x ) {\n" + "std :: cout << logf ( x ) ;\n" + "std :: cout << logf ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_logf, tokWithNewlines(code_logf)); + + const char code_logl[] ="void f(long double x) {\n" + " std::cout << logl(x);\n" // do not simplify + " std::cout << logl(10.0f);\n" // do not simplify + " std::cout << logl(1.0f);\n" // simplify to 0 + "}"; + const char expected_logl[] = "void f ( double x ) {\n" + "std :: cout << logl ( x ) ;\n" + "std :: cout << logl ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_logl, tokWithNewlines(code_logl)); + } + + void simplifyMathFunctions_log2() { + // verify log2(), log2f(), log2l() - simplifcation + const char code_log2[] ="void f(int x) {\n" + " std::cout << log2(x);\n" // do not simplify + " std::cout << log2(10);\n" // do not simplify + " std::cout << log2(1L);\n" // simplify to 0 + "}"; + const char expected_log2[] = "void f ( int x ) {\n" + "std :: cout << log2 ( x ) ;\n" + "std :: cout << log2 ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log2, tokWithNewlines(code_log2)); + + const char code_log2f[] ="void f(float x) {\n" + " std::cout << log2f(x);\n" // do not simplify + " std::cout << log2f(10);\n" // do not simplify + " std::cout << log2f(1.0f);\n" // simplify to 0 + "}"; + const char expected_log2f[] = "void f ( float x ) {\n" + "std :: cout << log2f ( x ) ;\n" + "std :: cout << log2f ( 10 ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log2f, tokWithNewlines(code_log2f)); + + const char code_log2l[] ="void f(long double x) {\n" + " std::cout << log2l(x);\n" // do not simplify + " std::cout << log2l(10.0f);\n" // do not simplify + " std::cout << log2l(1.0f);\n" // simplify to 0 + "}"; + const char expected_log2l[] = "void f ( double x ) {\n" + "std :: cout << log2l ( x ) ;\n" + "std :: cout << log2l ( 10.0f ) ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_log2l, tokWithNewlines(code_log2l)); + } + + void simplifyMathFunctions_pow() { + // verify pow(),pow(),powl() - simplifcation + const char code_pow[] ="void f() {\n" + " std::cout << pow(-1.0,1);\n" + " std::cout << pow(1.0,1);\n" + " std::cout << pow(0,1);\n" + " std::cout << pow(1,-6);\n" + " std::cout << powf(-1.0,1.0f);\n" + " std::cout << powf(1.0,1.0f);\n" + " std::cout << powf(0,1.0f);\n" + " std::cout << powf(1.0,-6.0f);\n" + " std::cout << powl(-1.0,1.0);\n" + " std::cout << powl(1.0,1.0);\n" + " std::cout << powl(0,1.0);\n" + " std::cout << powl(1.0,-6.0d);\n" + "}"; + + const char expected_pow[] = "void f ( ) {\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 1 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 1 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 1 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1 ;\n" + "}"; + ASSERT_EQUALS(expected_pow, tokWithNewlines(code_pow)); + + // verify if code is simplified correctly. + // Do not simplify class members. + const char code_pow1[] = "int f(const Fred &fred) {return fred.pow(12,3);}"; + const char expected_pow1[] = "int f ( const Fred & fred ) { return fred . pow ( 12 , 3 ) ; }"; + ASSERT_EQUALS(expected_pow1, tokWithNewlines(code_pow1)); + + const char code_pow2[] = "int f() {return pow(0,0);}"; + const char expected_pow2[] = "int f ( ) { return 1 ; }"; + ASSERT_EQUALS(expected_pow2, tokWithNewlines(code_pow2)); + + const char code_pow3[] = "int f() {return pow(0,1);}"; + const char expected_pow3[] = "int f ( ) { return 0 ; }"; + ASSERT_EQUALS(expected_pow3, tokWithNewlines(code_pow3)); + + const char code_pow4[] = "int f() {return pow(1,0);}"; + const char expected_pow4[] = "int f ( ) { return 1 ; }"; + ASSERT_EQUALS(expected_pow4, tokWithNewlines(code_pow4)); + } + + void simplifyMathFunctions_fmin() { + // verify fmin,fminl,fminl simplifcation + const char code_fmin[] ="void f() {\n" + " std::cout << fmin(-1.0,0);\n" + " std::cout << fmin(1.0,0);\n" + " std::cout << fmin(0,0);\n" + " std::cout << fminf(-1.0,0);\n" + " std::cout << fminf(1.0,0);\n" + " std::cout << fminf(0,0);\n" + " std::cout << fminl(-1.0,0);\n" + " std::cout << fminl(1.0,0);\n" + " std::cout << fminl(0,0);\n" + "}"; + + const char expected_fmin[] = "void f ( ) {\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << -1.0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_fmin, tokWithNewlines(code_fmin)); + + // do not simplify this case + const char code_fmin1[] = "float f(float f) { return fmin(f,0);}"; + const char expected_fmin1[] = "float f ( float f ) { return fmin ( f , 0 ) ; }"; + ASSERT_EQUALS(expected_fmin1, tokWithNewlines(code_fmin1)); + } + + void simplifyMathFunctions_fmax() { + // verify fmax(),fmax(),fmaxl() simplifcation + const char code_fmax[] ="void f() {\n" + " std::cout << fmax(-1.0,0);\n" + " std::cout << fmax(1.0,0);\n" + " std::cout << fmax(0,0);\n" + " std::cout << fmaxf(-1.0,0);\n" + " std::cout << fmaxf(1.0,0);\n" + " std::cout << fmaxf(0,0);\n" + " std::cout << fmaxl(-1.0,0);\n" + " std::cout << fmaxl(1.0,0);\n" + " std::cout << fmaxl(0,0);\n" + "}"; + + const char expected_fmax[] = "void f ( ) {\n" + "std :: cout << 0 ;\n" + "std :: cout << 1.0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1.0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 0 ;\n" + "std :: cout << 1.0 ;\n" + "std :: cout << 0 ;\n" + "}"; + ASSERT_EQUALS(expected_fmax, tokWithNewlines(code_fmax)); + + // do not simplify this case + const char code_fmax1[] = "float f(float f) { return fmax(f,0);}"; + const char expected_fmax1[] = "float f ( float f ) { return fmax ( f , 0 ) ; }"; + ASSERT_EQUALS(expected_fmax1, tokWithNewlines(code_fmax1)); + } + + void simplifyMathExpressions() { //#1620 + const char code1[] = "void foo() {\n" + " std::cout<centerX, h->centerY, 1 + index }, 1);")); + } + + void simplifyCompoundAssignment() { + ASSERT_EQUALS("; x = x + y ;", tok("; x += y;")); + ASSERT_EQUALS("; x = x - y ;", tok("; x -= y;")); + ASSERT_EQUALS("; x = x * y ;", tok("; x *= y;")); + ASSERT_EQUALS("; x = x / y ;", tok("; x /= y;")); + ASSERT_EQUALS("; x = x % y ;", tok("; x %= y;")); + ASSERT_EQUALS("; x = x & y ;", tok("; x &= y;")); + ASSERT_EQUALS("; x = x | y ;", tok("; x |= y;")); + ASSERT_EQUALS("; x = x ^ y ;", tok("; x ^= y;")); + ASSERT_EQUALS("; x = x << y ;", tok("; x <<= y;")); + ASSERT_EQUALS("; x = x >> y ;", tok("; x >>= y;")); + + ASSERT_EQUALS("{ x = x + y ; }", tok("{ x += y;}")); + ASSERT_EQUALS("{ x = x - y ; }", tok("{ x -= y;}")); + ASSERT_EQUALS("{ x = x * y ; }", tok("{ x *= y;}")); + ASSERT_EQUALS("{ x = x / y ; }", tok("{ x /= y;}")); + ASSERT_EQUALS("{ x = x % y ; }", tok("{ x %= y;}")); + ASSERT_EQUALS("{ x = x & y ; }", tok("{ x &= y;}")); + ASSERT_EQUALS("{ x = x | y ; }", tok("{ x |= y;}")); + ASSERT_EQUALS("{ x = x ^ y ; }", tok("{ x ^= y;}")); + ASSERT_EQUALS("{ x = x << y ; }", tok("{ x <<= y;}")); + ASSERT_EQUALS("{ x = x >> y ; }", tok("{ x >>= y;}")); + + ASSERT_EQUALS("; * p = * p + y ;", tok("; *p += y;")); + ASSERT_EQUALS("; ( * p ) = ( * p ) + y ;", tok("; (*p) += y;")); + ASSERT_EQUALS("; * ( p [ 0 ] ) = * ( p [ 0 ] ) + y ;", tok("; *(p[0]) += y;")); + ASSERT_EQUALS("; p [ { 1 , 2 } ] = p [ { 1 , 2 } ] + y ;", tok("; p[{1,2}] += y;")); + + ASSERT_EQUALS("void foo ( ) { switch ( n ) { case 0 : ; x = x + y ; break ; } }", tok("void foo() { switch (n) { case 0: x += y; break; } }")); + + ASSERT_EQUALS("; x . y = x . y + 1 ;", tok("; x.y += 1;")); + + ASSERT_EQUALS("; x [ 0 ] = x [ 0 ] + 1 ;", tok("; x[0] += 1;")); + ASSERT_EQUALS("; x [ y - 1 ] = x [ y - 1 ] + 1 ;", tok("; x[y-1] += 1;")); + ASSERT_EQUALS("; x [ y ] = x [ y ++ ] + 1 ;", tok("; x[y++] += 1;")); + ASSERT_EQUALS("; x [ ++ y ] = x [ y ] + 1 ;", tok("; x[++y] += 1;")); + + ASSERT_EQUALS(";", tok(";x += 0;")); + TODO_ASSERT_EQUALS(";", "; x = x + '\\0' ;", tok("; x += '\\0'; ")); + ASSERT_EQUALS(";", tok(";x -= 0;")); + ASSERT_EQUALS(";", tok(";x |= 0;")); + ASSERT_EQUALS(";", tok(";x *= 1;")); + ASSERT_EQUALS(";", tok(";x /= 1;")); + + ASSERT_EQUALS("; a . x ( ) = a . x ( ) + 1 ;", tok("; a.x() += 1;")); + ASSERT_EQUALS("; x ( 1 ) = x ( 1 ) + 1 ;", tok("; x(1) += 1;")); + + // #2368 + ASSERT_EQUALS("{ j = j - i ; }", tok("{if (false) {} else { j -= i; }}")); + + // #2714 - wrong simplification of "a += b?c:d;" + ASSERT_EQUALS("; a = a + ( b ? c : d ) ;", tok("; a+=b?c:d;")); + ASSERT_EQUALS("; a = a * ( b + 1 ) ;", tok("; a*=b+1;")); + + ASSERT_EQUALS("; a = a + ( b && c ) ;", tok("; a+=b&&c;")); + ASSERT_EQUALS("; a = a * ( b || c ) ;", tok("; a*=b||c;")); + ASSERT_EQUALS("; a = a | ( b == c ) ;", tok("; a|=b==c;")); + + // #3469 + ASSERT_EQUALS("; a = a + ( b = 1 ) ;", tok("; a += b = 1;")); + + // #7571 + ASSERT_EQUALS("; foo = foo + [ & ] ( ) { } ;", tok("; foo += [&]() {int i;};")); + + // #8796 + ASSERT_EQUALS("{ return ( a = b ) += c ; }", tok("{ return (a = b) += c; }")); + } + + + void cast() { + ASSERT_EQUALS("{ if ( p == 0 ) { ; } }", tok("{if (p == (char *)0);}")); + ASSERT_EQUALS("{ return str ; }", tok("{return (char *)str;}")); + + ASSERT_EQUALS("{ if ( * a ) }", tok("{if ((char)*a)}")); + ASSERT_EQUALS("{ if ( & a ) }", tok("{if ((int)&a)}")); + ASSERT_EQUALS("{ if ( * a ) }", tok("{if ((unsigned int)(unsigned char)*a)}")); + ASSERT_EQUALS("class A { A operator* ( int ) ; } ;", tok("class A { A operator *(int); };")); + ASSERT_EQUALS("class A { A operator* ( int ) const ; } ;", tok("class A { A operator *(int) const; };")); + ASSERT_EQUALS("{ if ( p == 0 ) { ; } }", tok("{ if (p == (char *)(char *)0); }")); + ASSERT_EQUALS("{ if ( p == 0 ) { ; } }", tok("{ if (p == (char **)0); }")); + + // no simplification as the cast may be important here. see #2897 for example + ASSERT_EQUALS("; * ( ( char * ) p + 1 ) = 0 ;", tok("; *((char *)p + 1) = 0;")); + + ASSERT_EQUALS("{ if ( true ) }", tok("{ if ((unsigned char)1) }")); // #4164 + ASSERT_EQUALS("f ( 200 )", tok("f((unsigned char)200)")); + ASSERT_EQUALS("f ( ( char ) 1234 )", tok("f((char)1234)")); // don't simplify downcast + } + + + void iftruefalse() { + { + const char code1[] = " void f() { int a; bool use = false; if( use ) { a=0; } else {a=1;} }"; + const char code2[] = " void f() { int a; bool use = false; {a=1;} }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; bool use = true; if( use ) { a=0; } else {a=1;} }"; + const char code2[] = " void f() { int a; bool use = true; { a=0; } }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; int use = 5; if( use ) { a=0; } else {a=1;} }"; + const char code2[] = " void f() { int a; int use = 5; { a=0; } }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; int use = 0; if( use ) { a=0; } else {a=1;} }"; + const char code2[] = " void f() { int a; int use = 0; {a=1;} }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; bool use = false; if( use ) a=0; else a=1; int c=1; }"; + const char code2[] = " void f() { int a; bool use = false; { a=1; } int c=1; }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; bool use = true; if( use ) a=0; else a=1; int c=1; }"; + const char code2[] = " void f() { int a; bool use = true; { a=0; } int c=1; }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; bool use = false; if( use ) a=0; else if( bb ) a=1; int c=1; }"; + const char code2[] = " void f ( ) { int a ; bool use ; use = false ; { if ( bb ) { a = 1 ; } } int c ; c = 1 ; }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { int a; bool use = true; if( use ) a=0; else if( bb ) a=1; int c=1; }"; + const char code2[] = " void f() { int a; bool use = true; { a=0;} int c=1; }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = "void f() { int a; bool use = true; if( use ) a=0; else if( bb ) a=1; else if( cc ) a=33; else { gg = 0; } int c=1; }"; + const char code2[] = "void f ( ) { }"; + ASSERT_EQUALS(code2, tok(code1)); + } + + { + const char code1[] = " void f() { if( aa ) { a=0; } else if( true ) a=1; else { a=2; } }"; + const char code2[] = " void f ( ) { if ( aa ) { a = 0 ; } else { { a = 1 ; } } }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = " void f() { if( aa ) { a=0; } else if( false ) a=1; else { a=2; } }"; + const char code2[] = " void f ( ) { if ( aa ) { a = 0 ; } else { { a = 2 ; } } }"; + ASSERT_EQUALS(tok(code2), tok(code1)); + } + + { + const char code1[] = "static const int x=1; void f() { if(x) { a=0; } }"; + ASSERT_EQUALS("void f ( ) { a = 0 ; }", tok(code1)); + } + } void combine_strings() { const char code1[] = "void foo()\n" @@ -449,6 +2034,38 @@ private: } } + + void parentheses1() { + ASSERT_EQUALS("a <= 110 ;", tok("a <= (10+100);")); + ASSERT_EQUALS("{ while ( x ( ) == -1 ) { } }", tok("{while((x()) == -1){ }}")); + } + + void parenthesesVar() { + // remove parentheses.. + ASSERT_EQUALS("a = p ;", tok("a = (p);")); + ASSERT_EQUALS("void f ( ) { if ( a < p ) { } }", tok("void f(){if(a<(p)){}}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( p == -1 ) { } }", tok("void f(){int p; if((p)==-1){}}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( -1 == p ) { } }", tok("void f(){int p; if(-1==(p)){}}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( p ) { } }", tok("void f(){int p; if((p)){}}")); + ASSERT_EQUALS("void f ( ) { return p ; }", tok("void f(){return (p);}")); + ASSERT_EQUALS("void f ( ) { int * p ; if ( * p == 0 ) { } }", tok("void f(){int *p; if (*(p) == 0) {}}")); + ASSERT_EQUALS("void f ( ) { int * p ; if ( * p == 0 ) { } }", tok("void f(){int *p; if (*p == 0) {}}")); + ASSERT_EQUALS("void f ( int & p ) { p = 1 ; }", tok("void f(int &p) {(p) = 1;}")); + ASSERT_EQUALS("void f ( ) { int p [ 10 ] ; p [ 0 ] = 1 ; }", tok("void f(){int p[10]; (p)[0] = 1;}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( p == 0 ) { } }", tok("void f(){int p; if ((p) == 0) {}}")); + ASSERT_EQUALS("void f ( ) { int * p ; * p = 1 ; }", tok("void f(){int *p; *(p) = 1;}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( p ) { } p = 1 ; }", tok("void f(){int p; if ( p ) { } (p) = 1;}")); + ASSERT_EQUALS("void f ( ) { a . b ; }", tok("void f ( ) { ( & a ) -> b ; }")); // Ticket #5776 + + // keep parentheses.. + ASSERT_EQUALS("b = a ;", tok("b = (char)a;")); + ASSERT_EQUALS("cast < char * > ( p ) ;", tok("cast(p);")); + ASSERT_EQUALS("void f ( ) { return ( a + b ) * c ; }", tok("void f(){return (a+b)*c;}")); + ASSERT_EQUALS("void f ( ) { int p ; if ( 2 * p == 0 ) { } }", tok("void f(){int p; if (2*p == 0) {}}")); + ASSERT_EQUALS("void f ( ) { DIR * f ; f = opendir ( dirname ) ; if ( closedir ( f ) ) { } }", tok("void f(){DIR * f = opendir(dirname);if (closedir(f)){}}")); + ASSERT_EQUALS("void foo ( int p ) { if ( p >= 0 ) { ; } }", tok("void foo(int p){if((p)>=0);}")); + } + void declareVar() { const char code[] = "void f ( ) { char str [ 100 ] = \"100\" ; }"; ASSERT_EQUALS(code, tok(code)); @@ -472,6 +2089,68 @@ private: ASSERT_EQUALS(expected4, tok(code4)); } + void dontRemoveIncrement() { + { + const char code[] = "void f(int a)\n" + "{\n" + " if (a > 10)\n" + " a = 5;\n" + " else\n" + " a = 10;\n" + " a++;\n" + "}\n"; + ASSERT_EQUALS("void f ( int a ) { if ( a > 10 ) { a = 5 ; } else { a = 10 ; } a ++ ; }", tok(code)); + } + + { + const char code[] = "void f(int a)\n" + "{\n" + " if (a > 10)\n" + " a = 5;\n" + " else\n" + " a = 10;\n" + " ++a;\n" + "}\n"; + ASSERT_EQUALS("void f ( int a ) { if ( a > 10 ) { a = 5 ; } else { a = 10 ; } ++ a ; }", tok(code)); + } + } + + void removePostIncrement() { + const char code[] = "void f(int &c)\n" + "{\n" + " c = 0;\n" + " c++;\n" + " if (c>0) { c++; }\n" + " c++;\n" + "}\n"; + TODO_ASSERT_EQUALS("void f ( int & c ) { c = 3 ; { ; } ; }", + "void f ( int & c ) { c = 1 ; { c ++ ; } c ++ ; }", tok(code)); + } + + + void removePreIncrement() { + { + const char code[] = "void f(int &c)\n" + "{\n" + " c = 0;\n" + " ++c;\n" + " if (c>0) { ++c; }\n" + " ++c;\n" + "}\n"; + TODO_ASSERT_EQUALS("void f ( int & c ) { c = 3 ; { ; } ; }", + "void f ( int & c ) { c = 1 ; { ++ c ; } ++ c ; }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " char a[] = \"p\";\n" + " ++a[0];\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { char a [ 2 ] = \"p\" ; ++ a [ 0 ] ; }", tok(code)); + } + } + void elseif1() { const char code[] = "void f(){ if(x) {} else if(ab) { cd } else { ef }gh; }"; ASSERT_EQUALS("\n\n##file 0\n1: void f ( ) { if ( x ) { } else { if ( ab ) { cd } else { ef } } gh ; }\n", tokenizeDebugListing(code)); @@ -528,6 +2207,677 @@ private: } + unsigned int sizeofFromTokenizer(const char type[]) { + Tokenizer tokenizer(&settings0, this); + tokenizer.fillTypeSizes(); + Token tok1; + tok1.str(type); + return tokenizer.sizeOfType(&tok1); + } + + + + void sizeof_array() { + const char *code; + + code = "void foo()\n" + "{\n" + " int i[4];\n" + " sizeof(i);\n" + " sizeof(*i);\n" + "}\n"; + ASSERT_EQUALS("void foo ( ) { int i [ 4 ] ; 16 ; 4 ; }", tok(code)); + + code = "static int i[4];\n" + "void f()\n" + "{\n" + " int i[10];\n" + " sizeof(i);\n" + "}\n"; + ASSERT_EQUALS("static int i [ 4 ] ; void f ( ) { int i [ 10 ] ; 40 ; }", tok(code)); + { + code = "int i[10];\n" + "sizeof(i[0]);\n"; + ASSERT_EQUALS("int i [ 10 ] ; 4 ;", tok(code)); + + code = "int i[10];\n" + "sizeof i[0];\n"; + ASSERT_EQUALS("int i [ 10 ] ; 4 ;", tok(code)); + } + + code = "char i[2][20];\n" + "sizeof(i[1]);\n" + "sizeof(i);"; + ASSERT_EQUALS("char i [ 2 ] [ 20 ] ; 20 ; 40 ;", tok(code)); + + code = "char i[2][20][30];\n" + "sizeof(i[1][4][2]);\n" + "sizeof(***i);\n" + "sizeof(i[1][4]);\n" + "sizeof(**i);\n" + "sizeof(i[1]);\n" + "sizeof(*i);\n" + "sizeof(i);"; + ASSERT_EQUALS("char i [ 2 ] [ 20 ] [ 30 ] ; 1 ; 1 ; 30 ; 30 ; 600 ; 600 ; 1200 ;", tok(code)); + + code = "sizeof(char[20]);\n" + "sizeof(char[20][3]);\n" + "sizeof(char[unknown][3]);"; + ASSERT_EQUALS("20 ; 60 ; sizeof ( char [ unknown ] [ 3 ] ) ;", tok(code)); + } + + void sizeof5() { + const char code[] = + "{" + "const char * names[2];" + "for (int i = 0; i != sizeof(names[0]); i++)" + "{}" + "}"; + std::ostringstream expected; + expected << "{ const char * names [ 2 ] ; for ( int i = 0 ; i != " << sizeofFromTokenizer("*") << " ; i ++ ) { } }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + void sizeof6() { + const char code[] = ";int i;\n" + "sizeof(i);\n"; + + std::ostringstream expected; + expected << "; int i ; " << sizeof(int) << " ;"; + + ASSERT_EQUALS(expected.str(), tok(code)); + } + + void sizeof7() { + const char code[] = ";INT32 i[10];\n" + "sizeof(i[0]);\n"; + ASSERT_EQUALS("; INT32 i [ 10 ] ; sizeof ( i [ 0 ] ) ;", tok(code, true, Settings::Native)); + ASSERT_EQUALS("; int i [ 10 ] ; 4 ;", tokWithWindows(code, true, Settings::Win32A)); + } + + void sizeof8() { + { + const char code[] = "void f()\n" + "{\n" + " char* ptrs[2];\n" + " a = sizeof( ptrs );\n" + "}\n"; + std::ostringstream oss; + oss << (sizeofFromTokenizer("*") * 2); + ASSERT_EQUALS("void f ( ) { char * ptrs [ 2 ] ; a = " + oss.str() + " ; }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " char* ptrs[55];\n" + " a = sizeof( ptrs );\n" + "}\n"; + std::ostringstream oss; + oss << (sizeofFromTokenizer("*") * 55); + ASSERT_EQUALS("void f ( ) { char * ptrs [ 55 ] ; a = " + oss.str() + " ; }", tok(code)); + } + + + { + const char code[] = "void f()\n" + "{\n" + " char* ptrs;\n" + " a = sizeof( ptrs );\n" + "}\n"; + std::ostringstream oss; + oss << sizeofFromTokenizer("*"); + ASSERT_EQUALS("void f ( ) { a = " + oss.str() + " ; }", tok(code)); + } + } + + void sizeof9() { + // ticket #487 + { + const char code[] = "; const char *str = \"1\"; sizeof(str);"; + + std::ostringstream expected; + expected << "; const char * str ; str = \"1\" ; " << sizeofFromTokenizer("*") << " ;"; + + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "; const char str[] = \"1\"; sizeof(str);"; + + std::ostringstream expected; + expected << "; const char str [ 2 ] = \"1\" ; " << sizeofFromTokenizer("char")*2 << " ;"; + + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + // Ticket #799 + const char code[] = "; const char str[] = {'1'}; sizeof(str);"; + ASSERT_EQUALS("; const char str [ 1 ] = { '1' } ; 1 ;", tok(code)); + } + + { + // Ticket #2087 + const char code[] = "; const char str[] = {\"abc\"}; sizeof(str);"; + ASSERT_EQUALS("; const char str [ 4 ] = \"abc\" ; 4 ;", tok(code)); + } + + // ticket #716 - sizeof string + { + std::ostringstream expected; + expected << "; " << (sizeof "123") << " ;"; + + ASSERT_EQUALS(expected.str(), tok("; sizeof \"123\";")); + ASSERT_EQUALS(expected.str(), tok("; sizeof(\"123\");")); + } + + { + const char code[] = "void f(char *a,char *b, char *c)" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( char * a , char * b , char * c ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(char a,char b, char c)" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( char a , char b , char c ) { g ( " << + sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(const char *a,const char *b, const char *c)" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( const char * a , const char * b , const char * c ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(char a[10],char b[10], char c[10])" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( char a [ 10 ] , char b [ 10 ] , char c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(const char a[10],const char b[10], const char c[10])" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( const char a [ 10 ] , " + "const char b [ 10 ] , " + "const char c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(const char *a[10],const char *b[10], const char *c[10])" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( const char * a [ 10 ] , " + "const char * b [ 10 ] , " + "const char * c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + const char code[] = "void f(char *a[10],char *b[10], char *c[10])" + "{g(sizeof(a),sizeof(b),sizeof(c));}"; + std::ostringstream expected; + expected << "void f ( char * a [ 10 ] , char * b [ 10 ] , char * c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + ASSERT_EQUALS(expected.str(), tok(code)); + } + + { + std::ostringstream expected; + expected << "; " << sizeof("\"quote\""); + ASSERT_EQUALS(expected.str(), tok("; sizeof(\"\\\"quote\\\"\")")); + } + + { + std::ostringstream expected; + expected << "void f ( ) { char str [ 100 ] = \"100\" ; " << sizeofFromTokenizer("char")*100 << " }"; + ASSERT_EQUALS(expected.str(), tok("void f ( ) { char str [ 100 ] = \"100\" ; sizeof ( str ) }")); + } + } + + void sizeof10() { + // ticket #809 + const char code[] = "int m ; " + "compat_ulong_t um ; " + "long size ; size = sizeof ( m ) / sizeof ( um ) ;"; + + ASSERT_EQUALS(code, tok(code, true, Settings::Win32A)); + } + + void sizeof11() { + // ticket #827 + const char code[] = "void f()\n" + "{\n" + " char buf2[4];\n" + " sizeof buf2;\n" + "}\n" + "\n" + "void g()\n" + "{\n" + " struct A a[2];\n" + " char buf[32];\n" + " sizeof buf;\n" + "}"; + + const char expected[] = "void f ( ) " + "{" + " char buf2 [ 4 ] ;" + " 4 ; " + "} " + "" + "void g ( ) " + "{" + " struct A a [ 2 ] ;" + " char buf [ 32 ] ;" + " 32 ; " + "}"; + + ASSERT_EQUALS(expected, tok(code)); + } + + void sizeof12() { + // ticket #827 + const char code[] = "void f()\n" + "{\n" + " int *p;\n" + " (sizeof *p);\n" + "}"; + + const char expected[] = "void f ( ) " + "{" + "" + " 4 ; " + "}"; + + ASSERT_EQUALS(expected, tok(code)); + } + + void sizeof13() { + // ticket #851 + const char code[] = "int main()\n" + "{\n" + " char *a;\n" + " a = malloc(sizeof(*a));\n" + "}\n" + "\n" + "struct B\n" + "{\n" + " char * b[2];\n" + "};"; + const char expected[] = "int main ( ) " + "{" + " char * a ;" + " a = malloc ( 1 ) ; " + "} " + "struct B " + "{" + " char * b [ 2 ] ; " + "} ;"; + ASSERT_EQUALS(expected, tok(code)); + } + + void sizeof14() { + // ticket #954 + const char code[] = "void f()\n" + "{\n" + " A **a;\n" + " int aa = sizeof *(*a)->b;\n" + "}\n"; + const char expected[] = "void f ( ) " + "{" + " A * * a ;" + " int aa ; aa = sizeof ( * ( * a ) . b ) ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + + // #5064 - sizeof !! (a == 1); + ASSERT_EQUALS("sizeof ( ! ! ( a == 1 ) ) ;", tok("sizeof !!(a==1);")); + } + + void sizeof15() { + // ticket #1020 + tok("void f()\n" + "{\n" + " int *n;\n" + " sizeof *(n);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + + void sizeof16() { + // ticket #1027 + const char code[] = "void f()\n" + "{\n" + " int a;\n" + " printf(\"%i\", sizeof a++);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { int a ; printf ( \"%i\" , sizeof ( a ++ ) ) ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + void sizeof17() { + // ticket #1050 + const char code[] = "void f()\n" + "{\n" + " sizeof 1;\n" + " while (0);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { sizeof ( 1 ) ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + void sizeof18() { + { + std::ostringstream expected; + expected << sizeof(short int); + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(short int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(unsigned short int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(short unsigned int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(signed short int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + } + + { + std::ostringstream expected; + expected << sizeof(long long); + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(long long);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(signed long long);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(unsigned long long);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(long unsigned long);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(long long int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(signed long long int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(unsigned long long int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(long unsigned long int);\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(char*);\n" + "}\n"; + std::ostringstream expected; + expected << sizeof(int*); + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof(unsigned int*);\n" + "}\n"; + std::ostringstream expected; + expected << sizeof(int*); + ASSERT_EQUALS("void f ( ) { " + expected.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + } + + void sizeof19() { + // ticket #1891 - sizeof 'x' + { + const char code[] = "void f()\n" + "{\n" + " sizeof 'x';\n" + "}\n"; + std::ostringstream sz; + sz << sizeof('x'); + ASSERT_EQUALS("void f ( ) { " + sz.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "void f()\n" + "{\n" + " sizeof('x');\n" + "}\n"; + std::ostringstream sz; + sz << sizeof('x'); + ASSERT_EQUALS("void f ( ) { " + sz.str() + " ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + } + + void sizeof20() { + // ticket #2024 - sizeof a) + const char code[] = "struct struct_a {\n" + " char a[20];\n" + "};\n" + "\n" + "void foo() {\n" + " struct_a a;\n" + " append(sizeof a).append();\n" + "}\n"; + ASSERT_EQUALS("struct struct_a { char a [ 20 ] ; } ; " + "void foo ( ) {" + " struct_a a ;" + " append ( sizeof ( a ) ) . append ( ) ; " + "}", tok(code)); + } + + void sizeof21() { + // ticket #2232 - sizeof...(Args) + const char code[] = "struct Internal {\n" + " int operator()(const Args&... args) const {\n" + " int n = sizeof...(Args);\n" + " return n;\n" + " }\n" + "};\n" + "\n" + "int main() {\n" + " Internal internal;\n" + " int n = 0; n = internal(1);\n" + " return 0;\n" + "}\n"; + + // don't segfault + tok(code); + } + + void sizeof22() { + // sizeof from library + const char code[] = "foo(sizeof(uint32_t), sizeof(std::uint32_t));"; + TODO_ASSERT_EQUALS("foo ( 4 , 4 ) ;", "foo ( 4 , sizeof ( std :: uint32_t ) ) ;", tokWithStdLib(code)); + } + + void sizeofsizeof() { + // ticket #1682 + const char code[] = "void f()\n" + "{\n" + " sizeof sizeof 1;\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { sizeof ( sizeof ( 1 ) ) ; }", tok(code)); + ASSERT_EQUALS("", errout.str()); + } + + void casting() { + { + const char code[] = "void f()\n" + "{\n" + "for (int i = 0; i < static_cast(3); ++i) {}\n" + "}\n"; + + const char expected[] = "void f ( ) { for ( int i = 0 ; i < 3 ; ++ i ) { } }"; + + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " p = const_cast qtu ();\n" + "}\n"; + + const char expected[] = "void f ( ) { p = const_cast < char * > qtu ( ) ; }"; + + ASSERT_EQUALS(expected, tok(code)); + } + + { + // ticket #645 + const char code[] = "void f()\n" + "{\n" + " return dynamic_cast((bar()));\n" + "}\n"; + const char expected[] = "void f ( ) { return bar ( ) ; }"; + + ASSERT_EQUALS(expected, tok(code)); + } + } + + + void strlen1() { + ASSERT_EQUALS("4", tok("strlen(\"abcd\")")); + + { + const char code[] = "void f()\n" + "{\n" + " const char *s = \"abcd\";\n" + " strlen(s);\n" + "}\n"; + const char expected[] = "void f ( ) " + "{" + " const char * s ;" + " s = \"abcd\" ;" + " 4 ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " const char s [ ] = \"abcd\";\n" + " strlen(s);\n" + "}\n"; + const char expected[] = "void f ( ) " + "{" + " const char s [ 5 ] = \"abcd\" ;" + " 4 ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + } + + void strlen2() { + // #4530 - make sure calculation with strlen is simplified + ASSERT_EQUALS("i = -4 ;", + tok("i = (strlen(\"abcd\") - 8);")); + } + void namespaces() { { @@ -567,76 +2917,209 @@ private: } } + + std::string simplifyIfAndWhileAssign(const char code[]) { + // tokenize.. + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.simplifyIfAndWhileAssign(); + + return tokenizer.tokens()->stringifyList(nullptr, false); + } + + void ifassign1() { + ASSERT_EQUALS("{ a = b ; if ( a ) { ; } }", simplifyIfAndWhileAssign("{if(a=b);}")); + ASSERT_EQUALS("{ a = b ( ) ; if ( a ) { ; } }", simplifyIfAndWhileAssign("{if((a=b()));}")); + ASSERT_EQUALS("{ a = b ( ) ; if ( ! ( a ) ) { ; } }", simplifyIfAndWhileAssign("{if(!(a=b()));}")); + ASSERT_EQUALS("{ a . x = b ( ) ; if ( ! ( a . x ) ) { ; } }", simplifyIfAndWhileAssign("{if(!(a->x=b()));}")); + ASSERT_EQUALS("void f ( ) { A ( ) a = b ; if ( a ) { ; } }", simplifyIfAndWhileAssign("void f() { A() if(a=b); }")); + ASSERT_EQUALS("void foo ( int a ) { a = b ( ) ; if ( a >= 0 ) { ; } }", tok("void foo(int a) {if((a=b())>=0);}")); + TODO_ASSERT_EQUALS("void foo ( A a ) { a . c = b ( ) ; if ( 0 <= a . c ) { ; } }", + "void foo ( A a ) { a . c = b ( ) ; if ( a . c >= 0 ) { ; } }", + tok("void foo(A a) {if((a.c=b())>=0);}")); + } + + void ifAssignWithCast() { + const char *code = "void foo()\n" + "{\n" + "FILE *f;\n" + "if( (f = fopen(\"foo\", \"r\")) == ((FILE*)NULL) )\n" + "return(-1);\n" + "fclose(f);\n" + "}\n"; + const char *expected = "void foo ( ) " + "{ " + "FILE * f ; " + "f = fopen ( \"foo\" , \"r\" ) ; " + "if ( f == NULL ) " + "{ " + "return -1 ; " + "} " + "fclose ( f ) ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + void whileAssign1() { + ASSERT_EQUALS("{ a = b ; while ( a ) { b = 0 ; a = b ; } }", simplifyIfAndWhileAssign("{while(a=b) { b = 0; }}")); + ASSERT_EQUALS("{ a . b = c ; while ( a . b ) { c = 0 ; a . b = c ; } }", simplifyIfAndWhileAssign("{while(a.b=c) { c=0; }}")); + ASSERT_EQUALS("{ " + "struct hfs_bnode * node ; " + "struct hfs_btree * tree ; " + "node = tree . node_hash [ i ++ ] ; " + "while ( node ) { node = tree . node_hash [ i ++ ] ; } " + "}", + tok("{" + "struct hfs_bnode *node;" + "struct hfs_btree *tree;" + "while ((node = tree->node_hash[i++])) { }" + "}")); + ASSERT_EQUALS("{ char * s ; s = new char [ 10 ] ; while ( ! s ) { s = new char [ 10 ] ; } }", + tok("{ char *s; while (0 == (s=new char[10])) { } }")); + } + + void whileAssign2() { + // #1909 - Internal error + tok("void f()\n" + "{\n" + " int b;\n" + " while (b = sizeof (struct foo { int i0;}))\n" + " ;\n" + " if (!(0 <= b ))\n" + " ;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + + void whileAssign3() { + // #4254 - Variable id + const char code[] = "void f() {\n" + " int a;\n" + " while (a = x());\n" + "}"; + ASSERT_EQUALS("\n\n##file 0\n" + "1: void f ( ) {\n" + "2: int a@1 ;\n" + "3: a@1 = x ( ) ; while ( a@1 ) { ; a@1 = x ( ) ; }\n" + "4: }\n", tokenizeDebugListing(code, true, "test.c")); + } + + void whileAssign4() { + errout.str(""); + + Tokenizer tokenizer(&settings0, this); + std::istringstream istr("{ while (!(m = q->push(x))) {} }"); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.simplifyTokenList2(); + + ASSERT_EQUALS("{ m = q . push < Message > ( x ) ; while ( ! m ) { m = q . push < Message > ( x ) ; } }", tokenizer.tokens()->stringifyList(nullptr, false)); + ASSERT(tokenizer.tokens()->tokAt(26) != nullptr); + if (tokenizer.tokens()->tokAt(26)) { + ASSERT(tokenizer.tokens()->linkAt(6) == tokenizer.tokens()->tokAt(8)); + ASSERT(tokenizer.tokens()->linkAt(24) == tokenizer.tokens()->tokAt(26)); + } + } + + void doWhileAssign() { + ASSERT_EQUALS("{ do { a = b ; } while ( a ) ; }", simplifyIfAndWhileAssign("{ do { } while(a=b); }")); + ASSERT_EQUALS("{ do { a . a = 0 ; a . b = c ; } while ( a . b ) ; }", simplifyIfAndWhileAssign("{ do { a.a = 0; } while(a.b=c); }")); + ASSERT_EQUALS("{ " + "struct hfs_bnode * node ; " + "struct hfs_btree * tree ; " + "do { node = tree . node_hash [ i ++ ] ; } while ( node ) ; " + "}", + tok("{" + "struct hfs_bnode *node;" + "struct hfs_btree *tree;" + "do { } while((node = tree->node_hash[i++]));" + "}")); + ASSERT_EQUALS("void foo ( ) { char * s ; do { s = new char [ 10 ] ; } while ( ! s ) ; }", + tok("void foo() { char *s; do { } while (0 == (s=new char[10])); }")); + // #4911 + ASSERT_EQUALS("void foo ( ) { do { current = f ( ) ; } while ( ( current ) != NULL ) ; }", simplifyIfAndWhileAssign("void foo() { do { } while((current=f()) != NULL); }")); + } + void not1() { - ASSERT_EQUALS("void f ( ) { if ( ! p ) { ; } }", tok("void f() { if (not p); }", "test.c")); - ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", tok("void f() { if (p && not q); }", "test.c")); - ASSERT_EQUALS("void f ( ) { a = ! ( p && q ) ; }", tok("void f() { a = not(p && q); }", "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! p ) { ; } }", tok("void f() { if (not p); }", "test.c", false)); + ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", tok("void f() { if (p && not q); }", "test.c", false)); + ASSERT_EQUALS("void f ( ) { a = ! ( p && q ) ; }", tok("void f() { a = not(p && q); }", "test.c", false)); // Don't simplify 'not' or 'compl' if they are defined as a type; // in variable declaration and in function declaration/definition - ASSERT_EQUALS("struct not { int x ; } ;", tok("struct not { int x; };", "test.c")); - ASSERT_EQUALS("void f ( ) { not p ; compl c ; }", tok(" void f() { not p; compl c; }", "test.c")); - ASSERT_EQUALS("void foo ( not i ) ;", tok("void foo(not i);", "test.c")); - ASSERT_EQUALS("int foo ( not i ) { return g ( i ) ; }", tok("int foo(not i) { return g(i); }", "test.c")); + ASSERT_EQUALS("struct not { int x ; } ;", tok("struct not { int x; };", "test.c", false)); + ASSERT_EQUALS("void f ( ) { not p ; compl c ; }", tok(" void f() { not p; compl c; }", "test.c", false)); + ASSERT_EQUALS("void foo ( not i ) ;", tok("void foo(not i);", "test.c", false)); + ASSERT_EQUALS("int foo ( not i ) { return g ( i ) ; }", tok("int foo(not i) { return g(i); }", "test.c", false)); } void and1() { ASSERT_EQUALS("void f ( ) { if ( p && q ) { ; } }", - tok("void f() { if (p and q) ; }", "test.c")); + tok("void f() { if (p and q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) && q ) { ; } }", - tok("void f() { if (foo() and q) ; }", "test.c")); + tok("void f() { if (foo() and q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) && bar ( ) ) { ; } }", - tok("void f() { if (foo() and bar()) ; }", "test.c")); + tok("void f() { if (foo() and bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p && bar ( ) ) { ; } }", - tok("void f() { if (p and bar()) ; }", "test.c")); + tok("void f() { if (p and bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", - tok("void f() { if (p and not q) ; }", "test.c")); + tok("void f() { if (p and not q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = a && b ; }", - tok("void f() { r = a and b; }", "test.c")); + tok("void f() { r = a and b; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = ( a || b ) && ( c || d ) ; }", - tok("void f() { r = (a || b) and (c || d); }", "test.c")); + tok("void f() { r = (a || b) and (c || d); }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( test1 [ i ] == 'A' && test2 [ i ] == 'C' ) { } }", - tok("void f() { if (test1[i] == 'A' and test2[i] == 'C') {} }", "test.c")); + tok("void f() { if (test1[i] == 'A' and test2[i] == 'C') {} }", "test.c", false)); } void or1() { ASSERT_EQUALS("void f ( ) { if ( p || q ) { ; } }", - tok("void f() { if (p or q) ; }", "test.c")); + tok("void f() { if (p or q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) || q ) { ; } }", - tok("void f() { if (foo() or q) ; }", "test.c")); + tok("void f() { if (foo() or q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) || bar ( ) ) { ; } }", - tok("void f() { if (foo() or bar()) ; }", "test.c")); + tok("void f() { if (foo() or bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p || bar ( ) ) { ; } }", - tok("void f() { if (p or bar()) ; }", "test.c")); + tok("void f() { if (p or bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p || ! q ) { ; } }", - tok("void f() { if (p or not q) ; }", "test.c")); + tok("void f() { if (p or not q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = a || b ; }", - tok("void f() { r = a or b; }", "test.c")); + tok("void f() { r = a or b; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = ( a && b ) || ( c && d ) ; }", - tok("void f() { r = (a && b) or (c && d); }", "test.c")); + tok("void f() { r = (a && b) or (c && d); }", "test.c", false)); } void cAlternativeTokens() { ASSERT_EQUALS("void f ( ) { err |= ( ( r & s ) && ! t ) ; }", - tok("void f() { err or_eq ((r bitand s) and not t); }", "test.c")); + tok("void f() { err or_eq ((r bitand s) and not t); }", "test.c", false)); ASSERT_EQUALS("void f ( ) const { r = f ( a [ 4 ] | 0x0F , ~ c , ! d ) ; }", - tok("void f() const { r = f(a[4] bitor 0x0F, compl c, not d) ; }", "test.c")); + tok("void f() const { r = f(a[4] bitor 0x0F, compl c, not d) ; }", "test.c", false)); } void comma_keyword() { + { + const char code[] = "void foo()\n" + "{\n" + " char *a, *b;\n" + " delete a, delete b;\n" + "}\n"; + ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; delete a ; delete b ; }", tok(code)); + } + { const char code[] = "void foo()\n" "{\n" @@ -659,7 +3142,7 @@ private: " char *a, *b;\n" " delete a, b;\n" "}\n"; - ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; delete a , b ; }", tok(code)); + ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; delete a ; b ; }", tok(code)); } { @@ -669,7 +3152,7 @@ private: " delete a, b, c;\n" "}\n"; // delete a; b; c; would be better but this will do too - ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; char * c ; delete a , b , c ; }", tok(code)); + ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; char * c ; delete a ; b , c ; }", tok(code)); } { @@ -679,7 +3162,18 @@ private: " if (x) \n" " delete a, b;\n" "}\n"; - ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; if ( x ) { delete a , b ; } }", tok(code)); + ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; if ( x ) { delete a ; b ; } }", tok(code)); + } + + { + const char code[] = "void foo()\n" + "{\n" + " char *a, *b, *c;\n" + " if (x) \n" + " delete a, b, c;\n" + "}\n"; + // delete a; b; c; would be better but this will do too + ASSERT_EQUALS("void foo ( ) { char * a ; char * b ; char * c ; if ( x ) { delete a ; b , c ; } }", tok(code)); } { @@ -690,6 +3184,51 @@ private: ASSERT_EQUALS("void foo ( ) { char * * a ; char * * b ; char * * c ; }", tok(code)); } + { + const char code[] = "int f()\n" + "{\n" + " if (something)\n" + " return a(2, c(3, 4)), b(3), 10;\n" + " return a(), b(0, 0, 0), 10;\n" + "}\n"; + ASSERT_EQUALS("int f ( )" + " {" + " if ( something )" + " {" + " a ( 2 , c ( 3 , 4 ) ) ;" + " b ( 3 ) ;" + " return 10 ;" + " }" + " a ( ) ;" + " b ( 0 , 0 , 0 ) ;" + " return 10 ; " + "}", tok(code)); + } + + { + const char code[] = "void foo()\n" + "{\n" + " delete [] a, a = 0;\n" + "}\n"; + ASSERT_EQUALS("void foo ( ) { delete [ ] a ; a = 0 ; }", tok(code)); + } + + { + const char code[] = "void foo()\n" + "{\n" + " delete a, a = 0;\n" + "}\n"; + ASSERT_EQUALS("void foo ( ) { delete a ; a = 0 ; }", tok(code)); + } + + { + const char code[] = "void foo()\n" + "{\n" + " if( x ) delete a, a = 0;\n" + "}\n"; + ASSERT_EQUALS("void foo ( ) { if ( x ) { delete a ; a = 0 ; } }", tok(code)); + } + { const char code[] = "void f()\n" "{\n" @@ -714,6 +3253,196 @@ private: } } + void remove_comma() { + { + const char code[] = "void f()\n" + "{\n" + " int a,b;\n" + " if( a )\n" + " a=0,\n" + " b=0;\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { int a ; int b ; if ( a ) { a = 0 ; b = 0 ; } }", tok(code)); + } + + { + ASSERT_EQUALS("a ? ( b = c , d ) : e ;", tok("a ? b = c , d : e ;")); // Keep comma + } + + { + ASSERT_EQUALS("{ return a ? ( b = c , d ) : e ; }", tok("{ return a ? b = c , d : e ; }")); // Keep comma + } + + { + const char code[] = "void f()\n" + "{\n" + " A a,b;\n" + " if( a.f )\n" + " a.f=b.f,\n" + " a.g=b.g;\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { A a ; A b ; if ( a . f ) { a . f = b . f ; a . g = b . g ; } }", tok(code)); + } + + // keep the comma in template specifiers.. + { + const char code[] = "void f()\n" + "{\n" + " int a = b, int>();\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { int a ; a = b < T < char , 3 > , int > ( ) ; }", tok(code)); + } + + { + const char code[] = "void f() {\n" + " a = new std::map;\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { a = new std :: map < std :: string , std :: string > ; }", tok(code)); + } + + { + // ticket #1327 + const char code[] = "const C<1,2,3> foo ()\n" + "{\n" + " return C<1,2,3>(x,y);\n" + "}\n"; + const char expected[] = "const C < 1 , 2 , 3 > foo ( ) " + "{" + " return C < 1 , 2 , 3 > ( x , y ) ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "int foo ()\n" + "{\n" + " return doSomething(), 0;\n" + "}\n"; + const char expected[] = "int foo ( ) " + "{" + " doSomething ( ) ; return 0 ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "int foo ()\n" + "{\n" + " return a=1, b=2;\n" + "}\n"; + const char expected[] = "int foo ( ) " + "{" + " a = 1 ; return b = 2 ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "tr = (struct reg){ .a = (1), .c = (2) };"; + const char expected[] = "tr = ( struct reg ) { . a = 1 , . c = 2 } ;"; + ASSERT_EQUALS(expected, tok(code)); + } + } + + void simplifyConditionOperator() { + { + const char code[] = "(0?(false?1:2):3);"; + ASSERT_EQUALS("( 3 ) ;", tok(code)); + } + + { + const char code[] = "(1?(false?1:2):3);"; + ASSERT_EQUALS("( 2 ) ;", tok(code)); + } + + { + const char code[] = "int a = (1?0:1 == 1?0:1);"; + ASSERT_EQUALS("int a ; a = 0 ;", tok(code)); + } + + { + const char code[] = "(1?0:foo());"; + ASSERT_EQUALS("( 0 ) ;", tok(code)); + } + + { + const char code[] = "void f () { switch(n) { case 1?0:foo(): break; }}"; + // TODO Do not throw AST validation exception + TODO_ASSERT_THROW(tok(code), InternalError); + //ASSERT_EQUALS("void f ( ) { switch ( n ) { case 0 : ; break ; } }", tok(code)); + } + + { + const char code[] = "void f () { switch(n) { case 1?0?1:0:foo(): break; }}"; + // TODO Do not throw AST validation exception + TODO_ASSERT_THROW(tok(code), InternalError); + } + + { + const char code[] = "void f () { switch(n) { case 0?foo():1: break; }}"; + // TODO Do not throw AST validation exception + TODO_ASSERT_THROW(tok(code), InternalError); + } + + { + const char code[] = "( true ? a ( ) : b ( ) );"; + ASSERT_EQUALS("( a ( ) ) ;", tok(code)); + } + + { + const char code[] = "( true ? abc . a : abc . b );"; + ASSERT_EQUALS("( abc . a ) ;", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " bool x = false;\n" + " int b = x ? 44 : 3;\n" + "}\n"; + ASSERT_EQUALS("void f ( ) { }", tok(code)); + } + + { + const char code[] = "int vals[] = { 0x13, 1?0x01:0x00 };"; + ASSERT_EQUALS("int vals [ 2 ] = { 0x13 , 0x01 } ;", tok(code)); + } + + { + const char code[] = "int vals[] = { 0x13, 0?0x01:0x00 };"; + ASSERT_EQUALS("int vals [ 2 ] = { 0x13 , 0x00 } ;", tok(code)); + } + + { + const char code[] = "a = 1 ? 0 : ({ 0; });"; + ASSERT_EQUALS("a = 0 ;", tok(code)); + } + + //GNU extension: "x ?: y" <-> "x ? x : y" + { + const char code[] = "; a = 1 ? : x; b = 0 ? : 2;"; + ASSERT_EQUALS("; a = 1 ; b = 2 ;", tok(code)); + } + + // Ticket #3572 (segmentation fault) + ASSERT_EQUALS("0 ; x = { ? y : z ; }", tok("0; x = { ? y : z; }")); + + { + // #3922 - (true) + ASSERT_EQUALS("; x = 2 ;", tok("; x = (true)?2:4;")); + ASSERT_EQUALS("; x = 4 ;", tok("; x = (false)?2:4;")); + ASSERT_EQUALS("; x = * a ;", tok("; x = (true)?*a:*b;")); + ASSERT_EQUALS("; x = * b ;", tok("; x = (false)?*a:*b;")); + ASSERT_EQUALS("void f ( ) { return 1 ; }", tok("void f() { char *p=0; return (p==0)?1:2; }")); + } + + { + // TODO Do not throw AST validation exception + TODO_ASSERT_THROW(tok("; type = decay_t() : declval())>;"), InternalError); + TODO_ASSERT_THROW(tok("; type = decay_t() : declval())>;"), InternalError); + } + } + void calculations() { { const char code[] = "a[i+8+2];"; @@ -770,7 +3499,7 @@ private: ASSERT_EQUALS("; a [ 0 ] ;", tok(";a[0*(*p)];")); - ASSERT_EQUALS("; ;", tok("; x = x + 0;")); + ASSERT_EQUALS(";", tok("; x = x + 0;")); ASSERT_EQUALS("{ if ( a == 2 ) { } }", tok("{if (a==1+1){}}")); ASSERT_EQUALS("{ if ( a + 2 != 6 ) { } }", tok("{if (a+1+1!=1+2+3){}}")); @@ -789,12 +3518,361 @@ private: ASSERT_EQUALS("x ( -2 << 6 | 1 ) ;", tok("x(1-3<<6|5/3);")); // #4931 ASSERT_EQUALS("x ( 2 ) ;", tok("x(2|0*0&2>>1+0%2*1);")); // #4931 ASSERT_EQUALS("x ( 0 & 4 != 1 ) ;", tok("x(4%1<<1&4!=1);")); // #4931 (can be simplified further but it's not a problem) - ASSERT_EQUALS("x ( 1 ) ;", tok("x(0&&4>0==2||4);")); // #4931 + ASSERT_EQUALS("x ( true ) ;", tok("x(0&&4>0==2||4);")); // #4931 // don't remove these spaces.. ASSERT_EQUALS("new ( auto ) ( 4 ) ;", tok("new (auto)(4);")); } + void comparisons() { + ASSERT_EQUALS("( 1 ) ;", tok("( 1 < 2 );")); + ASSERT_EQUALS("( x && true ) ;", tok("( x && 1 < 2 );")); + ASSERT_EQUALS("( 5 ) ;", tok("( 1 < 2 && 3 < 4 ? 5 : 6 );")); + ASSERT_EQUALS("( 6 ) ;", tok("( 1 > 2 && 3 > 4 ? 5 : 6 );")); + } + + + void simplifyFlowControl() { + const char code1[] = "void f() {\n" + " return;\n" + " y();\n" + "}"; + ASSERT_EQUALS("void f ( ) { return ; }", tokWithStdLib(code1)); + + const char code2[] = "void f() {\n" + " exit(0);\n" + " y();\n" + "}"; + ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib(code2)); + + const char code3[] = "void f() {\n" + " x.abort();\n" + " y();\n" + "}"; + ASSERT_EQUALS("void f ( ) { x . abort ( ) ; y ( ) ; }", tokWithStdLib(code3)); + } + + void flowControl() { + { + ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); foo(); }")); + ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); if (m) foo(); }")); + ASSERT_EQUALS("void f ( int n ) { if ( n ) { exit ( 0 ) ; } foo ( ) ; }", tokWithStdLib("void f(int n) { if (n) { exit(0); } foo(); }")); + ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); dead(); switch (n) { case 1: deadcode () ; default: deadcode (); } }")); + + ASSERT_EQUALS("int f ( int n ) { switch ( n ) { case 0 : ; exit ( 0 ) ; default : ; exit ( 0 ) ; } exit ( 0 ) ; }", + tokWithStdLib("int f(int n) { switch (n) {case 0: exit(0); n*=2; default: exit(0); n*=6;} exit(0); foo();}")); + //ticket #3132 + ASSERT_EQUALS("void f ( int i ) { goto label ; { label : ; exit ( 0 ) ; } }", tokWithStdLib("void f (int i) { goto label; switch(i) { label: exit(0); } }")); + //ticket #3148 + ASSERT_EQUALS("void f ( ) { MACRO ( exit ( 0 ) ) }", tokWithStdLib("void f() { MACRO(exit(0)) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , exit ( 0 ) ) }", tokWithStdLib("void f() { MACRO(bar1, exit(0)) }")); + } + + { + const char* code = "void f(){ " + " if (k>0) goto label; " + " exit(0); " + " if (tnt) " + " { " + " { " + " check(); " + " k=0; " + " } " + " label: " + " bar(); " + " } " + "}"; + ASSERT_EQUALS("void f ( ) { if ( k > 0 ) { goto label ; } exit ( 0 ) ; { label : ; bar ( ) ; } }", tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " {" + " boo();" + " while (n) { --n; }" + " {" + " label:" + " ok();" + " }" + " }" + "}"; + ASSERT_EQUALS("void foo ( ) { exit ( 0 ) ; { label : ; ok ( ) ; } }", tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case 1:" + " label:" + " foo(); break;" + " default:" + " break;" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case 1:" + " {" + " foo();" + " }" + " label:" + " bar();" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; bar ( ) ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case a:" + " {" + " foo();" + " }" + " case b|c:" + " bar();" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case 1:" + " label:" + " foo(); break;" + " default:" + " break; break;" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case 1:" + " label:" + " foo(); break; break;" + " default:" + " break;" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (n) {" + " case 1:" + " label:" + " foo(); break; break;" + " default:" + " break; break;" + " }" + "}"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "int f() { " + "switch (x) { case 1: exit(0); bar(); tack; { ticak(); exit(0) } exit(0);" + "case 2: exit(0); { random(); } tack(); " + "switch(y) { case 1: exit(0); case 2: exit(0); } " + "exit(0); } exit(0); }"; + ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : ; exit ( 0 ) ; case 2 : ; exit ( 0 ) ; } exit ( 0 ) ; }",tokWithStdLib(code)); + } + + { + const char* code = "int f() {" + "switch (x) { case 1: exit(0); bar(); tack; { ticak(); exit(0); } exit(0);" + "case 2: switch(y) { case 1: exit(0); bar2(); foo(); case 2: exit(0); }" + "exit(0); } exit(0); }"; + const char* expected = "int f ( ) {" + " switch ( x ) { case 1 : ; exit ( 0 ) ;" + " case 2 : ; switch ( y ) { case 1 : ; exit ( 0 ) ; case 2 : ; exit ( 0 ) ; }" + " exit ( 0 ) ; } exit ( 0 ) ; }"; + ASSERT_EQUALS(expected,tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " switch (i) { case 0: switch (j) { case 0: exit(0); }" + " case 1: switch (j) { case -1: exit(0); }" + " case 2: switch (j) { case -2: exit(0); }" + " case 3: if (blah6) {exit(0);} break; } }"; + const char* expected = "void foo ( ) {" + " switch ( i ) { case 0 : ; switch ( j ) { case 0 : ; exit ( 0 ) ; }" + " case 1 : ; switch ( j ) { case -1 : ; exit ( 0 ) ; }" + " case 2 : ; switch ( j ) { case -2 : ; exit ( 0 ) ; }" + " case 3 : ; if ( blah6 ) { exit ( 0 ) ; } break ; } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo () {" + " exit(0);" + " switch (i) { case 0: switch (j) { case 0: foo(); }" + " case 1: switch (j) { case -1: bar(); label:; ok(); }" + " case 3: if (blah6) { boo(); break; } } }"; + const char* expected = "void foo ( ) { exit ( 0 ) ; { { label : ; ok ( ) ; } case 3 : ; if ( blah6 ) { boo ( ) ; break ; } } }"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char* code = "void foo() {" + " switch ( t ) {" + " case 0:" + " if ( t ) switch ( b ) {}" + " break;" + " case 1:" + " exit(0);" + " return 0;" + " }" + " return 0;" + "}"; + const char* expected = "void foo ( ) {" + " switch ( t ) {" + " case 0 : ;" + " if ( t ) { switch ( b ) { } }" + " break ;" + " case 1 : ;" + " exit ( 0 ) ;" + " }" + " return 0 ; " + "}"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char code[] = "void foo()\n" + "{\n" + " A *a = 0;\n" + " if (!a) {\n" + " nondeadcode;\n" + " return;\n" + " dead;\n" + " }\n" + " stilldead;\n" + " a->_a;\n" + "}\n"; + const char expected[] = "void foo ( ) " + "{" + " A * a ; a = 0 ; {" + " nondeadcode ;" + " return ;" + " } " + "}"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char code[] = "class Fred\n" + "{\n" + "public:\n" + " bool foo() const { return f; }\n" + " bool exit();\n" + "\n" + "private:\n" + " bool f;\n" + "};\n"; + const char expected[] = "class Fred " + "{" + " public:" + " bool foo ( ) const { return f ; }" + " bool exit ( ) ;" + "" + " private:" + " bool f ; " + "} ;"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + { + const char code[] = "class abort { };\n" + "\n" + "class Fred\n" + "{\n" + " public:\n" + " bool foo() const { return f; }\n" + " abort exit();\n" + "\n" + " private:\n" + "bool f;\n" + "};\n"; + const char expected[] = "class abort { } ; " + "class Fred " + "{" + " public:" + " bool foo ( ) const { return f ; }" + " abort exit ( ) ;" + "" + " private:" + " bool f ; " + "} ;"; + ASSERT_EQUALS(expected, tokWithStdLib(code)); + } + + ASSERT_EQUALS("void foo ( ) { exit ( 0 ) ; }", + tokWithStdLib("void foo() { do { exit(0); } while (true); }")); + + // #6187 + tokWithStdLib("void foo() {\n" + " goto label;\n" + " for (int i = 0; i < 0; ++i) {\n" + " ;\n" + "label:\n" + " ;\n" + " }\n" + "}"); + } + + void strcat1() { + const char code[] = "; strcat(strcat(strcat(strcat(strcat(strcat(dst, \"this \"), \"\"), \"is \"), \"a \"), \"test\"), \".\");"; + const char expect[] = "; " + "strcat ( dst , \"this \" ) ; " + "strcat ( dst , \"\" ) ; " + "strcat ( dst , \"is \" ) ; " + "strcat ( dst , \"a \" ) ; " + "strcat ( dst , \"test\" ) ; " + "strcat ( dst , \".\" ) ;"; + + ASSERT_EQUALS(expect, tok(code)); + } + void strcat2() { + const char code[] = "; strcat(strcat(dst, foo[0]), \" \");"; + const char expect[] = "; " + "strcat ( dst , foo [ 0 ] ) ; " + "strcat ( dst , \" \" ) ;"; + + ASSERT_EQUALS(expect, tok(code)); + } + + void simplifyAtol() { + ASSERT_EQUALS("a = std :: atol ( x ) ;", tok("a = std::atol(x);")); + ASSERT_EQUALS("a = atol ( \"text\" ) ;", tok("a = atol(\"text\");")); + ASSERT_EQUALS("a = 0 ;", tok("a = std::atol(\"0\");")); + ASSERT_EQUALS("a = 10 ;", tok("a = atol(\"0xa\");")); + } + void simplifyOperator1() { // #3237 - error merging namespaces with operators const char code[] = "class c {\n" @@ -837,6 +3915,297 @@ private: "1: int a@1 ; a@1 [ 13 ] ;\n", tokenizeDebugListing("int a; 13[a];")); } + void simplify_numeric_condition() { + { + const char code[] = + "void f()\n" + "{\n" + "int x = 0;\n" + "if( !x || 0 )\n" + "{ g();\n" + "}\n" + "}"; + + ASSERT_EQUALS("void f ( ) { g ( ) ; }", tok(code)); + } + + { + const char code[] = + "void f()\n" + "{\n" + "int x = 1;\n" + "if( !x )\n" + "{ g();\n" + "}\n" + "}"; + + ASSERT_EQUALS("void f ( ) { }", tok(code)); + } + + { + const char code[] = + "void f()\n" + "{\n" + "bool x = true;\n" + "if( !x )\n" + "{ g();\n" + "}\n" + "}"; + + ASSERT_EQUALS("void f ( ) { }", tok(code)); + } + + { + const char code[] = + "void f()\n" + "{\n" + "bool x = false;\n" + "if( !x )\n" + "{ g();\n" + "}\n" + "}"; + + ASSERT_EQUALS("void f ( ) { g ( ) ; }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (5==5);\n" + "}\n"; + + ASSERT_EQUALS("void f ( ) { ; }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (4<5);\n" + "}\n"; + + ASSERT_EQUALS("void f ( ) { ; }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (5<5);\n" + "}\n"; + + ASSERT_EQUALS("void f ( ) { }", tok(code)); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (13>12?true:false);\n" + "}\n"; + + ASSERT_EQUALS("void f ( ) { ; }", tok(code)); + } + + { + // #7849 + const char code[] = + "void f() {\n" + "if (-1e-2 == -0.01) \n" + " g();\n" + "else\n" + " h();\n" + "}"; + ASSERT_EQUALS("void f ( ) { if ( -1e-2 == -0.01 ) { g ( ) ; } else { h ( ) ; } }", + tok(code)); + } + } + + void simplify_condition() { + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (a && false) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (false && a) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (true || a) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { g ( ) ; }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (a || true) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { g ( ) ; }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (a || true || b) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { g ( ) ; }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (a && false && b) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if (a || (b && false && c) || d) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { if ( a || d ) { g ( ) ; } }", tok(code)); + } + + { + const char code[] = + "void f(int a)\n" + "{\n" + "if ((a && b) || true || (c && d)) g();\n" + "}"; + ASSERT_EQUALS("void f ( int a ) { g ( ) ; }", tok(code)); + } + + { + // #4931 + const char code[] = + "void f() {\n" + "if (12 && 7) g();\n" + "}"; + ASSERT_EQUALS("void f ( ) { g ( ) ; }", tok(code)); + } + } + + + void pointeralias1() { + { + const char code[] = "void f(char *p1)\n" + "{\n" + " char *p = p1;\n" + " p1 = 0;" + " x(p);\n" + "}\n"; + + const char expected[] = "void f ( char * p1 ) " + "{ " + "char * p ; p = p1 ; " + "p1 = 0 ; " + "x ( p ) ; " + "}"; + + ASSERT_EQUALS(expected, tok(code)); + } + + { + const char code[] = "void foo(Result* ptr)\n" + "{\n" + " Result* obj = ptr;\n" + " ++obj->total;\n" + "}\n"; + + const char expected[] = "void foo ( Result * ptr ) " + "{ " + "Result * obj ; obj = ptr ; " + "++ obj . total ; " + "}"; + + ASSERT_EQUALS(expected, tok(code)); + } + } + + 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 ; return i ; }", tok(code)); + } + + void pointeralias3() { + const char code[] = "void f()\n" + "{\n" + " int i, j, *p;\n" + " if (ab) p = &i;\n" + " else p = &j;\n" + " *p = 0;\n" + "}\n"; + const char expected[] = "void f ( ) " + "{" + " int i ; int j ; int * p ;" + " if ( ab ) { p = & i ; }" + " else { p = & j ; }" + " * p = 0 ; " + "}"; + 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 ( ) " + "{" + " return 5 ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + + void while0() { + ASSERT_EQUALS("void foo ( ) { x = 1 ; }", tok("void foo() { do { x = 1 ; } while (0);}")); + ASSERT_EQUALS("void foo ( ) { return 0 ; }", tok("void foo() { do { return 0; } while (0);}")); + ASSERT_EQUALS("void foo ( ) { goto label ; }", tok("void foo() { do { goto label; } while (0); }")); + ASSERT_EQUALS("void foo ( ) { continue ; }", tok("void foo() { do { continue ; } while (0); }")); + ASSERT_EQUALS("void foo ( ) { break ; }", tok("void foo() { do { break; } while (0); }")); + ASSERT_EQUALS("void foo ( ) { }", tok("void foo() { while (false) { a; } }")); + ASSERT_EQUALS("void foo ( ) { }", tok("void foo() { while (false) { switch (n) { case 0: return; default: break; } n*=1; } }")); + } + + void while0for() { + // for (condition is always false) + ASSERT_EQUALS("void f ( ) { int i ; for ( i = 0 ; i < 0 ; i ++ ) { } }", tok("void f() { int i; for (i = 0; i < 0; i++) { a; } }")); + //ticket #3140 + ASSERT_EQUALS("void f ( ) { int i ; for ( i = 0 ; i < 0 ; i ++ ) { } }", tok("void f() { int i; for (i = 0; i < 0; i++) { foo(); break; } }")); + ASSERT_EQUALS("void f ( ) { int i ; for ( i = 0 ; i < 0 ; i ++ ) { } }", tok("void f() { int i; for (i = 0; i < 0; i++) { foo(); continue; } }")); + ASSERT_EQUALS("void f ( ) { }", tok("void f() { for (int i = 0; i < 0; i++) { a; } }")); + ASSERT_EQUALS("void f ( ) { }", tok("void f() { for (unsigned int i = 0; i < 0; i++) { a; } }")); + ASSERT_EQUALS("void f ( ) { }", tok("void f() { for (long long i = 0; i < 0; i++) { a; } }")); + ASSERT_EQUALS("void f ( ) { }", tok("void f() { for (signed long long i = 0; i < 0; i++) { a; } }")); + ASSERT_EQUALS("void f ( ) { }", tok("void f() { int n = 0; for (signed long long i = 0; i < n; i++) { a; } }")); + // #8059 + ASSERT_EQUALS("void f ( ) { int i ; for ( i = 0 ; i < 0 ; ++ i ) { } return i ; }", tok("void f() { int i; for (i=0;i<0;++i){ dostuff(); } return i; }")); + } + void duplicateDefinition() { // #3565 - wrongly detects duplicate definition Tokenizer tokenizer(&settings0, this); std::istringstream istr("{ x ; return a not_eq x; }"); @@ -845,24 +4214,96 @@ private: ASSERT_EQUALS(false, tokenizer.duplicateDefinition(&x_token)); } + void removestd() { + ASSERT_EQUALS("; strcpy ( a , b ) ;", tok("; std::strcpy(a,b);")); + ASSERT_EQUALS("; strcat ( a , b ) ;", tok("; std::strcat(a,b);")); + ASSERT_EQUALS("; strncpy ( a , b , 10 ) ;", tok("; std::strncpy(a,b,10);")); + ASSERT_EQUALS("; strncat ( a , b , 10 ) ;", tok("; std::strncat(a,b,10);")); + ASSERT_EQUALS("; free ( p ) ;", tok("; std::free(p);")); + ASSERT_EQUALS("; malloc ( 10 ) ;", tok("; std::malloc(10);")); + } + void simplifyInitVar() { // ticket #1005 - int *p(0); => int *p = 0; { const char code[] = "void foo() { int *p(0); }"; - ASSERT_EQUALS("void foo ( ) { int * p ; p = 0 ; }", tok(code)); + ASSERT_EQUALS("void foo ( ) { }", tok(code)); } { const char code[] = "void foo() { int p(0); }"; - ASSERT_EQUALS("void foo ( ) { int p ; p = 0 ; }", tok(code)); + ASSERT_EQUALS("void foo ( ) { }", tok(code)); } { const char code[] = "void a() { foo *p(0); }"; - ASSERT_EQUALS("void a ( ) { foo * p ; p = 0 ; }", tok(code)); + ASSERT_EQUALS("void a ( ) { }", tok(code)); } } + void simplifyReference() { + ASSERT_EQUALS("void f ( ) { int a ; a ++ ; }", + tok("void f() { int a; int &b(a); b++; }")); + ASSERT_EQUALS("void f ( ) { int a ; a ++ ; }", + tok("void f() { int a; int &b = a; b++; }")); + + ASSERT_EQUALS("void test ( ) { c . f ( 7 ) ; }", + tok("void test() { c.f(7); T3 &t3 = c; }")); // #6133 + } + + void simplifyRealloc() { + ASSERT_EQUALS("; free ( p ) ; p = 0 ;", tok("; p = realloc(p, 0);")); + ASSERT_EQUALS("; p = malloc ( 100 ) ;", tok("; p = realloc(0, 100);")); + ASSERT_EQUALS("; p = malloc ( 0 ) ;", tok("; p = realloc(0, 0);")); + ASSERT_EQUALS("; free ( q ) ; p = 0 ;", tok("; p = realloc(q, 0);")); + ASSERT_EQUALS("; free ( * q ) ; p = 0 ;", tok("; p = realloc(*q, 0);")); + ASSERT_EQUALS("; free ( f ( z ) ) ; p = 0 ;", tok("; p = realloc(f(z), 0);")); + ASSERT_EQUALS("; p = malloc ( n * m ) ;", tok("; p = realloc(0, n*m);")); + ASSERT_EQUALS("; p = malloc ( f ( 1 ) ) ;", tok("; p = realloc(0, f(1));")); + } + + void simplifyErrNoInWhile() { + ASSERT_EQUALS("{ while ( f ( ) ) { } }", + tok("{ while (f() && errno == EINTR) { } }")); + ASSERT_EQUALS("{ while ( f ( ) ) { } }", + tok("{ while (f() && (errno == EINTR)) { } }")); + } + + void simplifyFuncInWhile() { + ASSERT_EQUALS("{ " + "int cppcheck:r1 = fclose ( f ) ; " + "while ( cppcheck:r1 ) " + "{ " + "foo ( ) ; " + "cppcheck:r1 = fclose ( f ) ; " + "} " + "}", + tok("{while(fclose(f))foo();}")); + + ASSERT_EQUALS("{ " + "int cppcheck:r1 = fclose ( f ) ; " + "while ( cppcheck:r1 ) " + "{ " + "; cppcheck:r1 = fclose ( f ) ; " + "} " + "}", + tok("{while(fclose(f));}")); + + ASSERT_EQUALS("{ " + "int cppcheck:r1 = fclose ( f ) ; " + "while ( cppcheck:r1 ) " + "{ " + "; cppcheck:r1 = fclose ( f ) ; " + "} " + "int cppcheck:r2 = fclose ( g ) ; " + "while ( cppcheck:r2 ) " + "{ " + "; cppcheck:r2 = fclose ( g ) ; " + "} " + "}", + tok("{while(fclose(f)); while(fclose(g));}")); + } + void simplifyStructDecl1() { { const char code[] = "struct ABC { } abc;"; @@ -1269,7 +4710,8 @@ private: } void redundant_semicolon() { - ASSERT_EQUALS("void f ( ) { ; }", tok("void f() { ; }")); + ASSERT_EQUALS("void f ( ) { ; }", tok("void f() { ; }", false)); + ASSERT_EQUALS("void f ( ) { ; }", tok("void f() { do { ; } while (0); }", true)); } void simplifyFunctionReturn() { @@ -1334,6 +4776,88 @@ private: ASSERT_EQUALS("void foo ( ) ;", tok("void foo(void);")); } + void return_strncat() { + { + const char code[] = "char *f()\n" + "{\n" + " char *temp=malloc(2);\n" + " strcpy(temp,\"\");\n" + " return (strncat(temp,\"a\",1));\n" + "}"; + ASSERT_EQUALS("char * f ( ) {" + " char * temp ;" + " temp = malloc ( 2 ) ;" + " strcpy ( temp , \"\" ) ;" + " strncat ( temp , \"a\" , 1 ) ;" + " return temp ; " + "}", tok(code, true)); + } + { + const char code[] = "char *f()\n" + "{\n" + " char **temp=malloc(8);\n" + " *temp = malloc(2);\n" + " strcpy(*temp,\"\");\n" + " return (strncat(*temp,\"a\",1));\n" + "}"; + ASSERT_EQUALS("char * f ( ) {" + " char * * temp ;" + " temp = malloc ( 8 ) ;" + " * temp = malloc ( 2 ) ;" + " strcpy ( * temp , \"\" ) ;" + " strncat ( * temp , \"a\" , 1 ) ;" + " return * temp ; " + "}", tok(code, true)); + } + { + const char code[] = "char *f()\n" + "{\n" + " char **temp=malloc(8);\n" + " *temp = malloc(2);\n" + " strcpy(*temp,\"\");\n" + " return (strncat(temp[0],foo(b),calc(c-d)));\n" + "}"; + ASSERT_EQUALS("char * f ( ) {" + " char * * temp ;" + " temp = malloc ( 8 ) ;" + " * temp = malloc ( 2 ) ;" + " strcpy ( * temp , \"\" ) ;" + " strncat ( temp [ 0 ] , foo ( b ) , calc ( c - d ) ) ;" + " return temp [ 0 ] ; " + "}", tok(code, true)); + } + } + + void removeRedundantFor() { // ticket #3069 + { + const char code[] = "void f() {" + " for(x=0;x<1;x++) {" + " y = 1;" + " }" + "}"; + ASSERT_EQUALS("void f ( ) { { y = 1 ; } x = 1 ; }", tok(code, true)); + } + + { + const char code[] = "void f() {" + " for(x=0;x<1;x++) {" + " y = 1 + x;" + " }" + "}"; + ASSERT_EQUALS("void f ( ) { x = 0 ; { y = 1 + x ; } x = 1 ; }", tok(code, true)); + } + + { + const char code[] = "void f() {" + " foo();" + " for(int x=0;x<1;x++) {" + " y = 1 + x;" + " }" + "}"; + ASSERT_EQUALS("void f ( ) { foo ( ) ; { int x = 0 ; y = 1 + x ; } }", tok(code, true)); + } + } + void consecutiveBraces() { ASSERT_EQUALS("void f ( ) { }", tok("void f(){{}}", true)); ASSERT_EQUALS("void f ( ) { }", tok("void f(){{{}}}", true)); @@ -1341,12 +4865,58 @@ private: ASSERT_EQUALS("void f ( ) { { scope_lock lock ; foo ( ) ; } { scope_lock lock ; bar ( ) ; } }", tok("void f () { {scope_lock lock; foo();} {scope_lock lock; bar();} }", true)); } + void undefinedSizeArray() { + ASSERT_EQUALS("int * x ;", tok("int x [];")); + ASSERT_EQUALS("int * * x ;", tok("int x [][];")); + ASSERT_EQUALS("int * * x ;", tok("int * x [];")); + ASSERT_EQUALS("int * * * x ;", tok("int * x [][];")); + ASSERT_EQUALS("int * * * * x ;", tok("int * * x [][];")); + ASSERT_EQUALS("void f ( int x [ ] , double y [ ] ) { }", tok("void f(int x[], double y[]) { }")); + ASSERT_EQUALS("int x [ 13 ] = { [ 11 ] = 2 , [ 12 ] = 3 } ;", tok("int x[] = {[11]=2, [12]=3};")); + } + + void simplifyArrayAddress() { // ticket #3304 + const char code[] = "void foo() {\n" + " int a[10];\n" + " memset(&a[4], 0, 20*sizeof(int));\n" + "}"; + ASSERT_EQUALS("void foo ( ) {" + " int a [ 10 ] ;" + " memset ( a + 4 , 0 , 80 ) ;" + " }", tok(code, true)); + } + + void simplifyCharAt() { // ticket #4481 + ASSERT_EQUALS("'h' ;", tok("\"hello\"[0] ;")); + ASSERT_EQUALS("'\\n' ;", tok("\"\\n\"[0] ;")); + ASSERT_EQUALS("'\\0' ;", tok("\"hello\"[5] ;")); + ASSERT_EQUALS("'\\0' ;", tok("\"\"[0] ;")); + ASSERT_EQUALS("'\\0' ;", tok("\"\\0\"[0] ;")); + ASSERT_EQUALS("'\\n' ;", tok("\"hello\\nworld\"[5] ;")); + ASSERT_EQUALS("'w' ;", tok("\"hello world\"[6] ;")); + ASSERT_EQUALS("\"hello\" [ 7 ] ;", tok("\"hello\"[7] ;")); + ASSERT_EQUALS("\"hello\" [ -1 ] ;", tok("\"hello\"[-1] ;")); + } + + void test_4881() { + const char code[] = "int evallex() {\n" + " int c, t;\n" + "again:\n" + " do {\n" + " if ((c = macroid(c)) == EOF_CHAR || c == '\\n') {\n" + " }\n" + " } while ((t = type[c]) == LET && catenate());\n" + "}\n"; + ASSERT_EQUALS("int evallex ( ) { int c ; int t ; again : ; do { c = macroid ( c ) ; if ( c == EOF_CHAR || c == '\\n' ) { } t = type [ c ] ; } while ( t == LET && catenate ( ) ) ; }", + tok(code, true)); + } + void simplifyOverride() { // ticket #5069 const char code[] = "void fun() {\n" " unsigned char override[] = {0x01, 0x02};\n" " doSomething(override, sizeof(override));\n" "}\n"; - ASSERT_EQUALS("void fun ( ) { char override [ 2 ] = { 0x01 , 0x02 } ; doSomething ( override , sizeof ( override ) ) ; }", + ASSERT_EQUALS("void fun ( ) { char override [ 2 ] = { 0x01 , 0x02 } ; doSomething ( override , 2 ) ; }", tok(code, true)); } diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 16f5b1199..2e4984f56 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2491,7 +2491,7 @@ private: "Dummy y;"; const char exp [] = "Dummy < int [ 1 ] > y ;"; ASSERT_EQUALS(exp, tok(code, false)); - ASSERT_EQUALS("[test.cpp:2]: (debug) Unknown type 'Dummy'.\n", errout.str()); + ASSERT_EQUALS("", errout.str()); } void simplifyTypedef124() { // ticket #7792 diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 1999a89fb..30cef37ec 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -51,6 +51,7 @@ private: TEST_CASE(tokenize2); TEST_CASE(tokenize4); TEST_CASE(tokenize5); + TEST_CASE(tokenize6); // array access. replace "*(p+1)" => "p[1]" TEST_CASE(tokenize7); TEST_CASE(tokenize8); TEST_CASE(tokenize9); @@ -93,6 +94,23 @@ private: TEST_CASE(removeUnusedTemplates); + TEST_CASE(simplifyCasts1); + TEST_CASE(simplifyCasts2); + TEST_CASE(simplifyCasts3); + TEST_CASE(simplifyCasts4); + TEST_CASE(simplifyCasts5); + TEST_CASE(simplifyCasts7); + TEST_CASE(simplifyCasts8); + TEST_CASE(simplifyCasts9); + TEST_CASE(simplifyCasts10); + TEST_CASE(simplifyCasts11); + TEST_CASE(simplifyCasts12); + TEST_CASE(simplifyCasts13); + TEST_CASE(simplifyCasts14); + TEST_CASE(simplifyCasts15); // #5996 - don't remove cast in 'a+static_cast(b?60:0)' + TEST_CASE(simplifyCasts16); // #6278 + TEST_CASE(simplifyCasts17); // #6110 - don't remove any parentheses in 'a(b)(c)' + TEST_CASE(simplifyAt); TEST_CASE(inlineasm); @@ -122,6 +140,80 @@ private: TEST_CASE(forAddBraces1); TEST_CASE(forAddBraces2); // #5088 + 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); + 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(simplifyKnownVariables35); // ticket #2353 - False positive: Division by zero 'if (x == 0) return 0; return 10 / x;' + TEST_CASE(simplifyKnownVariables36); // ticket #2304 - known value for strcpy parameter + TEST_CASE(simplifyKnownVariables37); // ticket #2398 - false positive caused by no simplification in for loop + TEST_CASE(simplifyKnownVariables38); // ticket #2399 - simplify conditions + TEST_CASE(simplifyKnownVariables39); + TEST_CASE(simplifyKnownVariables40); + 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(simplifyKnownVariables52); // #4728 "= x %cop%" + 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(simplifyKnownVariablesBailOutAssign1); + TEST_CASE(simplifyKnownVariablesBailOutAssign2); + TEST_CASE(simplifyKnownVariablesBailOutAssign3); // #4395 - nested assignments + TEST_CASE(simplifyKnownVariablesBailOutFor1); + TEST_CASE(simplifyKnownVariablesBailOutFor2); + TEST_CASE(simplifyKnownVariablesBailOutFor3); + TEST_CASE(simplifyKnownVariablesBailOutMemberFunction); + TEST_CASE(simplifyKnownVariablesBailOutConditionalIncrement); + TEST_CASE(simplifyKnownVariablesBailOutSwitchBreak); // ticket #2324 + TEST_CASE(simplifyKnownVariablesFloat); // #2454 - float variable + 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(simplifyKnownVariablesReturn); // 3500 - return + TEST_CASE(simplifyKnownVariablesPointerAliasFunctionCall); // #7440 TEST_CASE(simplifyExternC); TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between [] @@ -163,6 +255,12 @@ private: TEST_CASE(tokenize_double); TEST_CASE(tokenize_strings); + TEST_CASE(simplify_constants); + TEST_CASE(simplify_constants2); + TEST_CASE(simplify_constants3); + TEST_CASE(simplify_constants4); + TEST_CASE(simplify_constants5); + TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter TEST_CASE(simplifyMulAndParens); // Ticket #2784 + #3184 TEST_CASE(simplifyStructDecl); @@ -232,6 +330,8 @@ private: TEST_CASE(functionpointer8); // #7410 - throw TEST_CASE(functionpointer9); // #6113 - function call with function pointer + TEST_CASE(removeRedundantAssignment); + TEST_CASE(removedeclspec); TEST_CASE(removeattribute); TEST_CASE(functionAttributeBefore); @@ -282,6 +382,8 @@ private: TEST_CASE(simplifyCAlternativeTokens); + TEST_CASE(simplifyCalculations); + // x = ({ 123; }); => { x = 123; } TEST_CASE(simplifyRoundCurlyParentheses); @@ -323,6 +425,7 @@ private: // a = b = 0; TEST_CASE(multipleAssignment); + TEST_CASE(sizeOfCharLiteral); TEST_CASE(platformWin); TEST_CASE(platformWin32); TEST_CASE(platformWin32A); @@ -393,7 +496,7 @@ private: TEST_CASE(cppcast); } - std::string tokenizeAndStringify(const char code[], bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { + std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { errout.str(""); settings1.debugwarnings = true; @@ -404,6 +507,8 @@ private: Tokenizer tokenizer(&settings1, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); + if (simplify) + tokenizer.simplifyTokenList2(); // filter out ValueFlow messages.. const std::string debugwarnings = errout.str(); @@ -421,7 +526,7 @@ private: return ""; } - std::string tokenizeAndStringifyWindows(const char code[], bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { + std::string tokenizeAndStringifyWindows(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { errout.str(""); settings_windows.debugwarnings = true; @@ -432,6 +537,8 @@ private: Tokenizer tokenizer(&settings_windows, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); + if (simplify) + tokenizer.simplifyTokenList2(); // filter out ValueFlow messages.. const std::string debugwarnings = errout.str(); @@ -461,7 +568,7 @@ private: return tokenizer.tokens()->stringifyList(false, true, false, true, false, nullptr, nullptr); } - std::string tokenizeDebugListing(const char code[], const char filename[] = "test.cpp") { + std::string tokenizeDebugListing(const char code[], bool simplify = false, const char filename[] = "test.cpp") { errout.str(""); settings2.standards.c = Standards::C89; @@ -471,6 +578,9 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, filename); + if (simplify) + tokenizer.simplifyTokenList2(); + // result.. return tokenizer.tokens()->stringifyList(true,true,true,true,false); } @@ -506,13 +616,56 @@ private: ASSERT_EQUALS("; 1E-2 ;", tokenizeAndStringify("; 1E-2 ;")); } + void tokenize6() { + // "&p[1]" => "p+1" + /* + ASSERT_EQUALS("; x = p + n ;", tokenizeAndStringify("; x = & p [ n ] ;", true)); + ASSERT_EQUALS("; x = ( p + n ) [ m ] ;", tokenizeAndStringify("; x = & p [ n ] [ m ] ;", true)); + ASSERT_EQUALS("; x = y & p [ n ] ;", tokenizeAndStringify("; x = y & p [ n ] ;", true)); + ASSERT_EQUALS("; x = 10 & p [ n ] ;", tokenizeAndStringify("; x = 10 & p [ n ] ;", true)); + ASSERT_EQUALS("; x = y [ 10 ] & p [ n ] ;", tokenizeAndStringify("; x = y [ 10 ] & p [ n ] ;", true)); + ASSERT_EQUALS("; x = ( a + m ) & p [ n ] ;", tokenizeAndStringify("; x = ( a + m ) & p [ n ] ;", true));*/ + // "*(p+1)" => "p[1]" + ASSERT_EQUALS("; x = p [ 1 ] ;", tokenizeAndStringify("; x = * ( p + 1 ) ;", true)); + ASSERT_EQUALS("; x = p [ 0xA ] ;", tokenizeAndStringify("; x = * ( p + 0xA ) ;", true)); + ASSERT_EQUALS("; x = p [ n ] ;", tokenizeAndStringify("; x = * ( p + n ) ;", true)); + ASSERT_EQUALS("; x = y * ( p + n ) ;", tokenizeAndStringify("; x = y * ( p + n ) ;", true)); + ASSERT_EQUALS("; x = 10 * ( p + n ) ;", tokenizeAndStringify("; x = 10 * ( p + n ) ;", true)); + ASSERT_EQUALS("; x = y [ 10 ] * ( p + n ) ;", tokenizeAndStringify("; x = y [ 10 ] * ( p + n ) ;", true)); + ASSERT_EQUALS("; x = ( a + m ) * ( p + n ) ;", tokenizeAndStringify("; x = ( a + m ) * ( p + n ) ;", true)); + + // "*(p-1)" => "p[-1]" and "*(p-n)" => "p[-n]" + ASSERT_EQUALS("; x = p [ -1 ] ;", tokenizeAndStringify("; x = *(p - 1);", true)); + ASSERT_EQUALS("; x = p [ -0xA ] ;", tokenizeAndStringify("; x = *(p - 0xA);", true)); + ASSERT_EQUALS("; x = p [ - n ] ;", tokenizeAndStringify("; x = *(p - n);", true)); + ASSERT_EQUALS("; x = y * ( p - 1 ) ;", tokenizeAndStringify("; x = y * (p - 1);", true)); + ASSERT_EQUALS("; x = 10 * ( p - 1 ) ;", tokenizeAndStringify("; x = 10 * (p - 1);", true)); + ASSERT_EQUALS("; x = y [ 10 ] * ( p - 1 ) ;", tokenizeAndStringify("; x = y[10] * (p - 1);", true)); + ASSERT_EQUALS("; x = ( a - m ) * ( p - n ) ;", tokenizeAndStringify("; x = (a - m) * (p - n);", true)); + + // Test that the array-index simplification is not applied when there's no dereference: + // "(x-y)" => "(x-y)" and "(x+y)" => "(x+y)" + ASSERT_EQUALS("; a = b * ( x - y ) ;", tokenizeAndStringify("; a = b * (x - y);", true)); + ASSERT_EQUALS("; a = b * x [ - y ] ;", tokenizeAndStringify("; a = b * *(x - y);", true)); + ASSERT_EQUALS("; a = a * ( x - y ) ;", tokenizeAndStringify("; a *= (x - y);", true)); + ASSERT_EQUALS("; z = a ++ * ( x - y ) ;", tokenizeAndStringify("; z = a++ * (x - y);", true)); + ASSERT_EQUALS("; z = a ++ * ( x + y ) ;", tokenizeAndStringify("; z = a++ * (x + y);", true)); + ASSERT_EQUALS("; z = a -- * ( x - y ) ;", tokenizeAndStringify("; z = a-- * (x - y);", true)); + ASSERT_EQUALS("; z = a -- * ( x + y ) ;", tokenizeAndStringify("; z = a-- * (x + y);", true)); + ASSERT_EQUALS("; z = 'a' * ( x - y ) ;", tokenizeAndStringify("; z = 'a' * (x - y);", true)); + ASSERT_EQUALS("; z = \"a\" * ( x - y ) ;", tokenizeAndStringify("; z = \"a\" * (x - y);", true)); + ASSERT_EQUALS("; z = 'a' * ( x + y ) ;", tokenizeAndStringify("; z = 'a' * (x + y);", true)); + ASSERT_EQUALS("; z = \"a\" * ( x + y ) ;", tokenizeAndStringify("; z = \"a\" * (x + y);", true)); + ASSERT_EQUALS("; z = foo ( ) * ( x + y ) ;", tokenizeAndStringify("; z = foo() * (x + y);", true)); + } + void tokenize7() { const char code[] = "void f() {\n" " int x1 = 1;\n" " int x2(x1);\n" "}\n"; ASSERT_EQUALS("void f ( ) {\nint x1 ; x1 = 1 ;\nint x2 ; x2 = x1 ;\n}", - tokenizeAndStringify(code)); + tokenizeAndStringify(code, false)); } void tokenize8() { @@ -524,7 +677,7 @@ private: "2: int x1@1 ; x1@1 = g ( ) ;\n" "3: int x2@2 ; x2@2 = x1@1 ;\n" "4: }\n", - tokenizeDebugListing(code)); + tokenizeDebugListing(code, false)); } void tokenize9() { @@ -533,12 +686,12 @@ private: "void f() {\n" " fpp x = (fpp)f();\n" "}"; - tokenizeAndStringify(code); + tokenizeAndStringify(code, false); ASSERT_EQUALS("", errout.str()); } void tokenize11() { - ASSERT_EQUALS("X * sizeof ( Y ( ) ) ;", tokenizeAndStringify("X * sizeof(Y());")); + ASSERT_EQUALS("X * sizeof ( Y ( ) ) ;", tokenizeAndStringify("X * sizeof(Y());", false)); } // bailout if there is "@" - it is not handled well @@ -673,7 +826,7 @@ private: "void z() {\n" " vector VI;\n" "}\n"; - tokenizeAndStringify(code); + tokenizeAndStringify(code, true); } void tokenize34() { // #8031 @@ -745,11 +898,11 @@ private: void validate() { // C++ code in C file - ASSERT_THROW(tokenizeAndStringify(";using namespace std;",false,Settings::Native,"test.c"), InternalError); - ASSERT_THROW(tokenizeAndStringify(";std::map m;",false,Settings::Native,"test.c"), InternalError); - ASSERT_THROW(tokenizeAndStringify(";template class X { };",false,Settings::Native,"test.c"), InternalError); - ASSERT_THROW(tokenizeAndStringify("int X() {};",false,Settings::Native,"test.c"), InternalError); - ASSERT_THROW(tokenizeAndStringify("void foo(int i) { reinterpret_cast(i) };",false,Settings::Native,"test.h"), InternalError); + ASSERT_THROW(tokenizeAndStringify(";using namespace std;",false,false,Settings::Native,"test.c"), InternalError); + ASSERT_THROW(tokenizeAndStringify(";std::map m;",false,false,Settings::Native,"test.c"), InternalError); + ASSERT_THROW(tokenizeAndStringify(";template class X { };",false,false,Settings::Native,"test.c"), InternalError); + ASSERT_THROW(tokenizeAndStringify("int X() {};",false,false,Settings::Native,"test.c"), InternalError); + ASSERT_THROW(tokenizeAndStringify("void foo(int i) { reinterpret_cast(i) };",false,false,Settings::Native,"test.h"), InternalError); } void objectiveC() { @@ -808,13 +961,13 @@ private: } void combineOperators() { - ASSERT_EQUALS("; private: ;", tokenizeAndStringify(";private:;")); - ASSERT_EQUALS("; protected: ;", tokenizeAndStringify(";protected:;")); - ASSERT_EQUALS("; public: ;", tokenizeAndStringify(";public:;")); - ASSERT_EQUALS("; __published: ;", tokenizeAndStringify(";__published:;")); - ASSERT_EQUALS("a . public : ;", tokenizeAndStringify("a.public:;")); - ASSERT_EQUALS("void f ( x & = 2 ) ;", tokenizeAndStringify("void f(x &= 2);")); - ASSERT_EQUALS("const_cast < a * > ( & e )", tokenizeAndStringify("const_cast(&e)")); + ASSERT_EQUALS("; private: ;", tokenizeAndStringify(";private:;", false)); + ASSERT_EQUALS("; protected: ;", tokenizeAndStringify(";protected:;", false)); + ASSERT_EQUALS("; public: ;", tokenizeAndStringify(";public:;", false)); + ASSERT_EQUALS("; __published: ;", tokenizeAndStringify(";__published:;", false)); + ASSERT_EQUALS("a . public : ;", tokenizeAndStringify("a.public:;", false)); + ASSERT_EQUALS("void f ( x & = 2 ) ;", tokenizeAndStringify("void f(x &= 2);", false)); + ASSERT_EQUALS("const_cast < a * > ( & e )", tokenizeAndStringify("const_cast(&e)", false)); } void concatenateNegativeNumber() { @@ -831,7 +984,7 @@ private: void longtok() { const std::string filedata(10000, 'a'); - ASSERT_EQUALS(filedata, tokenizeAndStringify(filedata.c_str())); + ASSERT_EQUALS(filedata, tokenizeAndStringify(filedata.c_str(), true)); } @@ -851,6 +1004,105 @@ private: "}", s)); } + + // Don’t remove "(int *)".. + void simplifyCasts1() { + const char code[] = "int *f(int *);"; + ASSERT_EQUALS("int * f ( int * ) ;", tokenizeAndStringify(code, true)); + } + + // remove static_cast.. + void simplifyCasts2() { + const char code[] = "t = (static_cast *>(&p));\n"; + ASSERT_EQUALS("t = & p ;", tokenizeAndStringify(code, true)); + } + + void simplifyCasts3() { + // ticket #961 + const char code[] = "assert (iplen >= (unsigned) ipv4->ip_hl * 4 + 20);"; + const char expected[] = "assert ( iplen >= ipv4 . ip_hl * 4 + 20 ) ;"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyCasts4() { + // ticket #970 + const char code[] = "{if (a >= (unsigned)(b)) {}}"; + const char expected[] = "{ if ( a >= ( unsigned int ) ( b ) ) { } }"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyCasts5() { + // ticket #1817 + ASSERT_EQUALS("a . data = f ;", tokenizeAndStringify("a->data = reinterpret_cast(static_cast(f));", true)); + } + + void simplifyCasts7() { + ASSERT_EQUALS("str = malloc ( 3 )", tokenizeAndStringify("str=(char **)malloc(3)", true)); + } + + void simplifyCasts8() { + ASSERT_EQUALS("ptr1 = ptr2", tokenizeAndStringify("ptr1=(int * **)ptr2", true)); + } + + void simplifyCasts9() { + ASSERT_EQUALS("f ( ( double ) ( v1 ) * v2 )", tokenizeAndStringify("f((double)(v1)*v2)", true)); + ASSERT_EQUALS("int v1 ; f ( ( double ) ( v1 ) * v2 )", tokenizeAndStringify("int v1; f((double)(v1)*v2)", true)); + ASSERT_EQUALS("f ( ( A ) ( B ) & x )", tokenizeAndStringify("f((A)(B)&x)", true)); // #4439 + } + + void simplifyCasts10() { + ASSERT_EQUALS("; ( * f ) ( p ) ;", tokenizeAndStringify("; (*(void (*)(char *))f)(p);", true)); + } + + void simplifyCasts11() { + ASSERT_EQUALS("; x = 0 ;", tokenizeAndStringify("; *(int *)&x = 0;", true)); + } + + void simplifyCasts12() { + // #3935 - don't remove this cast + ASSERT_EQUALS("; ( ( short * ) data ) [ 5 ] = 0 ;", tokenizeAndStringify("; ((short*)data)[5] = 0;", true)); + } + + void simplifyCasts13() { + // casting deref / address of + ASSERT_EQUALS("; int x ; x = * y ;", tokenizeAndStringify(";int x=(int)*y;",true)); + ASSERT_EQUALS("; int x ; x = & y ;", tokenizeAndStringify(";int x=(int)&y;",true)); + TODO_ASSERT_EQUALS("; int x ; x = ( INT ) * y ;", + "; int x ; x = * y ;", + tokenizeAndStringify(";int x=(INT)*y;",true)); // INT might be a variable + TODO_ASSERT_EQUALS("; int x ; x = ( INT ) & y ;", + "; int x ; x = & y ;", + tokenizeAndStringify(";int x=(INT)&y;",true)); // INT might be a variable + + // #4899 - False positive on unused variable + ASSERT_EQUALS("; float angle ; angle = tilt ;", tokenizeAndStringify("; float angle = (float) tilt;", true)); // status quo + ASSERT_EQUALS("; float angle ; angle = ( float ) - tilt ;", tokenizeAndStringify("; float angle = (float) -tilt;", true)); + ASSERT_EQUALS("; float angle ; angle = ( float ) + tilt ;", tokenizeAndStringify("; float angle = (float) +tilt;", true)); + ASSERT_EQUALS("; int a ; a = ( int ) ~ c ;", tokenizeAndStringify("; int a = (int)~c;", true)); + } + + void simplifyCasts14() { // const + // #5081 + ASSERT_EQUALS("( ! ( & s ) . a ) ;", tokenizeAndStringify("(! ( (struct S const *) &s)->a);", true)); + // #5244 + ASSERT_EQUALS("bar ( & ptr ) ;", tokenizeAndStringify("bar((const X**)&ptr);",true)); + } + + void simplifyCasts15() { // #5996 - don't remove cast in 'a+static_cast(b?60:0)' + ASSERT_EQUALS("a + ( b ? 60 : 0 ) ;", + tokenizeAndStringify("a + static_cast(b ? 60 : 0);", true)); + } + + void simplifyCasts16() { // #6278 + ASSERT_EQUALS("Get ( pArray ) ;", + tokenizeAndStringify("Get((CObject*&)pArray);", true)); + } + + void simplifyCasts17() { // #6110 - don't remove any parentheses in 'a(b)(c)' + ASSERT_EQUALS("{ if ( a ( b ) ( c ) >= 3 ) { } }", + tokenizeAndStringify("{ if (a(b)(c) >= 3) { } }", true)); + } + void simplifyAt() { ASSERT_EQUALS("int x ;", tokenizeAndStringify("int x@123;")); ASSERT_EQUALS("bool x ;", tokenizeAndStringify("bool x@123:1;")); @@ -879,7 +1131,7 @@ private: ASSERT_EQUALS("asm\n\n( \"push b ; for if\" ) ;", tokenizeAndStringify("__asm\npush b ; for if\n__endasm;")); // 'asm ( ) ;' should be in the same line - ASSERT_EQUALS(";\n\nasm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify(";\n\n__asm__ volatile ( \"mov ax,bx\" );")); + ASSERT_EQUALS(";\n\nasm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify(";\n\n__asm__ volatile ( \"mov ax,bx\" );", true)); } // #4725 - ^{} @@ -947,7 +1199,7 @@ private: "{\n" "if ( a ) { ; }\n" "else { ; }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces2() { @@ -958,7 +1210,7 @@ private: ASSERT_EQUALS("void f ( )\n" "{\n" "if ( a ) { if ( b ) { } }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces3() { @@ -969,7 +1221,7 @@ private: ASSERT_EQUALS("void f ( )\n" "{\n" "if ( a ) { for ( ; ; ) { } }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces4() { @@ -988,7 +1240,7 @@ private: "for ( ; ; )\n" "{ } }\n" "return str ;\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces5() { @@ -1004,10 +1256,10 @@ private: ASSERT_EQUALS("void f ( )\n" "{\n" "for ( int i = 0 ; i < 2 ; i ++ ) {\n" - "if ( true ) {\n" - "return ; } }\n\n" + "\n" + "return ; }\n\n" "return ;\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces7() { @@ -1022,7 +1274,7 @@ private: "int a ;\n" "if ( a ) {\n" "( { a = 4 ; } ) , ( { a = 5 ; } ) ; }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces9() { @@ -1037,38 +1289,38 @@ private: "for ( int k = 0 ; k < VectorSize ; k ++ ) " "LOG_OUT ( ID_Vector [ k ] ) " "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } void ifAddBraces11() { const char code[] = "{ if (x) if (y) ; else ; }"; const char expected[] = "{ if ( x ) { if ( y ) { ; } else { ; } } }"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } void ifAddBraces12() { // ticket #1424 const char code[] = "{ if (x) do { } while(x); }"; const char expected[] = "{ if ( x ) { do { } while ( x ) ; } }"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } void ifAddBraces13() { // ticket #1809 const char code[] = "{ if (x) if (y) { } else { } else { } }"; const char expected[] = "{ if ( x ) { if ( y ) { } else { } } else { } }"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); // ticket #1809 const char code2[] = "{ if (x) while (y) { } else { } }"; const char expected2[] = "{ if ( x ) { while ( y ) { } } else { } }"; - ASSERT_EQUALS(expected2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true)); } void ifAddBraces15() { // ticket #2616 - unknown macro before if // TODO: Remove "A" or change it to ";A;". Then cleanup Tokenizer::ifAddBraces(). - ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}")); + ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false)); } void ifAddBraces16() { @@ -1098,16 +1350,16 @@ private: "\n" "else {\n" "bar2 ( ) ; }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces18() { // ticket #3424 - if if { } else else ASSERT_EQUALS("{ if ( x ) { if ( y ) { } else { ; } } else { ; } }", - tokenizeAndStringify("{ if(x) if(y){}else;else;}")); + tokenizeAndStringify("{ if(x) if(y){}else;else;}", false)); ASSERT_EQUALS("{ if ( x ) { if ( y ) { if ( z ) { } else { ; } } else { ; } } else { ; } }", - tokenizeAndStringify("{ if(x) if(y) if(z){}else;else;else;}")); + tokenizeAndStringify("{ if(x) if(y) if(z){}else;else;else;}", false)); } void ifAddBraces19() { @@ -1129,22 +1381,22 @@ private: "bar1 ( ) ; }\n" "else {\n" "bar2 ( ) ; } } }\n" - "}", tokenizeAndStringify(code)); + "}", tokenizeAndStringify(code, true)); } void ifAddBraces20() { // #5012 - syntax error 'else }' const char code[] = "void f() { if(x) {} else }"; - ASSERT_THROW(tokenizeAndStringify(code), InternalError); + ASSERT_THROW(tokenizeAndStringify(code, true), InternalError); } void ifAddBraces21() { // #5332 - if (x) label: {} ... const char code[] = "void f() { if(x) label: {} a=1; }"; - ASSERT_EQUALS("void f ( ) { if ( x ) { label : ; { } } a = 1 ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void f ( ) { if ( x ) { label : ; { } } a = 1 ; }", tokenizeAndStringify(code, false)); } void whileAddBraces() { const char code[] = "{while(a);}"; - ASSERT_EQUALS("{ while ( a ) { ; } }", tokenizeAndStringify(code)); + ASSERT_EQUALS("{ while ( a ) { ; } }", tokenizeAndStringify(code, true)); } void doWhileAddBraces() { @@ -1152,21 +1404,21 @@ private: const char code[] = "{do ; while (0);}"; const char result[] = "{ do { ; } while ( 0 ) ; }"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, false)); } { const char code[] = "{ UNKNOWN_MACRO ( do ) ; while ( a -- ) ; }"; const char result[] = "{ UNKNOWN_MACRO ( do ) ; while ( a -- ) { ; } }"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, true)); } { const char code[] = "{ UNKNOWN_MACRO ( do , foo ) ; while ( a -- ) ; }"; const char result[] = "{ UNKNOWN_MACRO ( do , foo ) ; while ( a -- ) { ; } }"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, true)); } { @@ -1186,7 +1438,7 @@ private: "while ( -- d > 0 ) ;\n" "return 0 ;\n" "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, true)); } { @@ -1202,7 +1454,7 @@ private: "while ( -- d > 0 ) ;\n" "return 0 ;\n" "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, true)); } { @@ -1213,7 +1465,7 @@ private: const char result[] = "void foo ( ) {\n" "do { while ( x ) { f ( ) ; } } while ( y ) ;\n" "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, true)); } } @@ -1229,7 +1481,7 @@ private: "if ( a ) { }\n" "else { } }\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } { @@ -1245,7 +1497,7 @@ private: "else { if ( b ) { }\n" "else { } } }\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } } @@ -1256,9 +1508,1623 @@ private: const char expected[] = "void f ( ) {\n" "for ( ; ; ) { try { } catch ( ... ) { } }\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); } + std::string simplifyKnownVariables(const char code[]) { + errout.str(""); + + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + 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" + " int a = 10;\n" + " a = g();\n" + " if (a);\n" + "}\n"; + + ASSERT_EQUALS( + "void f ( ) { int a ; a = 10 ; a = g ( ) ; if ( a ) { ; } }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables3() { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " while(true){\n" + " break;\n" + " a = 10;\n" + " }\n" + " if (a);\n" + "}\n"; + + ASSERT_EQUALS( + "void f ( ) { int a ; a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) { ; } }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables4() { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " if ( g(a));\n" + "}\n"; + + // TODO: if a is passed by value is is ok to simplify.. + ASSERT_EQUALS( + "void f ( ) { int a ; a = 4 ; if ( g ( a ) ) { ; } }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables5() { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " if ( a = 5 );\n" + "}\n"; + + ASSERT_EQUALS( + "void f ( ) { int a ; a = 4 ; if ( a = 5 ) { ; } }", + 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" + " int i = 10;\n" + " while(--i) {}\n" + "}\n"; + + ASSERT_EQUALS( + "void f ( ) { int i ; i = 10 ; while ( -- i ) { } }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables14() { + // ticket #753 + const char code[] = "void f ( ) { int n ; n = 1 ; do { ++ n ; } while ( n < 10 ) ; }"; + 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); }"; + ASSERT_THROW(simplifyKnownVariables(code), InternalError); + } + + void simplifyKnownVariables17() { + // ticket #807 - segmentation fault when macro isn't found + const char code[] = "void f ( ) { char *s = malloc(100);mp_ptr p = s; p++; }"; + ASSERT_EQUALS( + "void f ( ) { char * s ; s = malloc ( 100 ) ; mp_ptr p ; p = s ; p ++ ; }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables18() { + const char code[] = "void f ( ) { char *s = malloc(100);mp_ptr p = s; ++p; }"; + ASSERT_EQUALS( + "void f ( ) { char * s ; s = malloc ( 100 ) ; mp_ptr p ; p = s ; ++ p ; }", + simplifyKnownVariables(code)); + } + + void simplifyKnownVariables19() { + const char code[] = "void f ( ) { int i=0; do { if (i>0) { a(); } i=b(); } while (i != 12); }"; + ASSERT_EQUALS( + "void f ( ) { int i ; i = 0 ; do { if ( i > 0 ) { a ( ) ; } i = b ( ) ; } while ( i != 12 ) ; }", + 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 + const char code[] = "void foo(char *str)\n" + "{\n" + " int i;\n" + " for (i=0;i<10;++i) {\n" + " if (*str == 0) goto label;\n" + " }\n" + " return;\n" + "label:\n" + " str[i] = 0;\n" + "}\n"; + + // Current result + ASSERT_EQUALS( + "void foo ( char * str ) " + "{" + " int i ;" + " for ( i = 0 ; i < 10 ; ++ i ) {" + " if ( * str == 0 ) { goto label ; }" + " }" + " return ;" + " label : ;" + " str [ i ] = 0 ; " + "}", + simplifyKnownVariables(code)); + } + + { + // This testcase is related to ticket #1646 + const char code[] = "void foo(char *str)\n" + "{\n" + " int i;\n" + " for (i=0;i<10;++i) { }\n" + " return;\n" + " str[i] = 0;\n" + "}\n"; + + // Current result + ASSERT_EQUALS( + "void foo ( char * str ) " + "{" + " int i ;" + " for ( i = 0 ; i < 10 ; ++ i ) { }" + " return ;" + " str [ i ] = 0 ; " + "}", + simplifyKnownVariables(code)); + } + } + + 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" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h + i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 + v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h - i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 - v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h * i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 * v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h / i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 / v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h & i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 & v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h | i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 | v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h ^ i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 ^ v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h % i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 % v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h >> i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 >> v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "int foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h << i;\n" + "}\n"; + const char expected[] = "1: int foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 << v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h == i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 == v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h != i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 != v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h > i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 > v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h >= i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 >= v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h < i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 < v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h <= i;\n" + "}\n"; + const char expected[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 <= v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h && i;\n" + "}\n"; + const char wanted[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 && v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(wanted, tokenizeDebugListing(code, true)); + } + + { + const char code[] = "bool foo(int u, int v)\n" + "{\n" + " int h = u;\n" + " int i = v;\n" + " return h || i;\n" + "}\n"; + const char wanted[] = "1: bool foo ( int u@1 , int v@2 )\n" + "2: {\n" + "3:\n" + "4:\n" + "5: return u@1 || v@2 ;\n" + "6: }\n"; + ASSERT_EQUALS(wanted, tokenizeDebugListing(code, true)); + } + } + + void simplifyKnownVariables30() { + const char code[] = "int foo() {\n" + " iterator it1 = ints.begin();\n" + " iterator it2 = it1;\n" + " for (++it2;it2!=ints.end();++it2);\n" + "}\n"; + const char expected[] = "int foo ( ) {\n" + "iterator it1 ; it1 = ints . begin ( ) ;\n" + "iterator it2 ; it2 = it1 ;\n" + "for ( ++ it2 ; it2 != ints . end ( ) ; ++ it2 ) { ; }\n" + "}"; + 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" + " do { cin >> x; } while (x > 5);\n" + " a[x] = 0;\n" + "}\n"; + const char expected[] = "void f ( ) {\n" + "int x ; x = 10 ;\n" + "do { cin >> x ; } while ( x > 5 ) ;\n" + "a [ x ] = 0 ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariables35() { + // Ticket #2353 + const char code[] = "int f() {" + " int x = 0;" + " if (x == 0) {" + " return 0;" + " }" + " return 10 / x;" + "}"; + const char expected[] = "int f ( ) { int x ; x = 0 ; { return 0 ; } }"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + 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() {" + " char buf[10] = \"ab\";" + " memset(buf, 0, 10);" + "}"; + const char expected2[] = "void f ( ) { char buf [ 10 ] = \"ab\" ; memset ( buf , 0 , 10 ) ; }"; + ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true)); + } + + void simplifyKnownVariables37() { + // Ticket #2398 - no simplification in for loop + const char code[] = "void f() {\n" + " double x = 0;\n" + " for (int iter=0; iter<42; iter++) {\n" + " int EvaldF = 1;\n" + " if (EvaldF)\n" + " Eval (x);\n" + " }\n" + "}"; + const char expected[] = "void f ( ) {\n" + "double x ; x = 0 ;\n" + "for ( int iter = 0 ; iter < 42 ; iter ++ ) {\n" + "\n" + "\n" + "Eval ( x ) ;\n" + "}\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariables38() { + // Ticket #2399 - simplify conditions + const char code[] = "void f() {\n" + " int x = 0;\n" + " int y = 1;\n" + " if (x || y);\n" + "}"; + const char expected[] = "void f ( ) {\n" + "\n" + "\n" + ";\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, 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 ;\n\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 ;\n\ndelete [ ] x ;\n}", tokenizeAndStringify(code, true)); + } + } + + + void simplifyKnownVariables40() { + const char code[] = "void f() {\n" + " char c1 = 'a';\n" + " char c2 = { c1 };\n" + "}"; + ASSERT_EQUALS("void f ( ) {\n\nchar c2 ; c2 = { 'a' } ;\n}", tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariables41() { + const char code[] = "void f() {\n" + " int x = 0;\n" + " const int *p; p = &x;\n" + " if (p) { return 0; }\n" + "}"; + ASSERT_EQUALS("void f ( ) {\nint x ; x = 0 ;\nconst int * p ; p = & x ;\nif ( & x ) { return 0 ; }\n}", tokenizeAndStringify(code, true)); + } + + void 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" + " strcpy(a, \"hello\");\n" + " strcat(a, \"!\");\n" + "}"; + const char expected[] = "void f ( ) {\n" + "char a [ 10 ] ;\n" + "strcpy ( a , \"hello\" ) ;\n" + "strcat ( a , \"!\" ) ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.c")); + } + + { + 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)); + } + + // 3538 + { + const char code[] = "void f() {\n" + " char s[10];\n" + " strcpy(s, \"123\");\n" + " if (s[6] == ' ');\n" + "}"; + const char expected[] = "void f ( ) {\n" + "char s [ 10 ] ;\n" + "strcpy ( s , \"123\" ) ;\n" + "if ( s [ 6 ] == ' ' ) { ; }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + } + } + + void simplifyKnownVariables43() { + { + const char code[] = "void f() {\n" + " int a, *p; p = &a;\n" + " { int a = *p; }\n" + "}"; + const char expected[] = "void f ( ) {\n" + "int a ; int * p ; p = & a ;\n" + "{ int a ; a = * p ; }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + { + const char code[] = "void f() {\n" + " int *a, **p; p = &a;\n" + " { int *a = *p; }\n" + "}"; + const char expected[] = "void f ( ) {\n" + "int * a ; int * * p ; p = & a ;\n" + "{ int * a ; a = * p ; }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + } + + void simplifyKnownVariables44() { + const char code[] = "void a() {\n" + " static int i = 10;\n" + " b(i++);\n" + "}"; + const char expected[] = "void a ( ) {\n" + "static int i = 10 ;\n" + "b ( i ++ ) ;\n" + "}"; + 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" + " cin >> x;\n" + " return x;\n" + "}"; + + { + const char expected[] = "void f ( ) {\n" + "int x ; x = 0 ;\n" + "cin >> x ;\n" + "return x ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.cpp")); + } + + { + const char expected[] = "void f ( ) {\n" + "\n" + "cin >> 0 ;\n" + "return 0 ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.c")); + } + } + + void simplifyKnownVariables47() { + // #3621 + const char code[] = "void f() {\n" + " int x = 0;\n" + " cin >> std::hex >> x;\n" + "}"; + const char expected[] = "void f ( ) {\n" + "int x ; x = 0 ;\n" + "cin >> std :: hex >> x ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.cpp")); + } + + void simplifyKnownVariables48() { + // #3754 + const char code[] = "void f(int sz) {\n" + " int i;\n" + " for (i = 0; ((i3)); ++i) { }\n" + "}"; + const char expected[] = "void f ( int sz ) {\n" + "int i ;\n" + "for ( i = 0 ; ( i < sz ) && ( sz > 3 ) ; ++ i ) { }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.c")); + } + + void simplifyKnownVariables49() { // #3691 + const char code[] = "void f(int sz) {\n" + " switch (x) {\n" + " case 1: sz = 2; continue;\n" + " case 2: x = sz; break;\n" + " }\n" + "}"; + const char expected[] = "void f ( int sz ) {\n" + "switch ( x ) {\n" + "case 1 : ; sz = 2 ; continue ;\n" + "case 2 : ; x = sz ; break ;\n" + "}\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Native, "test.c")); + } + + 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" + "const char x1 = 'b' ;\n" + "f ( & x1 ) ;\n" + "const char x2 = 'b' ;\n" + "f ( y , & x2 ) ;\n" + "const char x3 = 'b' ;\n" + "t = & x3 ;\n" + "const char x4 = 'b' ;\n" + "t = y + & x4 ;\n" + "const char x5 = 'b' ;\n" + "z [ & x5 ] = y ;\n" + "const char x6 = 'b' ;\n" + "v = { & x6 } ;\n" + "const char x7 = 'b' ;\n" + "return & x7 ;\n" + "}"; + ASSERT_EQUALS(code, tokenizeAndStringify(code, true)); + } + { + //don't simplify '&x'! + const char code[] = "const int * foo ( ) {\n" + "const int x1 = 1 ;\n" + "f ( & x1 ) ;\n" + "const int x2 = 1 ;\n" + "f ( y , & x2 ) ;\n" + "const int x3 = 1 ;\n" + "t = & x3 ;\n" + "const int x4 = 1 ;\n" + "t = y + & x4 ;\n" + "const int x5 = 1 ;\n" + "z [ & x5 ] = y ;\n" + "const int x6 = 1 ;\n" + "v = { & x6 } ;\n" + "const int x7 = 1 ;\n" + "return & x7 ;\n" + "}"; + ASSERT_EQUALS(code, tokenizeAndStringify(code, true)); + } + } + + void simplifyKnownVariables51() { // #4409 hang + const char code[] = "void mhz_M(int enough) {\n" + " TYPE *x=&x, **p=x, **q = NULL;\n" + " BENCH1(q = _mhz_M(n); n = 1;)\n" + " use_pointer(q);\n" + "}"; + ASSERT_THROW(tokenizeAndStringify(code, true), InternalError); + } + + void simplifyKnownVariables52() { // #4728 "= x %op%" + ASSERT_EQUALS("void f ( ) { int y ; y = 34 + z ; }", tokenizeAndStringify("void f() { int x=34; int y=x+z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 - z ; }", tokenizeAndStringify("void f() { int x=34; int y=x-z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 * z ; }", tokenizeAndStringify("void f() { int x=34; int y=x*z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 / z ; }", tokenizeAndStringify("void f() { int x=34; int y=x/z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 % z ; }", tokenizeAndStringify("void f() { int x=34; int y=x%z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 & z ; }", tokenizeAndStringify("void f() { int x=34; int y=x&z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 | z ; }", tokenizeAndStringify("void f() { int x=34; int y=x|z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 ^ z ; }", tokenizeAndStringify("void f() { int x=34; int y=x^z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 << z ; }", tokenizeAndStringify("void f() { int x=34; int y=x<> z ; }", tokenizeAndStringify("void f() { int x=34; int y=x>>z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 && z ; }", tokenizeAndStringify("void f() { int x=34; int y=x&&z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 || z ; }", tokenizeAndStringify("void f() { int x=34; int y=x||z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 > z ; }", tokenizeAndStringify("void f() { int x=34; int y=x>z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 >= z ; }", tokenizeAndStringify("void f() { int x=34; int y=x>=z; }", true)); + ASSERT_EQUALS("void f ( ) { int y ; y = 34 < z ; }", tokenizeAndStringify("void f() { int x=34; int y=xtype() == 1)); }", true)); + } + + 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 ; 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 ; 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)); + } + + void simplifyKnownVariables57() { // #4724 + ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808UL ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true)); + ASSERT_EQUALS("long long x ; x = -9223372036854775808L ;", tokenizeAndStringify("long long x = 1L << 63 ;", true)); + } + + void simplifyKnownVariables58() { // #5268 + const char code[] = "enum e { VAL1 = 1, VAL2 }; " + "typedef char arr_t[VAL2]; " + "int foo(int) ; " + "void bar () { " + " throw foo (VAL1); " + "} " + "int baz() { " + " return sizeof(arr_t); " + "}"; + ASSERT_EQUALS("enum e { VAL1 = 1 , VAL2 } ; " + "int foo ( int ) ; " + "void bar ( ) { " + "throw foo ( VAL1 ) ; " + "} " + "int baz ( ) { " + "return sizeof ( char [ VAL2 ] ) ; " + "}", tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariables59() { // #5062 - for head + const char code[] = "void f() {\n" + " int a[3], i, j;\n" + " for(i = 0, j = 1; i < 3, j < 12; i++,j++) {\n" + " a[i] = 0;\n" + " }\n" + "}"; + ASSERT_EQUALS("void f ( ) {\n" + "int a [ 3 ] ; int i ; int j ;\n" + "for ( i = 0 , j = 1 ; i < 3 , j < 12 ; i ++ , j ++ ) {\n" + "a [ i ] = 0 ;\n" + "}\n" + "}", 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" + "struct s {\n" + " enum Bar {\n" + " XX,\n" + " Other\n" + " };\n" + " enum { XX };\n" + "};", /*simplify=*/true); + ASSERT_EQUALS("", errout.str()); + } + + void simplifyKnownVariables62() { // #5666 + ASSERT_EQUALS("void foo ( std :: string str ) {\n" + "char * p ; p = & str [ 0 ] ;\n" + "* p = 0 ;\n" + "}", + tokenizeAndStringify("void foo(std::string str) {\n" + " char *p = &str[0];\n" + " *p = 0;\n" + "}", /*simplify=*/true)); + } + + void simplifyKnownVariablesBailOutAssign1() { + const char code[] = "int foo() {\n" + " int i; i = 0;\n" + " if (x) { i = 10; }\n" + " return i;\n" + "}\n"; + const char expected[] = "int foo ( ) {\n" + "int i ; i = 0 ;\n" + "if ( x ) { i = 10 ; }\n" + "return i ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariablesBailOutAssign2() { + // ticket #3032 - assignment in condition + const char code[] = "void f(struct ABC *list) {\n" + " struct ABC *last = NULL;\n" + " nr = (last = list->prev)->nr;\n" // <- don't replace "last" with 0 + "}\n"; + const char expected[] = "void f ( struct ABC * list ) {\n" + "struct ABC * last ; last = NULL ;\n" + "nr = ( last = list . prev ) . nr ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariablesBailOutAssign3() { // #4395 - nested assignments + const char code[] = "void f() {\n" + " int *p = 0;\n" + " a = p = (VdbeCursor*)pMem->z;\n" + " return p ;\n" + "}\n"; + const char expected[] = "void f ( ) {\n" + "int * p ; p = 0 ;\n" + "a = p = pMem . z ;\n" + "return p ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariablesBailOutFor1() { + const char code[] = "void foo() {\n" + " for (int i = 0; i < 10; ++i) { }\n" + "}\n"; + const char expected[] = "void foo ( ) {\n" + "for ( int i = 0 ; i < 10 ; ++ i ) { }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); // debug warnings + } + + void simplifyKnownVariablesBailOutFor2() { + const char code[] = "void foo() {\n" + " int i = 0;\n" + " while (i < 10) { ++i; }\n" + "}\n"; + const char expected[] = "void foo ( ) {\n" + "int i ; i = 0 ;\n" + "while ( i < 10 ) { ++ i ; }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); // debug warnings + } + + void simplifyKnownVariablesBailOutFor3() { + const char code[] = "void foo() {\n" + " for (std::string::size_type pos = 0; pos < 10; ++pos)\n" + " { }\n" + "}\n"; + const char expected[] = "void foo ( ) {\n" + "for ( std :: string :: size_type pos = 0 ; pos < 10 ; ++ pos )\n" + "{ }\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); // debug warnings + } + + void simplifyKnownVariablesBailOutMemberFunction() { + const char code[] = "void foo(obj a) {\n" + " obj b = a;\n" + " b.f();\n" + "}\n"; + const char expected[] = "void foo ( obj a ) {\n" + "obj b ; b = a ;\n" + "b . f ( ) ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + void simplifyKnownVariablesBailOutConditionalIncrement() { + const char code[] = "int f() {\n" + " int a = 0;\n" + " if (x) {\n" + " ++a;\n" // conditional increment + " }\n" + " return a;\n" + "}\n"; + tokenizeAndStringify(code,true); + ASSERT_EQUALS("", errout.str()); // no debug warnings + } + + void simplifyKnownVariablesBailOutSwitchBreak() { + // Ticket #2324 + const char code[] = "int f(char *x) {\n" + " char *p;\n" + " char *q;\n" + "\n" + " switch (x & 0x3)\n" + " {\n" + " case 1:\n" + " p = x;\n" + " x = p;\n" + " break;\n" + " case 2:\n" + " q = x;\n" // x is not equal with p + " x = q;\n" + " break;\n" + " }\n" + "}\n"; + + const char expected[] = "int f ( char * x ) {\n" + "char * p ;\n" + "char * q ;\n" + "\n" + "switch ( x & 0x3 )\n" + "{\n" + "case 1 : ;\n" + "p = x ;\n" + "x = p ;\n" + "break ;\n" + "case 2 : ;\n" + "q = x ;\n" + "x = q ;\n" + "break ;\n" + "}\n" + "}"; + + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + } + + void simplifyKnownVariablesFloat() { + // Ticket #2454 + const char code[] = "void f() {\n" + " float a = 40;\n" + " x(10 / a);\n" + "}\n"; + + const char expected[] = "void f ( ) {\n\nx ( 0.25 ) ;\n}"; + + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + + // Ticket #4227 + const char code2[] = "double f() {" + " double a = false;" + " return a;" + "}"; + ASSERT_EQUALS("double f ( ) { return 0.0 ; }", tokenizeAndStringify(code2,true)); + + // Ticket #5485 + const char code3[] = "void f() {" + " double a = 1e+007;\n" + " std::cout << a;\n" + "}"; + ASSERT_EQUALS("void f ( ) {\nstd :: cout << 1e+007 ;\n}", tokenizeAndStringify(code3,true)); + + const char code4[] = "void f() {" + " double a = 1;\n" + " std::cout << a;\n" + "}"; + ASSERT_EQUALS("void f ( ) {\nstd :: cout << 1.0 ;\n}", tokenizeAndStringify(code4,true)); + } + + void simplifyKnownVariablesFunctionCalls() { + { + const char code[] = "void a(int x);" // <- x is passed by value + "void b() {" + " int x = 123;" + " a(x);" // <- replace with a(123); + "}"; + const char expected[] = "void a ( int x ) ; void b ( ) { a ( 123 ) ; }"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + } + + { + const char code[] = "void a(int &x);" // <- x is passed by reference + "void b() {" + " int x = 123;" + " a(x);" // <- don't replace with a(123); + "}"; + const char expected[] = "void a ( int & x ) ; void b ( ) { int x ; x = 123 ; a ( x ) ; }"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + } + } + + void simplifyKnownVariablesGlobalVars() { + // #8054 + const char code[] = "static int x;" + "void f() {" + " x = 123;" + " while (!x) { dostuff(); }" + "}"; + ASSERT_EQUALS("static int x ; void f ( ) { x = 123 ; while ( ! x ) { dostuff ( ) ; } }", tokenizeAndStringify(code,true)); + } + + void simplifyKnownVariablesReturn() { + const char code[] = "int a() {" + " int x = 123;" + " return (x);" + "}"; + ASSERT_EQUALS("int a ( ) { return 123 ; }", 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 simplifyKnownVariablesClassMember() { + // Ticket #2815 + { + const char code[] = "char *a;\n" + "void f(const char *s) {\n" + " a = NULL;\n" + " x();\n" + " memcpy(a, s, 10);\n" // <- don't simplify "a" here + "}\n"; + + const std::string s(tokenizeAndStringify(code, true)); + ASSERT_EQUALS(true, s.find("memcpy ( a , s , 10 ) ;") != std::string::npos); + } + + // If the variable is local then perform simplification.. + { + const char code[] = "void f(const char *s) {\n" + " char *a = NULL;\n" + " x();\n" + " memcpy(a, s, 10);\n" // <- simplify "a" + "}\n"; + + const std::string s(tokenizeAndStringify(code, true)); + TODO_ASSERT_EQUALS(true, false, s.find("memcpy ( 0 , s , 10 ) ;") != std::string::npos); + } + } void simplifyExternC() { ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" int foo();")); @@ -1292,7 +3158,7 @@ private: " int x;" " { }" "}"; - ASSERT_EQUALS("void foo ( ) { if ( x ) { int x ; } { } }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { if ( x ) { } { } }", tokenizeAndStringify(code, true)); } } @@ -1364,6 +3230,7 @@ private: " comphelper::EmbeddedObjectContainer aCnt( xDestStorage );\n" " { }\n" "}"); + ASSERT_EQUALS("", errout.str()); } // Simplify "((..))" into "(..)" @@ -1373,7 +3240,7 @@ private: " free(((void*)p));" "}"; - ASSERT_EQUALS("void foo ( ) { free ( ( void * ) p ) ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { free ( p ) ; }", tokenizeAndStringify(code, true)); } void removeParentheses3() { @@ -1382,7 +3249,7 @@ private: "{" " if (( true )==(true)){}" "}"; - ASSERT_EQUALS("void foo ( ) { if ( true == true ) { } }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { }", tokenizeAndStringify(code, true)); } { @@ -1390,7 +3257,7 @@ private: "{" " if (( 2 )==(2)){}" "}"; - ASSERT_EQUALS("void foo ( ) { if ( 2 == 2 ) { } }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { }", tokenizeAndStringify(code, true)); } { @@ -1446,14 +3313,14 @@ private: void removeParentheses7() { const char code[] = ";char *p; (delete(p), (p)=0);"; - ASSERT_EQUALS("; char * p ; delete ( p ) , p = 0 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("; char * p ; delete p ; p = 0 ;", tokenizeAndStringify(code,true)); } void removeParentheses8() { const char code[] = "struct foo {\n" " void operator delete(void *obj, size_t sz);\n" "}\n"; - const std::string actual(tokenizeAndStringify(code, true, Settings::Win32A)); + const std::string actual(tokenizeAndStringify(code, false, true, Settings::Win32A)); const char expected[] = "struct foo {\n" "void operatordelete ( void * obj , unsigned long sz ) ;\n" @@ -1463,65 +3330,65 @@ private: } void removeParentheses9() { - ASSERT_EQUALS("void delete ( double num ) ;", tokenizeAndStringify("void delete(double num);")); + ASSERT_EQUALS("void delete ( double num ) ;", tokenizeAndStringify("void delete(double num);", false)); } void removeParentheses10() { - ASSERT_EQUALS("p = buf + 8 ;", tokenizeAndStringify("p = (buf + 8);")); + ASSERT_EQUALS("p = buf + 8 ;", tokenizeAndStringify("p = (buf + 8);", false)); } void removeParentheses11() { // #2502 - ASSERT_EQUALS("{ } x ( ) ;", tokenizeAndStringify("{}(x());")); + ASSERT_EQUALS("{ } x ( ) ;", tokenizeAndStringify("{}(x());", false)); } void removeParentheses12() { // #2760 - ASSERT_EQUALS(", x = 0 ;", tokenizeAndStringify(",(x)=0;")); + ASSERT_EQUALS(", x = 0 ;", tokenizeAndStringify(",(x)=0;", false)); } void removeParentheses13() { - ASSERT_EQUALS("; f ( a + b , c ) ;", tokenizeAndStringify(";f((a+b),c);")); - ASSERT_EQUALS("; x = y [ a + b ] ;", tokenizeAndStringify(";x=y[(a+b)];")); + ASSERT_EQUALS("; f ( a + b , c ) ;", tokenizeAndStringify(";f((a+b),c);", false)); + ASSERT_EQUALS("; x = y [ a + b ] ;", tokenizeAndStringify(";x=y[(a+b)];", false)); } void removeParentheses14() { - ASSERT_EQUALS("{ if ( ( i & 1 ) == 0 ) { ; } }", tokenizeAndStringify("{ if ( (i & 1) == 0 ); }")); + ASSERT_EQUALS("{ if ( ( i & 1 ) == 0 ) { ; } }", tokenizeAndStringify("{ if ( (i & 1) == 0 ); }", false)); } void removeParentheses15() { - ASSERT_EQUALS("a = b ? c : 123 ;", tokenizeAndStringify("a = b ? c : (123);")); - ASSERT_EQUALS("a = b ? c : ( 123 + 456 ) ;", tokenizeAndStringify("a = b ? c : ((123)+(456));")); - ASSERT_EQUALS("a = b ? 123 : c ;", tokenizeAndStringify("a = b ? (123) : c;")); + ASSERT_EQUALS("a = b ? c : 123 ;", tokenizeAndStringify("a = b ? c : (123);", false)); + ASSERT_EQUALS("a = b ? c : ( 123 + 456 ) ;", tokenizeAndStringify("a = b ? c : ((123)+(456));", false)); + ASSERT_EQUALS("a = b ? 123 : c ;", tokenizeAndStringify("a = b ? (123) : c;", false)); // #4316 - ASSERT_EQUALS("a = b ? c : ( d = 1 , 0 ) ;", tokenizeAndStringify("a = b ? c : (d=1,0);")); + ASSERT_EQUALS("a = b ? c : ( d = 1 , 0 ) ;", tokenizeAndStringify("a = b ? c : (d=1,0);", false)); } void removeParentheses16() { // *(x.y)= // #4423 - ASSERT_EQUALS("; * x = 0 ;", tokenizeAndStringify(";*(x)=0;")); - ASSERT_EQUALS("; * x . y = 0 ;", tokenizeAndStringify(";*(x.y)=0;")); + ASSERT_EQUALS("; * x = 0 ;", tokenizeAndStringify(";*(x)=0;", false)); + ASSERT_EQUALS("; * x . y = 0 ;", tokenizeAndStringify(";*(x.y)=0;", false)); } void removeParentheses17() { // a ? b : (c > 0 ? d : e) - ASSERT_EQUALS("a ? b : ( c > 0 ? d : e ) ;", tokenizeAndStringify("a?b:(c>0?d:e);")); + ASSERT_EQUALS("a ? b : ( c > 0 ? d : e ) ;", tokenizeAndStringify("a?b:(c>0?d:e);", false)); } void removeParentheses18() { - ASSERT_EQUALS("float ( * a ) [ 2 ] ;", tokenizeAndStringify("float(*a)[2];")); + ASSERT_EQUALS("float ( * a ) [ 2 ] ;", tokenizeAndStringify("float(*a)[2];", false)); } void removeParentheses19() { - ASSERT_EQUALS("( ( ( typeof ( X ) ) * ) 0 ) ;", tokenizeAndStringify("(((typeof(X))*)0);")); + ASSERT_EQUALS("( ( ( typeof ( X ) ) * ) 0 ) ;", tokenizeAndStringify("(((typeof(X))*)0);", false)); } void removeParentheses20() { - ASSERT_EQUALS("a < b < int > > ( 2 ) ;", tokenizeAndStringify("a>(2);")); + ASSERT_EQUALS("a < b < int > > ( 2 ) ;", tokenizeAndStringify("a>(2);", false)); } void removeParentheses21() { - ASSERT_EQUALS("a = ( int ) - b ;", tokenizeAndStringify("a = ((int)-b);")); + ASSERT_EQUALS("a = ( int ) - b ;", tokenizeAndStringify("a = ((int)-b);", false)); } void removeParentheses22() { @@ -1611,6 +3478,90 @@ private: "}", tokenizeAndStringify(code)); } + void simplify_constants() { + const char code[] = + "void f() {\n" + "const int a = 45;\n" + "if( a )\n" + "{ int b = a; }\n" + "}\n" + "void g() {\n" + "int a = 2;\n" + "}"; + ASSERT_EQUALS("void f ( ) {\n" + "\n" + "\n" + "\n" + "}\n" + "void g ( ) {\n" + "\n" + "}", tokenizeAndStringify(code, true)); + } + + 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 ) {\n" + "\n" + "foo . a = 90 ;\n" + "foo2 . a = 45 ;\n" + "}", tokenizeAndStringify(code, true)); + } + + void simplify_constants3() { + const char code[] = + "static const char str[] = \"abcd\";\n" + "static const unsigned int SZ = sizeof(str);\n" + "void f() {\n" + "a = SZ;\n" + "}\n"; + const char expected[] = + "static const char str [ 5 ] = \"abcd\" ;\n\nvoid f ( ) {\na = 5 ;\n}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); + } + + 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 ;\ny = 50 ;", tokenizeAndStringify(code,true)); + } + + void simplify_constants5() { + const char code[] = "int buffer[10];\n" + "static const int NELEMS = sizeof(buffer)/sizeof(int);\n" + "static const int NELEMS2(sizeof(buffer)/sizeof(int));\n" + "x = NELEMS;\n" + "y = NELEMS2;\n"; + ASSERT_EQUALS("int buffer [ 10 ] ;\n\n\nx = 10 ;\ny = 10 ;", tokenizeAndStringify(code,true)); + } + + void simplify_constants6() { // Ticket #5625 + { + const char code[] = "template < class T > struct foo ;\n" + "void bar ( ) {\n" + "foo < 1 ? 0 ? 1 : 6 : 2 > x ;\n" + "foo < 1 ? 0 : 2 > y ;\n" + "}"; + const char exp [] = "template < class T > struct foo ;\n" + "void bar ( ) {\n" + "foo < 6 > x ;\n" + "foo < 0 > y ;\n" + "}"; + ASSERT_EQUALS(exp, tokenizeAndStringify(code, true)); + } + { + const char code[] = "bool b = true ? false : 1 > 2 ;"; + const char exp [] = "bool b ; b = false ;"; + ASSERT_EQUALS(exp, tokenizeAndStringify(code, true)); + } + } + void simplifyMulAndParens() { // (error) Resource leak const char code[] = "void f() {" @@ -1934,7 +3885,7 @@ private: void vardecl14() { const char code[] = "::std::tr1::shared_ptr pNum1, pNum2;\n"; - ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, false, Settings::Native, "test.cpp", false)); + ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, false, false, Settings::Native, "test.cpp", false)); } void vardecl15() { @@ -2139,7 +4090,7 @@ private: void vardecl26() { // #5907 const char code[] = "extern int *new, obj, player;"; const char expected[] = "extern int * new ; extern int obj ; extern int player ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Settings::Native, "test.c")); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, false, true, Settings::Native, "test.c")); ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } @@ -2150,7 +4101,7 @@ private: " return 0;\n" " return 0;\n" "}"; - tokenizeAndStringify(code, /*expand=*/true, Settings::Native, "test.c"); + tokenizeAndStringify(code, /*simplify=*/false, /*expand=*/true, Settings::Native, "test.c"); } void volatile_variables() { @@ -3051,15 +5002,15 @@ private: // Pointer to standard type ASSERT_EQUALS("char buf [ 100 ] ; readlink ( path , buf , 99 ) ;", tokenizeAndStringify("char buf[100] ; readlink(path, &buf[0], 99);", - true, Settings::Native, "test.c")); + false, true, Settings::Native, "test.c")); ASSERT_EQUALS("void foo ( char * c ) { if ( 1 == ( 1 & c [ 0 ] ) ) { } }", tokenizeAndStringify("void foo(char *c) { if (1==(1 & c[0])) {} }", - true, Settings::Native, "test.c")); + false, true, Settings::Native, "test.c")); // Simplification of unknown type - C only ASSERT_EQUALS("foo data [ 100 ] ; something ( foo ) ;", - tokenizeAndStringify("foo data[100]; something(&foo[0]);", true, Settings::Native, "test.c")); + tokenizeAndStringify("foo data[100]; something(&foo[0]);", false, true, Settings::Native, "test.c")); // C++: No pointer simplification ASSERT_EQUALS("foo data [ 100 ] ; something ( & foo [ 0 ] ) ;", @@ -3106,49 +5057,55 @@ private: "3:\n" "4: virtual void * getFP ( ) ;\n" "5: } ;\n"; - ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + ASSERT_EQUALS(expected, tokenizeDebugListing(code, false)); } void functionpointer5() { const char code[] = ";void (*fp[])(int a) = {0,0,0};"; const char expected[] = "1: ; void ( * fp@1 [ ] ) ( ) = { 0 , 0 , 0 } ;\n"; // TODO: Array dimension - ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + ASSERT_EQUALS(expected, tokenizeDebugListing(code, false)); } void functionpointer6() { const char code1[] = "void (*fp(void))(int) {}"; const char expected1[] = "1: void * fp ( ) { }\n"; - ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); + ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); const char code2[] = "std::string (*fp(void))(int);"; const char expected2[] = "1: std :: string * fp ( ) ;\n"; - ASSERT_EQUALS(expected2, tokenizeDebugListing(code2)); + ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false)); } void functionpointer7() { const char code1[] = "void (X::*y)();"; const char expected1[] = "1: void ( * y@1 ) ( ) ;\n"; - ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); + ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); } void functionpointer8() { const char code1[] = "int (*f)() throw(int);"; const char expected1[] = "1: int ( * f@1 ) ( ) ;\n"; - ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); + ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); } void functionpointer9() { // function call with function pointer const char code1[] = "int f() { (*f)(); }"; const char expected1[] = "1: int f ( ) { ( * f ) ( ) ; }\n"; - ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); + ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); const char code2[] = "int f() { return (*f)(); }"; const char expected2[] = "1: int f ( ) { return ( * f ) ( ) ; }\n"; - ASSERT_EQUALS(expected2, tokenizeDebugListing(code2)); + ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false)); const char code3[] = "int f() { throw (*f)(); }"; const char expected3[] = "1: int f ( ) { throw ( * f ) ( ) ; }\n"; - ASSERT_EQUALS(expected3, tokenizeDebugListing(code3)); + ASSERT_EQUALS(expected3, tokenizeDebugListing(code3, false)); + } + + void removeRedundantAssignment() { + ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() { int *p, *q; p = q; }", true)); + ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() { int *p = 0, *q; p = q; }", true)); + ASSERT_EQUALS("int f ( int * x ) { return * x ; }", tokenizeAndStringify("int f(int *x) { return *x; }", true)); } void removedeclspec() { @@ -3552,19 +5509,53 @@ private: { const char code[] = "class A { } ; A a; int foo(a);"; - ASSERT_EQUALS("class A { } ; A a ; int foo ; foo = a ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("class A { } ; A a ; int foo ; foo = a ;", tokenizeAndStringify(code, false)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int x(f());"; - ASSERT_EQUALS("int x ; x = f ( ) ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int x ; x = f ( ) ;", tokenizeAndStringify(code, false)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "{ return doSomething(X), 0; }"; - ASSERT_EQUALS("{ return doSomething ( X ) , 0 ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("{ return doSomething ( X ) , 0 ; }", tokenizeAndStringify(code, false)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "const int x(1);" + "const int y(2);" + "const int z((x+1)*y);" + "f(z);"; + ASSERT_EQUALS("f ( 4 ) ;", tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "const int x(1);" + "const int y(2);" + "const int z((x+1)*y);" + "f(&z);"; + ASSERT_EQUALS("const int z ( 4 ) ; f ( & z ) ;", tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "const bool x(true);" + "const bool y(!x);" + "f(y);"; + ASSERT_EQUALS("f ( false ) ;", tokenizeAndStringify(code, true)); + ASSERT_EQUALS("", errout.str()); + } + + { + const char code[] = "const bool x(true);" + "const bool y(!x);" + "f(&y);"; + ASSERT_EQUALS("const bool y ( false ) ; f ( & y ) ;", tokenizeAndStringify(code, true)); ASSERT_EQUALS("", errout.str()); } } @@ -3590,173 +5581,173 @@ private: void bitfields1() { const char code1[] = "struct A { bool x : 1; };"; - ASSERT_EQUALS("struct A { bool x ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct A { bool x ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { char x : 3; };"; - ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { short x : 3; };"; - ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringify(code3)); + ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringify(code3,false)); const char code4[] = "struct A { int x : 3; };"; - ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringify(code4)); + ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringify(code4,false)); const char code5[] = "struct A { long x : 3; };"; - ASSERT_EQUALS("struct A { long x ; } ;", tokenizeAndStringify(code5)); + ASSERT_EQUALS("struct A { long x ; } ;", tokenizeAndStringify(code5,false)); const char code6[] = "struct A { __int8 x : 3; };"; - ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringifyWindows(code6, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringifyWindows(code6,false, true, Settings::Win32A)); const char code7[] = "struct A { __int16 x : 3; };"; - ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringifyWindows(code7, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringifyWindows(code7,false, true, Settings::Win32A)); const char code8[] = "struct A { __int32 x : 3; };"; - ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringifyWindows(code8, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringifyWindows(code8,false, true, Settings::Win32A)); const char code9[] = "struct A { __int64 x : 3; };"; - ASSERT_EQUALS("struct A { long long x ; } ;", tokenizeAndStringifyWindows(code9, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { long long x ; } ;", tokenizeAndStringifyWindows(code9,false, true, Settings::Win32A)); const char code10[] = "struct A { unsigned char x : 3; };"; - ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringify(code10)); + ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringify(code10,false)); const char code11[] = "struct A { unsigned short x : 3; };"; - ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringify(code11)); + ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringify(code11,false)); const char code12[] = "struct A { unsigned int x : 3; };"; - ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringify(code12)); + ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringify(code12,false)); const char code13[] = "struct A { unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { unsigned long x ; } ;", tokenizeAndStringify(code13)); + ASSERT_EQUALS("struct A { unsigned long x ; } ;", tokenizeAndStringify(code13,false)); const char code14[] = "struct A { unsigned __int8 x : 3; };"; - ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringifyWindows(code14, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringifyWindows(code14,false, true, Settings::Win32A)); const char code15[] = "struct A { unsigned __int16 x : 3; };"; - ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringifyWindows(code15, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringifyWindows(code15,false, true, Settings::Win32A)); const char code16[] = "struct A { unsigned __int32 x : 3; };"; - ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringifyWindows(code16, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringifyWindows(code16,false, true, Settings::Win32A)); const char code17[] = "struct A { unsigned __int64 x : 3; };"; - ASSERT_EQUALS("struct A { unsigned long long x ; } ;", tokenizeAndStringifyWindows(code17, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { unsigned long long x ; } ;", tokenizeAndStringifyWindows(code17,false, true, Settings::Win32A)); const char code18[] = "struct A { signed char x : 3; };"; - ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringify(code18)); + ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringify(code18,false)); const char code19[] = "struct A { signed short x : 3; };"; - ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringify(code19)); + ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringify(code19,false)); const char code20[] = "struct A { signed int x : 3; };"; - ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringify(code20)); + ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringify(code20,false)); const char code21[] = "struct A { signed long x : 3; };"; - ASSERT_EQUALS("struct A { signed long x ; } ;", tokenizeAndStringifyWindows(code21)); + ASSERT_EQUALS("struct A { signed long x ; } ;", tokenizeAndStringifyWindows(code21,false)); const char code22[] = "struct A { signed __int8 x : 3; };"; - ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringifyWindows(code22, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringifyWindows(code22,false, true, Settings::Win32A)); const char code23[] = "struct A { signed __int16 x : 3; };"; - ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringifyWindows(code23, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringifyWindows(code23,false, true, Settings::Win32A)); const char code24[] = "struct A { signed __int32 x : 3; };"; - ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringifyWindows(code24, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringifyWindows(code24,false, true, Settings::Win32A)); const char code25[] = "struct A { signed __int64 x : 3; };"; - ASSERT_EQUALS("struct A { signed long long x ; } ;", tokenizeAndStringifyWindows(code25, true, Settings::Win32A)); + ASSERT_EQUALS("struct A { signed long long x ; } ;", tokenizeAndStringifyWindows(code25,false, true, Settings::Win32A)); } void bitfields2() { const char code1[] = "struct A { public: int x : 3; };"; - ASSERT_EQUALS("struct A { public: int x ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct A { public: int x ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { public: unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { public: unsigned long x ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { public: unsigned long x ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { protected: int x : 3; };"; - ASSERT_EQUALS("struct A { protected: int x ; } ;", tokenizeAndStringify(code3)); + ASSERT_EQUALS("struct A { protected: int x ; } ;", tokenizeAndStringify(code3,false)); const char code4[] = "struct A { protected: unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { protected: unsigned long x ; } ;", tokenizeAndStringify(code4)); + ASSERT_EQUALS("struct A { protected: unsigned long x ; } ;", tokenizeAndStringify(code4,false)); const char code5[] = "struct A { private: int x : 3; };"; - ASSERT_EQUALS("struct A { private: int x ; } ;", tokenizeAndStringify(code5)); + ASSERT_EQUALS("struct A { private: int x ; } ;", tokenizeAndStringify(code5,false)); const char code6[] = "struct A { private: unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { private: unsigned long x ; } ;", tokenizeAndStringify(code6)); + ASSERT_EQUALS("struct A { private: unsigned long x ; } ;", tokenizeAndStringify(code6,false)); } void bitfields3() { const char code1[] = "struct A { const int x : 3; };"; - ASSERT_EQUALS("struct A { const int x ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct A { const int x ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { const unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { const unsigned long x ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { const unsigned long x ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { public: const int x : 3; };"; - ASSERT_EQUALS("struct A { public: const int x ; } ;", tokenizeAndStringify(code3)); + ASSERT_EQUALS("struct A { public: const int x ; } ;", tokenizeAndStringify(code3,false)); const char code4[] = "struct A { public: const unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { public: const unsigned long x ; } ;", tokenizeAndStringify(code4)); + ASSERT_EQUALS("struct A { public: const unsigned long x ; } ;", tokenizeAndStringify(code4,false)); } void bitfields4() { // ticket #1956 const char code1[] = "struct A { CHAR x : 3; };"; - ASSERT_EQUALS("struct A { CHAR x ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct A { CHAR x ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { UCHAR x : 3; };"; - ASSERT_EQUALS("struct A { UCHAR x ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { UCHAR x ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { BYTE x : 3; };"; - ASSERT_EQUALS("struct A { BYTE x ; } ;", tokenizeAndStringify(code3)); + ASSERT_EQUALS("struct A { BYTE x ; } ;", tokenizeAndStringify(code3,false)); const char code4[] = "struct A { WORD x : 3; };"; - ASSERT_EQUALS("struct A { WORD x ; } ;", tokenizeAndStringify(code4)); + ASSERT_EQUALS("struct A { WORD x ; } ;", tokenizeAndStringify(code4,false)); const char code5[] = "struct A { DWORD x : 3; };"; - ASSERT_EQUALS("struct A { DWORD x ; } ;", tokenizeAndStringify(code5)); + ASSERT_EQUALS("struct A { DWORD x ; } ;", tokenizeAndStringify(code5,false)); const char code6[] = "struct A { LONG x : 3; };"; - ASSERT_EQUALS("struct A { LONG x ; } ;", tokenizeAndStringify(code6)); + ASSERT_EQUALS("struct A { LONG x ; } ;", tokenizeAndStringify(code6,false)); const char code7[] = "struct A { UINT8 x : 3; };"; - ASSERT_EQUALS("struct A { UINT8 x ; } ;", tokenizeAndStringify(code7)); + ASSERT_EQUALS("struct A { UINT8 x ; } ;", tokenizeAndStringify(code7,false)); const char code8[] = "struct A { UINT16 x : 3; };"; - ASSERT_EQUALS("struct A { UINT16 x ; } ;", tokenizeAndStringify(code8)); + ASSERT_EQUALS("struct A { UINT16 x ; } ;", tokenizeAndStringify(code8,false)); const char code9[] = "struct A { UINT32 x : 3; };"; - ASSERT_EQUALS("struct A { UINT32 x ; } ;", tokenizeAndStringify(code9)); + ASSERT_EQUALS("struct A { UINT32 x ; } ;", tokenizeAndStringify(code9,false)); const char code10[] = "struct A { UINT64 x : 3; };"; - ASSERT_EQUALS("struct A { UINT64 x ; } ;", tokenizeAndStringify(code10)); + ASSERT_EQUALS("struct A { UINT64 x ; } ;", tokenizeAndStringify(code10,false)); } void bitfields5() { // ticket #1956 const char code1[] = "struct RGB { unsigned int r : 3, g : 3, b : 2; };"; - ASSERT_EQUALS("struct RGB { unsigned int r ; unsigned int g ; unsigned int b ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct RGB { unsigned int r ; unsigned int g ; unsigned int b ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { int a : 3; int : 3; int c : 3; };"; - ASSERT_EQUALS("struct A { int a ; int c ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { int a ; int c ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { virtual void f() {} int f1 : 1; };"; - ASSERT_EQUALS("struct A { virtual void f ( ) { } int f1 ; } ;", tokenizeAndStringify(code3)); + ASSERT_EQUALS("struct A { virtual void f ( ) { } int f1 ; } ;", tokenizeAndStringify(code3,false)); } void bitfields6() { // ticket #2595 const char code1[] = "struct A { bool b : true; };"; - ASSERT_EQUALS("struct A { bool b ; } ;", tokenizeAndStringify(code1)); + ASSERT_EQUALS("struct A { bool b ; } ;", tokenizeAndStringify(code1,false)); const char code2[] = "struct A { bool b : true, c : true; };"; - ASSERT_EQUALS("struct A { bool b ; bool c ; } ;", tokenizeAndStringify(code2)); + ASSERT_EQUALS("struct A { bool b ; bool c ; } ;", tokenizeAndStringify(code2,false)); const char code3[] = "struct A { bool : true; };"; - ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3)); + 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)); + 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)); + ASSERT_EQUALS("void f ( int a ) { switch ( a ) { default : ; break ; } }", tokenizeAndStringify(code5,true)); } void bitfields7() { // ticket #1987 @@ -3766,7 +5757,7 @@ private: const char expected[] = "struct Descriptor { " "unsigned int element_size ; " "} ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code,false)); ASSERT_EQUALS("", errout.str()); } @@ -3781,7 +5772,7 @@ private: "{ " "int f ( ) ; " "} ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code,false)); ASSERT_EQUALS("", errout.str()); } @@ -3793,7 +5784,7 @@ private: " ;\n" " }\n" "};"; - tokenizeAndStringify(code); + tokenizeAndStringify(code,false); ASSERT_EQUALS("", errout.str()); } @@ -3802,20 +5793,20 @@ private: "MACRO " "default: { }" ";"; - ASSERT_EQUALS("{ } MACRO default : { } ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("{ } MACRO default : { } ;", tokenizeAndStringify(code,false)); } void bitfields12() { // ticket #3485 (segmentation fault) const char code[] = "{a:1;};\n"; - ASSERT_EQUALS("{ } ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("{ } ;", tokenizeAndStringify(code,false)); } void bitfields13() { // ticket #3502 (segmentation fault) - ASSERT_EQUALS("x y ;", tokenizeAndStringify("struct{x y:};\n")); + ASSERT_EQUALS("x y ;", tokenizeAndStringify("struct{x y:};\n",false)); } void bitfields14() { // #4561 - crash for 'signals:' - ASSERT_EQUALS("class x { protected: } ;", tokenizeAndStringify("class x { signals: };\n")); + ASSERT_EQUALS("class x { protected: } ;", tokenizeAndStringify("class x { signals: };\n",false)); } void bitfields15() { // #7747 - enum Foo {A,B}:4; @@ -3848,58 +5839,58 @@ private: const char *code, *expected; code = "map m;"; // namespace std is not used - ASSERT_EQUALS("map < foo , bar > m ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("map < foo , bar > m ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "map m;"; - ASSERT_EQUALS("std :: map < foo , bar > m ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("std :: map < foo , bar > m ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "string s;"; - ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "void foo() {swap(a, b); }"; - ASSERT_EQUALS("void foo ( ) { std :: swap ( a , b ) ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { std :: swap ( a , b ) ; }", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "void search() {}"; - ASSERT_EQUALS("void search ( ) { }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void search ( ) { }", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "void search();\n" "void dostuff() { search(); }"; - ASSERT_EQUALS("void search ( ) ;\nvoid dostuff ( ) { search ( ) ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void search ( ) ;\nvoid dostuff ( ) { search ( ) ; }", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "void foo() {map(a, b); }"; // That's obviously not std::map<> - ASSERT_EQUALS("void foo ( ) { map ( a , b ) ; }", tokenizeAndStringify(code)); + ASSERT_EQUALS("void foo ( ) { map ( a , b ) ; }", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "string s;"; // That's obviously not std::string - ASSERT_EQUALS("string < wchar_t > s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("string < wchar_t > s ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "swap s;"; // That's obviously not std::swap - ASSERT_EQUALS("swap s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("swap s ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "std::string s;"; - ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "tr1::function f;"; - ASSERT_EQUALS("tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", false)); - ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", true)); + ASSERT_EQUALS("tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, false, true, Settings::Native, "test.cpp", false)); + ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, false, true, Settings::Native, "test.cpp", true)); code = "std::tr1::function f;"; - ASSERT_EQUALS("std :: tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", false)); - ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", true)); + ASSERT_EQUALS("std :: tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, false, true, Settings::Native, "test.cpp", false)); + ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, false, true, Settings::Native, "test.cpp", true)); // #4042 (Do not add 'std ::' to variables) code = "using namespace std;\n" "const char * string = \"Hi\";"; - ASSERT_EQUALS("const char * string ; string = \"Hi\" ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("const char * string ; string = \"Hi\" ;", tokenizeAndStringify(code, false)); code = "using namespace std;\n" "string f(const char * string) {\n" @@ -3910,7 +5901,7 @@ private: "std :: cout << string << std :: endl ;\n" "return string ;\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, false)); code = "using namespace std;\n" "void f() {\n" @@ -3921,7 +5912,7 @@ private: "try { }\n" "catch ( std :: exception & exception ) { }\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, false)); // #5773 (Don't prepend 'std ::' to function definitions) code = "using namespace std;\n" @@ -3935,7 +5926,7 @@ private: "void search ( ) const { }\n" "void search ( ) { }\n" "} ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, false)); // Ticket #8091 ASSERT_EQUALS("enum Anonymous0 { string } ;", @@ -3967,72 +5958,72 @@ private: void microsoftMemory() { const char code1a[] = "void foo() { int a[10], b[10]; CopyMemory(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1a,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1a,false,true,Settings::Win32A)); const char code1b[] = "void foo() { int a[10], b[10]; RtlCopyMemory(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1b,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1b,false,true,Settings::Win32A)); const char code1c[] = "void foo() { int a[10], b[10]; RtlCopyBytes(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1c,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1c,false,true,Settings::Win32A)); const char code2a[] = "void foo() { int a[10]; FillMemory(a, sizeof(a), 255); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2a,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2a,false,true,Settings::Win32A)); const char code2b[] = "void foo() { int a[10]; RtlFillMemory(a, sizeof(a), 255); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2b,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2b,false,true,Settings::Win32A)); const char code2c[] = "void foo() { int a[10]; RtlFillBytes(a, sizeof(a), 255); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2c,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2c,false,true,Settings::Win32A)); const char code3a[] = "void foo() { int a[10], b[10]; MoveMemory(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3a,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3a,false,true,Settings::Win32A)); const char code3b[] = "void foo() { int a[10], b[10]; RtlMoveMemory(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3b,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3b,false,true,Settings::Win32A)); const char code4a[] = "void foo() { int a[10]; ZeroMemory(a, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4a,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4a,false,true,Settings::Win32A)); const char code4b[] = "void foo() { int a[10]; RtlZeroMemory(a, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4b,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4b,false,true,Settings::Win32A)); const char code4c[] = "void foo() { int a[10]; RtlZeroBytes(a, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4c,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4c,false,true,Settings::Win32A)); const char code4d[] = "void foo() { int a[10]; RtlSecureZeroMemory(a, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4d,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4d,false,true,Settings::Win32A)); const char code5[] = "void foo() { int a[10], b[10]; RtlCompareMemory(a, b, sizeof(a)); }"; - ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcmp ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code5,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcmp ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code5,false,true,Settings::Win32A)); const char code6[] = "void foo() { ZeroMemory(f(1, g(a, b)), h(i, j(0, 1))); }"; - ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 0 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code6,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 0 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code6,false,true,Settings::Win32A)); const char code7[] = "void foo() { FillMemory(f(1, g(a, b)), h(i, j(0, 1)), 255); }"; - ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 255 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code7,true,Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 255 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code7,false,true,Settings::Win32A)); } void microsoftString() { const char code1a[] = "void foo() { _tprintf (_T(\"test\") _T(\"1\")); }"; - ASSERT_EQUALS("void foo ( ) { printf ( \"test1\" ) ; }", tokenizeAndStringify(code1a, true, Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { printf ( \"test1\" ) ; }", tokenizeAndStringify(code1a, false, true, Settings::Win32A)); const char code1b[] = "void foo() { _tprintf (_TEXT(\"test\") _TEXT(\"2\")); }"; - ASSERT_EQUALS("void foo ( ) { printf ( \"test2\" ) ; }", tokenizeAndStringify(code1b, true, Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { printf ( \"test2\" ) ; }", tokenizeAndStringify(code1b, false, true, Settings::Win32A)); const char code1c[] = "void foo() { _tprintf (TEXT(\"test\") TEXT(\"3\")); }"; - ASSERT_EQUALS("void foo ( ) { printf ( \"test3\" ) ; }", tokenizeAndStringify(code1c, true, Settings::Win32A)); + ASSERT_EQUALS("void foo ( ) { printf ( \"test3\" ) ; }", tokenizeAndStringify(code1c, false, true, Settings::Win32A)); const char code2a[] = "void foo() { _tprintf (_T(\"test\") _T(\"1\")); }"; - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, true, Settings::Win32W)); - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, true, Settings::Win64)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, false, true, Settings::Win32W)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, false, true, Settings::Win64)); const char code2b[] = "void foo() { _tprintf (_TEXT(\"test\") _TEXT(\"2\")); }"; - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, true, Settings::Win32W)); - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, true, Settings::Win64)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, false, true, Settings::Win32W)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, false, true, Settings::Win64)); const char code2c[] = "void foo() { _tprintf (TEXT(\"test\") TEXT(\"3\")); }"; - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, true, Settings::Win32W)); - ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, true, Settings::Win64)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, false, true, Settings::Win32W)); + ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, false, true, Settings::Win64)); } void borland() { // __closure ASSERT_EQUALS("int ( * a ) ( ) ;", // TODO VarId - tokenizeAndStringify("int (__closure *a)();", true, Settings::Win32A)); + tokenizeAndStringify("int (__closure *a)();", false, true, Settings::Win32A)); // __property ASSERT_EQUALS("class Fred { ; __property ; } ;", - tokenizeAndStringify("class Fred { __property int x = { } };", true, Settings::Win32A)); + tokenizeAndStringify("class Fred { __property int x = { } };", false, true, Settings::Win32A)); } void simplifyQtSignalsSlots1() { @@ -4077,7 +6068,7 @@ private: "} " "}"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); const char code2[] = "class Counter : public QObject " "{ " @@ -4120,7 +6111,7 @@ private: "} " "}"; - ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); const char code3[] = "class MyObject : public QObject {" " MyObject() {}" @@ -4137,7 +6128,7 @@ private: "void test ( ) { } " "} ;"; - ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); + ASSERT_EQUALS(result3, tokenizeAndStringify(code3,false)); ASSERT_EQUALS("", errout.str()); const char code4[] = "class MyObject : public QObject {" @@ -4148,63 +6139,64 @@ private: "public: " "} ;"; - ASSERT_EQUALS(result4, tokenizeAndStringify(code4)); + ASSERT_EQUALS(result4, tokenizeAndStringify(code4,false)); } void simplifyQtSignalsSlots2() { const char code1[] = "class Foo::Bar: public QObject { private slots: };"; const char result1[] = "class Foo :: Bar : public QObject { private: } ;"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); } void simplifySQL() { // Oracle PRO*C extensions for inline SQL. Just replace the SQL with "asm()" to fix wrong error messages // ticket: #1959 - ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B;")); - ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL"), InternalError); + ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B;",false)); + ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL",false), InternalError); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1 ( A ) ; END ; END - __CPPCHECK_EMBEDDED_SQL_EXEC__\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ;", - tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;")); + tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;",false)); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = C\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ;", - tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = C; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;")); + tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = C; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;",false)); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1 ( A ) ; END ; END - __CPPCHECK_EMBEDDED_SQL_EXEC__\"\" ) ;", - tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__;")); + tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__;",false)); - ASSERT_THROW(tokenizeAndStringify("int f(){ __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL } int a;"), InternalError); - ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL int f(){"), InternalError); - ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL END-__CPPCHECK_EMBEDDED_SQL_EXEC__ int a;"), InternalError); - ASSERT_NO_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = :&b->b1, C = :c::c1;")); + ASSERT_THROW(tokenizeAndStringify("int f(){ __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL } int a;",false), InternalError); + ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL int f(){",false), InternalError); + ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL END-__CPPCHECK_EMBEDDED_SQL_EXEC__ int a;",false), InternalError); + ASSERT_NO_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = :&b->b1, C = :c::c1;",false)); } void simplifyCAlternativeTokens() { - ASSERT_EQUALS("void or ( ) ;", tokenizeAndStringify("void or(void);", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", true, Settings::Native, "test.cpp")); - ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void or ( ) ;", tokenizeAndStringify("void or(void);", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) const { if ( ! b ) { ; } }", tokenizeAndStringify("void f() const { if (not b); }", false, true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", false, true, Settings::Native, "test.cpp")); // #6201 - ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", false, true, Settings::Native, "test.cpp")); // #6029 - ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", false, true, Settings::Native, "test.cpp")); // #6207 - ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", true, Settings::Native, "test.c")); - ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", true, Settings::Native, "test.cpp")); + ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", false, true, Settings::Native, "test.cpp")); // #8029 - ASSERT_EQUALS("void f ( struct S * s ) { x = s . and + 1 ; }", tokenizeAndStringify("void f(struct S *s) { x = s->and + 1; }", true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( struct S * s ) { x = s . and + 1 ; }", tokenizeAndStringify("void f(struct S *s) { x = s->and + 1; }", false, true, Settings::Native, "test.c")); // #8745 ASSERT_EQUALS("void f ( ) { if ( x ) { or = 0 ; } }", tokenizeAndStringify("void f() { if (x) or = 0; }")); // #9324 @@ -4212,6 +6204,57 @@ private: tokenizeAndStringify("void f(const char *str) { while (*str=='!' or *str=='['){} }")); } + void simplifyCalculations() { + ASSERT_EQUALS("void foo ( char str [ ] ) { char x ; x = * str ; }", + tokenizeAndStringify("void foo ( char str [ ] ) { char x = 0 | ( * str ) ; }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (b + 0) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (0 + b) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (b - 0) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (b * 1) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (1 * b) { } }", true)); + //ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + // tokenizeAndStringify("void foo ( ) { if (b / 1) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (b | 0) { } }", true)); + ASSERT_EQUALS("void foo ( ) { if ( b ) { } }", + tokenizeAndStringify("void foo ( ) { if (0 | b) { } }", true)); + ASSERT_EQUALS("void foo ( int b ) { int a ; a = b ; bar ( a ) ; }", + tokenizeAndStringify("void foo ( int b ) { int a = b | 0 ; bar ( a ) ; }", true)); + ASSERT_EQUALS("void foo ( int b ) { int a ; a = b ; bar ( a ) ; }", + tokenizeAndStringify("void foo ( int b ) { int a = 0 | b ; bar ( a ) ; }", true)); + + // ticket #3093 + ASSERT_EQUALS("int f ( ) { return 15 ; }", + tokenizeAndStringify("int f() { int a = 10; int b = 5; return a + b; }", true)); + ASSERT_EQUALS("int f ( ) { return a ; }", + tokenizeAndStringify("int f() { return a * 1; }", true)); + ASSERT_EQUALS("int f ( int a ) { return 0 ; }", + tokenizeAndStringify("int f(int a) { return 0 * a; }", true)); + ASSERT_EQUALS("bool f ( int i ) { switch ( i ) { case 15 : ; return true ; } }", + tokenizeAndStringify("bool f(int i) { switch (i) { case 10 + 5: return true; } }", true)); + + // ticket #3576 - False positives in boolean expressions + ASSERT_EQUALS("int foo ( ) { return 1 ; }", + tokenizeAndStringify("int foo ( ) { int i; int j; i = 1 || j; return i; }", true)); + + ASSERT_EQUALS("int foo ( ) { return 0 ; }", + tokenizeAndStringify("int foo ( ) { int i; int j; i = 0 && j; return i; }", true)); // ticket #3576 - False positives in boolean expressions + + // ticket #3723 - Simplify condition (0 && a < 123) + ASSERT_EQUALS("( 0 ) ;", + tokenizeAndStringify("( 0 && a < 123 );", true)); + ASSERT_EQUALS("( 0 ) ;", + tokenizeAndStringify("( 0 && a[123] );", true)); + + // ticket #4931 + ASSERT_EQUALS("dostuff ( 1 ) ;", tokenizeAndStringify("dostuff(9&&8);", true)); + } + void simplifyRoundCurlyParentheses() { ASSERT_EQUALS("; x = 123 ;", tokenizeAndStringify(";x=({123;});")); ASSERT_EQUALS("; x = y ;", tokenizeAndStringify(";x=({y;});")); @@ -4231,7 +6274,7 @@ private: "operator ( ) ; " "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code, /*expand=*/true, /*platform=*/Settings::Native, "test.c")); + ASSERT_EQUALS(result, tokenizeAndStringify(code, /*simplify=*/false, /*expand=*/true, /*platform=*/Settings::Native, "test.c")); } void simplifyOperatorName2() { @@ -4247,7 +6290,7 @@ private: "operator= ( ) ; " "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); } void simplifyOperatorName3() { @@ -4256,69 +6299,69 @@ private: "static_cast(xResult.operator->())->GetMatrix();" "}"; const char result[] = "void f ( ) { static_cast < ScToken * > ( xResult . operator. ( ) ) . GetMatrix ( ) ; }"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); } void simplifyOperatorName4() { const char code[] = "void operator==() { }"; const char result[] = "void operator== ( ) { }"; - ASSERT_EQUALS(result, tokenizeAndStringify(code)); + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); } void simplifyOperatorName5() { const char code1[] = "std::istream & operator >> (std::istream & s, Fred &f);"; const char result1[] = "std :: istream & operator>> ( std :: istream & s , Fred & f ) ;"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); const char code2[] = "std::ostream & operator << (std::ostream & s, const Fred &f);"; const char result2[] = "std :: ostream & operator<< ( std :: ostream & s , const Fred & f ) ;"; - ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); } void simplifyOperatorName6() { // ticket #3195 const char code1[] = "value_type * operator ++ (int);"; const char result1[] = "value_type * operator++ ( int ) ;"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); const char code2[] = "value_type * operator -- (int);"; const char result2[] = "value_type * operator-- ( int ) ;"; - ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); } void simplifyOperatorName7() { // ticket #4619 const char code1[] = "value_type * operator += (int);"; const char result1[] = "value_type * operator+= ( int ) ;"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); } void simplifyOperatorName8() { // ticket #5706 const char code1[] = "value_type * operator += (int) noexcept ;"; const char result1[] = "value_type * operator+= ( int ) noexcept ( true ) ;"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); const char code2[] = "value_type * operator += (int) noexcept ( true ) ;"; const char result2[] = "value_type * operator+= ( int ) noexcept ( true ) ;"; - ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); const char code3[] = "value_type * operator += (int) throw ( ) ;"; const char result3[] = "value_type * operator+= ( int ) throw ( ) ;"; - ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); + ASSERT_EQUALS(result3, tokenizeAndStringify(code3,false)); const char code4[] = "value_type * operator += (int) const noexcept ;"; const char result4[] = "value_type * operator+= ( int ) const noexcept ;"; - ASSERT_EQUALS(result4, tokenizeAndStringify(code4)); + ASSERT_EQUALS(result4, tokenizeAndStringify(code4,false)); const char code5[] = "value_type * operator += (int) const noexcept ( true ) ;"; const char result5[] = "value_type * operator+= ( int ) const noexcept ( true ) ;"; - ASSERT_EQUALS(result5, tokenizeAndStringify(code5)); + ASSERT_EQUALS(result5, tokenizeAndStringify(code5,false)); const char code6[] = "value_type * operator += (int) const throw ( ) ;"; const char result6[] = "value_type * operator+= ( int ) const throw ( ) ;"; - ASSERT_EQUALS(result6, tokenizeAndStringify(code6)); + ASSERT_EQUALS(result6, tokenizeAndStringify(code6,false)); const char code7[] = "value_type * operator += (int) const noexcept ( false ) ;"; const char result7[] = "value_type * operator+= ( int ) const noexcept ( false ) ;"; - ASSERT_EQUALS(result7, tokenizeAndStringify(code7)); + ASSERT_EQUALS(result7, tokenizeAndStringify(code7,false)); } @@ -4632,6 +6675,15 @@ private: ASSERT_EQUALS("a = b = 0 ;", tokenizeAndStringify("a=b=0;")); } + void sizeOfCharLiteral() { // #7490 sizeof('a') should be 4 in C mode + std::stringstream expected; + expected << "unsigned long a ; a = " << settings1.sizeof_int << " ;"; + ASSERT_EQUALS(expected.str(), + tokenizeAndStringify("unsigned long a = sizeof('x');", true, true, Settings::Native, "test.c", false)); + ASSERT_EQUALS("unsigned long a ; a = 1 ;", + tokenizeAndStringify("unsigned long a = sizeof('x');", true, true, Settings::Native, "test.cpp", true)); + } + void platformWin() { const char code[] = "BOOL f;" "BOOLEAN g;" @@ -4796,14 +6848,29 @@ private: "float * ptrToFloat ;"; // These types should be defined the same on all Windows platforms - const std::string win32A = tokenizeAndStringifyWindows(code, true, Settings::Win32A); + const std::string win32A = tokenizeAndStringifyWindows(code, true, true, Settings::Win32A); ASSERT_EQUALS(expected, win32A); - ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); - ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, Settings::Win64)); + ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, true, Settings::Win32W)); + ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, true, Settings::Win64)); } void platformWin32() { - const char code[] = "size_t a;" + const char code[] = "unsigned int sizeof_short = sizeof(short);" + "unsigned int sizeof_unsigned_short = sizeof(unsigned short);" + "unsigned int sizeof_int = sizeof(int);" + "unsigned int sizeof_unsigned_int = sizeof(unsigned int);" + "unsigned int sizeof_long = sizeof(long);" + "unsigned int sizeof_unsigned_long = sizeof(unsigned long);" + "unsigned int sizeof_long_long = sizeof(long long);" + "unsigned int sizeof_unsigned_long_long = sizeof(unsigned long long);" + "unsigned int sizeof_float = sizeof(float);" + "unsigned int sizeof_double = sizeof(double);" + "unsigned int sizeof_long_double = sizeof(long double);" + "unsigned int sizeof_bool = sizeof(bool);" + "unsigned int sizeof_wchar_t = sizeof(wchar_t);" + "unsigned int sizeof_pointer = sizeof(void *);" + "unsigned int sizeof_size_t = sizeof(size_t);" + "size_t a;" "ssize_t b;" "ptrdiff_t c;" "intptr_t d;" @@ -4821,7 +6888,22 @@ private: "HALF_PTR half_ptr;" "INT_PTR int_ptr;"; - const char expected[] = "unsigned long a ; " + const char expected[] = "unsigned int sizeof_short ; sizeof_short = 2 ; " + "unsigned int sizeof_unsigned_short ; sizeof_unsigned_short = 2 ; " + "unsigned int sizeof_int ; sizeof_int = 4 ; " + "unsigned int sizeof_unsigned_int ; sizeof_unsigned_int = 4 ; " + "unsigned int sizeof_long ; sizeof_long = 4 ; " + "unsigned int sizeof_unsigned_long ; sizeof_unsigned_long = 4 ; " + "unsigned int sizeof_long_long ; sizeof_long_long = 8 ; " + "unsigned int sizeof_unsigned_long_long ; sizeof_unsigned_long_long = 8 ; " + "unsigned int sizeof_float ; sizeof_float = 4 ; " + "unsigned int sizeof_double ; sizeof_double = 8 ; " + "unsigned int sizeof_long_double ; sizeof_long_double = 8 ; " + "unsigned int sizeof_bool ; sizeof_bool = 1 ; " + "unsigned int sizeof_wchar_t ; sizeof_wchar_t = 2 ; " + "unsigned int sizeof_pointer ; sizeof_pointer = 4 ; " + "unsigned int sizeof_size_t ; sizeof_size_t = 4 ; " + "unsigned long a ; " "long b ; " "long c ; " "long d ; " @@ -4840,9 +6922,9 @@ private: "int int_ptr ;"; // These types should be defined the same on all Win32 platforms - std::string win32A = tokenizeAndStringifyWindows(code, true, Settings::Win32A); + std::string win32A = tokenizeAndStringifyWindows(code, true, true, Settings::Win32A); ASSERT_EQUALS(expected, win32A); - ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); + ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, true, Settings::Win32W)); } void platformWin32A() { @@ -4888,7 +6970,7 @@ private: "sscanf ( dst , \"%s\" , dst ) ; " "} " "unsigned char tbyte ;"; - ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32A)); + ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, false, true, Settings::Win32A)); } void platformWin32W() { @@ -4934,11 +7016,26 @@ private: "wscanf ( L\"%s\" , dst ) ; " "swscanf ( dst , L\"%s\" , dst ) ; " "}"; - ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); + ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, false, true, Settings::Win32W)); } void platformWin64() { - const char code[] = "size_t a;" + const char code[] = "unsigned int sizeof_short = sizeof(short);" + "unsigned int sizeof_unsigned_short = sizeof(unsigned short);" + "unsigned int sizeof_int = sizeof(int);" + "unsigned int sizeof_unsigned_int = sizeof(unsigned int);" + "unsigned int sizeof_long = sizeof(long);" + "unsigned int sizeof_unsigned_long = sizeof(unsigned long);" + "unsigned int sizeof_long_long = sizeof(long long);" + "unsigned int sizeof_unsigned_long_long = sizeof(unsigned long long);" + "unsigned int sizeof_float = sizeof(float);" + "unsigned int sizeof_double = sizeof(double);" + "unsigned int sizeof_long_double = sizeof(long double);" + "unsigned int sizeof_bool = sizeof(bool);" + "unsigned int sizeof_wchar_t = sizeof(wchar_t);" + "unsigned int sizeof_pointer = sizeof(void *);" + "unsigned int sizeof_size_t = sizeof(size_t);" + "size_t a;" "ssize_t b;" "ptrdiff_t c;" "intptr_t d;" @@ -4956,7 +7053,22 @@ private: "HALF_PTR half_ptr;" "INT_PTR int_ptr;"; - const char expected[] = "unsigned long long a ; " + const char expected[] = "unsigned int sizeof_short ; sizeof_short = 2 ; " + "unsigned int sizeof_unsigned_short ; sizeof_unsigned_short = 2 ; " + "unsigned int sizeof_int ; sizeof_int = 4 ; " + "unsigned int sizeof_unsigned_int ; sizeof_unsigned_int = 4 ; " + "unsigned int sizeof_long ; sizeof_long = 4 ; " + "unsigned int sizeof_unsigned_long ; sizeof_unsigned_long = 4 ; " + "unsigned int sizeof_long_long ; sizeof_long_long = 8 ; " + "unsigned int sizeof_unsigned_long_long ; sizeof_unsigned_long_long = 8 ; " + "unsigned int sizeof_float ; sizeof_float = 4 ; " + "unsigned int sizeof_double ; sizeof_double = 8 ; " + "unsigned int sizeof_long_double ; sizeof_long_double = 8 ; " + "unsigned int sizeof_bool ; sizeof_bool = 1 ; " + "unsigned int sizeof_wchar_t ; sizeof_wchar_t = 2 ; " + "unsigned int sizeof_pointer ; sizeof_pointer = 8 ; " + "unsigned int sizeof_size_t ; sizeof_size_t = 8 ; " + "unsigned long long a ; " "long long b ; " "long long c ; " "long long d ; " @@ -4974,61 +7086,121 @@ private: "int half_ptr ; " "long long int_ptr ;"; - ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win64)); + ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, true, Settings::Win64)); } void platformUnix32() { - const char code[] = "size_t a;" + const char code[] = "unsigned int sizeof_short = sizeof(short);" + "unsigned int sizeof_unsigned_short = sizeof(unsigned short);" + "unsigned int sizeof_int = sizeof(int);" + "unsigned int sizeof_unsigned_int = sizeof(unsigned int);" + "unsigned int sizeof_long = sizeof(long);" + "unsigned int sizeof_unsigned_long = sizeof(unsigned long);" + "unsigned int sizeof_long_long = sizeof(long long);" + "unsigned int sizeof_unsigned_long_long = sizeof(unsigned long long);" + "unsigned int sizeof_float = sizeof(float);" + "unsigned int sizeof_double = sizeof(double);" + "unsigned int sizeof_long_double = sizeof(long double);" + "unsigned int sizeof_bool = sizeof(bool);" + "unsigned int sizeof_wchar_t = sizeof(wchar_t);" + "unsigned int sizeof_pointer = sizeof(void *);" + "unsigned int sizeof_size_t = sizeof(size_t);" + "size_t a;" "ssize_t b;" "ptrdiff_t c;" "intptr_t d;" "uintptr_t e;"; - const char expected[] = "unsigned long a ; " + const char expected[] = "unsigned int sizeof_short ; sizeof_short = 2 ; " + "unsigned int sizeof_unsigned_short ; sizeof_unsigned_short = 2 ; " + "unsigned int sizeof_int ; sizeof_int = 4 ; " + "unsigned int sizeof_unsigned_int ; sizeof_unsigned_int = 4 ; " + "unsigned int sizeof_long ; sizeof_long = 4 ; " + "unsigned int sizeof_unsigned_long ; sizeof_unsigned_long = 4 ; " + "unsigned int sizeof_long_long ; sizeof_long_long = 8 ; " + "unsigned int sizeof_unsigned_long_long ; sizeof_unsigned_long_long = 8 ; " + "unsigned int sizeof_float ; sizeof_float = 4 ; " + "unsigned int sizeof_double ; sizeof_double = 8 ; " + "unsigned int sizeof_long_double ; sizeof_long_double = 12 ; " + "unsigned int sizeof_bool ; sizeof_bool = 1 ; " + "unsigned int sizeof_wchar_t ; sizeof_wchar_t = 4 ; " + "unsigned int sizeof_pointer ; sizeof_pointer = 4 ; " + "unsigned int sizeof_size_t ; sizeof_size_t = 4 ; " + "unsigned long a ; " "long b ; " "long c ; " "long d ; " "unsigned long e ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Settings::Unix32)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Unix32)); } void platformUnix64() { - const char code[] = "size_t a;" + const char code[] = "unsigned int sizeof_short = sizeof(short);" + "unsigned int sizeof_unsigned_short = sizeof(unsigned short);" + "unsigned int sizeof_int = sizeof(int);" + "unsigned int sizeof_unsigned_int = sizeof(unsigned int);" + "unsigned int sizeof_long = sizeof(long);" + "unsigned int sizeof_unsigned_long = sizeof(unsigned long);" + "unsigned int sizeof_long_long = sizeof(long long);" + "unsigned int sizeof_unsigned_long_long = sizeof(unsigned long long);" + "unsigned int sizeof_float = sizeof(float);" + "unsigned int sizeof_double = sizeof(double);" + "unsigned int sizeof_long_double = sizeof(long double);" + "unsigned int sizeof_bool = sizeof(bool);" + "unsigned int sizeof_wchar_t = sizeof(wchar_t);" + "unsigned int sizeof_pointer = sizeof(void *);" + "unsigned int sizeof_size_t = sizeof(size_t);" + "size_t a;" "ssize_t b;" "ptrdiff_t c;" "intptr_t d;" "uintptr_t e;"; - const char expected[] = "unsigned long a ; " + const char expected[] = "unsigned int sizeof_short ; sizeof_short = 2 ; " + "unsigned int sizeof_unsigned_short ; sizeof_unsigned_short = 2 ; " + "unsigned int sizeof_int ; sizeof_int = 4 ; " + "unsigned int sizeof_unsigned_int ; sizeof_unsigned_int = 4 ; " + "unsigned int sizeof_long ; sizeof_long = 8 ; " + "unsigned int sizeof_unsigned_long ; sizeof_unsigned_long = 8 ; " + "unsigned int sizeof_long_long ; sizeof_long_long = 8 ; " + "unsigned int sizeof_unsigned_long_long ; sizeof_unsigned_long_long = 8 ; " + "unsigned int sizeof_float ; sizeof_float = 4 ; " + "unsigned int sizeof_double ; sizeof_double = 8 ; " + "unsigned int sizeof_long_double ; sizeof_long_double = 16 ; " + "unsigned int sizeof_bool ; sizeof_bool = 1 ; " + "unsigned int sizeof_wchar_t ; sizeof_wchar_t = 4 ; " + "unsigned int sizeof_pointer ; sizeof_pointer = 8 ; " + "unsigned int sizeof_size_t ; sizeof_size_t = 8 ; " + "unsigned long a ; " "long b ; " "long c ; " "long d ; " "unsigned long e ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Settings::Unix64)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Unix64)); } void platformWin32AStringCat() { //#5150 const char code[] = "TCHAR text[] = _T(\"123\") _T(\"456\") _T(\"789\");"; const char expected[] = "char text [ 10 ] = \"123456789\" ;"; - ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32A)); + ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, true, Settings::Win32A)); } void platformWin32WStringCat() { //#5150 const char code[] = "TCHAR text[] = _T(\"123\") _T(\"456\") _T(\"789\");"; const char expected[] = "wchar_t text [ 10 ] = L\"123456789\" ;"; - ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); + ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, true, Settings::Win32W)); } void platformWinWithNamespace() { const char code1[] = "UINT32 a; ::UINT32 b; foo::UINT32 c;"; const char expected1[] = "unsigned int a ; unsigned int b ; foo :: UINT32 c ;"; - ASSERT_EQUALS(expected1, tokenizeAndStringifyWindows(code1, true, Settings::Win32A)); + ASSERT_EQUALS(expected1, tokenizeAndStringifyWindows(code1, true, true, Settings::Win32A)); const char code2[] = "LPCVOID a; ::LPCVOID b; foo::LPCVOID c;"; const char expected2[] = "const void * a ; const void * b ; foo :: LPCVOID c ;"; - ASSERT_EQUALS(expected2, tokenizeAndStringifyWindows(code2, true, Settings::Win32A)); + ASSERT_EQUALS(expected2, tokenizeAndStringifyWindows(code2, true, true, Settings::Win32A)); } void isZeroNumber() const { @@ -5084,7 +7256,7 @@ private: void simplifyStaticConst() { const char code1[] = "class foo { public: bool const static c ; }"; const char expected1[] = "class foo { public: static const bool c ; }"; - ASSERT_EQUALS(expected1, tokenizeAndStringify(code1)); + ASSERT_EQUALS(expected1, tokenizeAndStringify(code1, true)); const char code2[] = "int long long f()\n" @@ -5134,52 +7306,52 @@ private: "return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12\n" "+ i13 + i14 + i15 + i16 + i17 + i18 ;\n" "}"; - ASSERT_EQUALS(expected2, tokenizeAndStringify(code2)); + ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true)); const char code3[] = "const unsigned long extern int i;"; const char expected3[] = "extern const unsigned long i ;"; - ASSERT_EQUALS(expected3, tokenizeAndStringify(code3)); + ASSERT_EQUALS(expected3, tokenizeAndStringify(code3, true)); } void simplifyCPPAttribute() { ASSERT_EQUALS("int f ( ) ;", - tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("[ [ deprecated ] ] int f ( ) ;", - tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.cpp", false)); + tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("[ [ deprecated ] ] int f ( ) ;", - tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.c", true)); + tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Native, "test.c", true)); ASSERT_EQUALS("template < class T > int f ( ) { }", - tokenizeAndStringify("template [[noreturn]] int f(){}", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("template [[noreturn]] int f(){}", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("int f ( int i ) ;", - tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("[ [ maybe_unused ] ] int f ( [ [ maybe_unused ] ] int i ) ;", - tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", true, Settings::Native, "test.cpp", false)); + tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", false, true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[,]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[deprecated,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[deprecated,]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[,,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[,,]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[deprecated,,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[deprecated,,]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[deprecated,maybe_unused,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[deprecated,maybe_unused,]] a;", false, true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", - tokenizeAndStringify("struct [[,,,]] a;", true, Settings::Native, "test.cpp", true)); + tokenizeAndStringify("struct [[,,,]] a;", false, true, Settings::Native, "test.cpp", true)); } void simplifyCaseRange() { @@ -5432,6 +7604,7 @@ private: "}\n"; // Ensure that the AST is validated for the simplified token list TODO_ASSERT_THROW(tokenizeAndStringify(code), InternalError); // this should not crash/hang + ASSERT_THROW(tokenizeAndStringify(code,true), InternalError); // when parentheses are simplified the AST will be wrong } void astnewdelete() { @@ -5834,7 +8007,7 @@ private: ASSERT_EQUALS("class Fred { } ;", tokenizeAndStringify("class DLLEXPORT Fred { } ;")); ASSERT_EQUALS("class Fred : Base { } ;", tokenizeAndStringify("class Fred FINAL : Base { } ;")); // Regression for C code: - ASSERT_EQUALS("struct Fred { } ;", tokenizeAndStringify("struct DLLEXPORT Fred { } ;", true, Settings::Native, "test.c")); + ASSERT_EQUALS("struct Fred { } ;", tokenizeAndStringify("struct DLLEXPORT Fred { } ;", false, true, Settings::Native, "test.c")); } void sizeofAddParentheses() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 71b4c71c0..9fe544132 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1456,8 +1456,7 @@ private: "}\n"); ASSERT_EQUALS_WITHOUT_LINENUMBERS( "[test.cpp:2]: (debug) valueflow.cpp:1035:valueFlowReverse bailout: assignment of abc\n" - "[test.cpp:8]: (debug) valueflow.cpp:1131:valueFlowReverse bailout: variable abc stopping on goto label\n" - "[test.cpp:2]: (debug) Unknown type 'ABC'.\n", + "[test.cpp:8]: (debug) valueflow.cpp:1131:valueFlowReverse bailout: variable abc stopping on goto label\n", errout.str()); }