/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2019 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "platform.h"
#include "settings.h"
#include "testsuite.h"
#include "token.h"
#include "tokenize.h"
#include "tokenlist.h"
#include
#include
class TestSimplifyTokens : public TestFixture {
public:
TestSimplifyTokens() : TestFixture("TestSimplifyTokens") {
}
private:
Settings settings0;
Settings settings1;
Settings settings_std;
Settings settings_windows;
void run() OVERRIDE {
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);
TEST_CASE(combine_Ustrings);
TEST_CASE(combine_u8strings);
TEST_CASE(combine_mixedstrings);
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);
// Simplify "and" to "&&" (#620)
TEST_CASE(and1);
// Simplify "or" to "||"
TEST_CASE(or1);
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(while1);
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
TEST_CASE(simplifyStructDecl3);
TEST_CASE(simplifyStructDecl4);
TEST_CASE(simplifyStructDecl6); // ticket #3732
TEST_CASE(simplifyStructDecl7); // ticket #476 (static anonymous struct array)
TEST_CASE(simplifyStructDecl8); // ticket #7698
// register int var; => int var;
// inline int foo() {} => int foo() {}
TEST_CASE(removeUnwantedKeywords);
// remove calling convention __cdecl, __stdcall, ...
TEST_CASE(simplifyCallingConvention);
TEST_CASE(simplifyFunctorCall);
TEST_CASE(simplifyFunctionPointer); // ticket #5339 (simplify function pointer after comma)
TEST_CASE(redundant_semicolon);
TEST_CASE(simplifyFunctionReturn);
// 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 "(str + num)"
TEST_CASE(simplifyCharAt);
TEST_CASE(simplifyOverride); // ticket #5069
TEST_CASE(simplifyNestedNamespace);
TEST_CASE(simplifyNamespaceAliases);
}
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) {
errout.str("");
settings0.platform(type);
Tokenizer tokenizer(&settings0, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
if (simplify)
tokenizer.simplifyTokenList2();
return tokenizer.tokens()->stringifyList(nullptr, !simplify);
}
std::string tokWithWindows(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) {
errout.str("");
settings_windows.platform(type);
Tokenizer tokenizer(&settings_windows, this);
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[], 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);
}
std::string tokWithNewlines(const char code[]) {
errout.str("");
Tokenizer tokenizer(&settings0, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.simplifyTokenList2();
return tokenizer.tokens()->stringifyList(false, false, false, true, false);
}
std::string tokWithStdLib(const char code[]) {
errout.str("");
Tokenizer tokenizer(&settings_std, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.simplifyTokenList2();
return tokenizer.tokens()->stringifyList(nullptr, false);
}
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