/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2018 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);
// 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(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
TEST_CASE(combine_wstrings);
TEST_CASE(combine_ustrings);
// 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(0, !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(0, !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(0, 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(0, 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 simplifyAssignmentInFunctionCall() {
ASSERT_EQUALS("; x = g ( ) ; f ( x ) ;", tok(";f(x=g());"));
ASSERT_EQUALS("; hs = ( xyz_t ) { h . centerX , h . centerY , 1 + index } ; putInput ( hs , 1 ) ;", tok(";putInput(hs = (xyz_t) { h->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;"));
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;}"));
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;};"));
}
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"
"{\n"
"const char *a =\n"
"{\n"
"\"hello \"\n"
"\"world\"\n"
"};\n"
"}\n";
const char code2[] = "void foo()\n"
"{\n"
"const char *a =\n"
"{\n"
"\"hello world\"\n"
"};\n"
"}\n";
ASSERT_EQUALS(tok(code2), tok(code1));
}
void combine_wstrings() {
const char code[] = "a = L\"hello \" L\"world\" ;\n";
const char expected[] = "a = \"hello world\" ;";
Tokenizer tokenizer(&settings0, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(0, false));
ASSERT_EQUALS(true, tokenizer.tokens()->tokAt(2)->isLong());
}
void combine_ustrings() {
const char code[] = "abc = u\"abc\";";
const char expected[] = "abc = \"abc\" ;";
Tokenizer tokenizer(&settings0, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(0, false));
ASSERT_EQUALS(true, tokenizer.tokens()->tokAt(2)->isLong());
}
void double_plus() {
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a++;\n"
"a--;\n"
"++a;\n"
"--a;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a ++ ; a -- ; ++ a ; -- a ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a+a;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a + a ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a+++b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a ++ + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a---b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a -- - b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a--+b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a -- + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a++-b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a ++ - b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a+--b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a + -- b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a-++b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a - ++ b ; }", tok(code1));
}
}
void redundant_plus() {
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a + + b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a + + + b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a + - b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a - + b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a - - b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a - + - b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1));
}
{
const char code1[] = "void foo( int a, int b )\n"
"{\n"
"a=a - - - b;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1));
}
}
void redundant_plus_numbers() {
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a + + 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a + + + 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a + - 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a - + 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a - - 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a - + - 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1));
}
{
const char code1[] = "void foo( int a )\n"
"{\n"
"a=a - - - 1;\n"
"}\n";
ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1));
}
}
void parentheses1() {
ASSERT_EQUALS("a = 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));
}
void declareArray() {
const char code1[] = "void f ( ) { char str [ ] = \"100\" ; }";
const char expected1[] = "void f ( ) { char str [ 4 ] = \"100\" ; }";
ASSERT_EQUALS(expected1, tok(code1));
const char code2[] = "char str [ ] = \"\\x00\";";
const char expected2[] = "char str [ 2 ] = \"\\0\" ;";
ASSERT_EQUALS(expected2, tok(code2));
const char code3[] = "char str [ ] = \"\\0\";";
const char expected3[] = "char str [ 2 ] = \"\\0\" ;";
ASSERT_EQUALS(expected3, tok(code3));
const char code4[] = "char str [ ] = \"\\n\\n\";";
const char expected4[] = "char str [ 3 ] = \"\\n\\n\" ;";
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[] = "else if(ab) { cd } else { ef }gh;";
ASSERT_EQUALS("\n\n##file 0\n1: else { if ( ab ) { cd } else { ef } } gh ;\n", tokenizeDebugListing(code));
// syntax error: assert there is no segmentation fault
ASSERT_EQUALS("\n\n##file 0\n1: else if ( x ) { }\n", tokenizeDebugListing("else if (x) { }"));
{
const char src[] = "void f(int g,int f) {\n"
"if(g==1) {poo();}\n"
"else if( g == 2 )\n"
"{\n"
" if( f == 0 ){coo();}\n"
" else if( f==1)\n"
" goo();\n"
"}\n"
"}";
const char expected[] = "void f ( int g , int f ) "
"{ "
"if ( g == 1 ) { poo ( ) ; } "
"else { "
"if ( g == 2 ) "
"{ "
"if ( f == 0 ) { coo ( ) ; } "
"else { "
"if ( f == 1 ) "
"{ "
"goo ( ) ; "
"} "
"} "
"} "
"} "
"}";
ASSERT_EQUALS(tok(expected), tok(src));
}
// Ticket #6860 - lambdas
{
const char src[] = "( []{if (ab) {cd}else if(ef) { gh } else { ij }kl}() );";
const char expected[] = "\n\n##file 0\n1: ( [ ] { if ( ab ) { cd } else { if ( ef ) { gh } else { ij } } kl } ( ) ) ;\n";
ASSERT_EQUALS(expected, tokenizeDebugListing(src));
}
{
const char src[] = "[ []{if (ab) {cd}else if(ef) { gh } else { ij }kl}() ];";
const char expected[] = "\n\n##file 0\n1: [ [ ] { if ( ab ) { cd } else { if ( ef ) { gh } else { ij } } kl } ( ) ] ;\n";
ASSERT_EQUALS(expected, tokenizeDebugListing(src));
}
{
const char src[] = "= { []{if (ab) {cd}else if(ef) { gh } else { ij }kl}() }";
const char expected[] = "\n\n##file 0\n1: = { [ ] { if ( ab ) { cd } else { if ( ef ) { gh } else { ij } } kl } ( ) }\n";
ASSERT_EQUALS(expected, tokenizeDebugListing(src));
}
}
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