void deallocuse2() { check("void f(char *p) {\n" " free(p);\n" " strcpy(a, p);\n" "}"); TODO_ASSERT_EQUALS("error (free,use)", "[test.c:3]: (information) --check-library: Function strcpy() should have <noreturn> configuration\n", errout.str()); check("void f(char *p) {\n" // #3041 - assigning pointer when it's used " free(p);\n" " strcpy(a, p=b());\n" "}"); TODO_ASSERT_EQUALS("", "[test.c:3]: (information) --check-library: Function strcpy() should have <noreturn> configuration\n", errout.str()); }
void heapDoubleFree() { check("void f() {" " HANDLE MyHeap = HeapCreate(0, 0, 0);" " int *a = HeapAlloc(MyHeap, 0, sizeof(int));" " int *b = HeapAlloc(MyHeap, 0, sizeof(int));" " HeapFree(MyHeap, 0, a);" " HeapFree(MyHeap, 0, b);" " HeapDestroy(MyHeap);" "}"); TODO_ASSERT_EQUALS("", "[test.c:1]: (error) Mismatching allocation and deallocation: MyHeap\n" "[test.c:1]: (error) Resource handle 'MyHeap' freed twice.\n", errout.str()); check("void f() {" " int *a = HeapAlloc(GetProcessHeap(), 0, sizeof(int));" " int *b = HeapAlloc(GetProcessHeap(), 0, sizeof(int));" " HeapFree(GetProcessHeap(), 0, a);" " HeapFree(GetProcessHeap(), 0, b);" "}"); ASSERT_EQUALS("", errout.str()); check("void f() {" " HANDLE MyHeap = HeapCreate(0, 0, 0);" " int *a = HeapAlloc(MyHeap, 0, sizeof(int));" " int *b = HeapAlloc(MyHeap, 0, sizeof(int));" " HeapFree(MyHeap, 0, a);" " HeapDestroy(MyHeap);" "}"); TODO_ASSERT_EQUALS("[test.c:1] (error) Memory leak: b", "[test.c:1]: (error) Mismatching allocation and deallocation: MyHeap\n" "[test.c:1]: (error) Memory leak: b\n", errout.str()); check("void f() {" " HANDLE MyHeap = HeapCreate(0, 0, 0);" " int *a = HeapAlloc(MyHeap, 0, sizeof(int));" " int *b = HeapAlloc(MyHeap, 0, sizeof(int));" " HeapFree(MyHeap, 0, a);" " HeapFree(MyHeap, 0, b);" "}"); TODO_ASSERT_EQUALS("[test.c:1] (error) Resource leak: MyHeap", "[test.c:1]: (error) Mismatching allocation and deallocation: MyHeap\n", errout.str()); check("void f() {" " HANDLE MyHeap = HeapCreate(0, 0, 0);" " int *a = HeapAlloc(MyHeap, 0, sizeof(int));" " int *b = HeapAlloc(MyHeap, 0, sizeof(int));" " HeapFree(MyHeap, 0, a);" "}"); TODO_ASSERT_EQUALS("[test.c:1] (error) Resource leak: MyHeap\n[test.c:1] (error) Memory leak: b", "[test.c:1]: (error) Mismatching allocation and deallocation: MyHeap\n[test.c:1]: (error) Memory leak: b\n", errout.str()); }
void structmember() { check("struct Foo { int *p };\n" "void f(struct Foo *foo) {\n" " int i = foo->p;\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an address value to the integer (int/long/etc) type is not portable\n", "", errout.str()); }
void ptrarithmetic() { // #3073 check("void foo(int *p) {\n" " int x = 10;\n" " int *a = p + x;\n" "}\n"); ASSERT_EQUALS("", errout.str()); check("void foo(int *p) {\n" " int x = 10;\n" " int *a = x + p;\n" "}\n"); ASSERT_EQUALS("", errout.str()); check("void foo(int *p) {\n" " int x = 10;\n" " int *a = x * x;\n" "}\n"); TODO_ASSERT_EQUALS("error", "", errout.str()); check("void foo(int *start, int *end) {\n" " int len;\n" " int len = end + 10 - start;\n" "}\n"); ASSERT_EQUALS("", errout.str()); }
void division8() { check("void foo(int b)\n" "{\n" " if (b > 0)\n" " {\n" " unsigned int a;\n" " unsigned int c = a / b;\n" " }\n" "}", true); ASSERT_EQUALS("", errout.str()); check("void foo(int b)\n" "{\n" " if (b < 0)\n" " {\n" " unsigned int a;\n" " unsigned int c = a / b;\n" " }\n" "}", true); TODO_ASSERT_EQUALS("[test.cpp:6]: (warning) Division with signed and unsigned operators. The result might be wrong.\n", "", errout.str()); check("void a(int i) { }\n" "int foo( unsigned int sz )\n" "{\n" " register unsigned int i=1;\n" " return i/sz;\n" "}", true); ASSERT_EQUALS("", errout.str()); }
void structmember() { check("struct Foo { int *p };\n" "void f(struct Foo *foo) {\n" " int i = foo->p;\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning a pointer to an integer is not portable.\n", "", errout.str()); }
void deallocuse2() { check("void f(char *p) {\n" " free(p);\n" " strcpy(a, p);\n" "}"); TODO_ASSERT_EQUALS("error", "", errout.str()); check("void f(char *p) {\n" // #3041 - assigning pointer when it's used " free(p);\n" " strcpy(a, p=b());\n" "}"); ASSERT_EQUALS("", errout.str()); }
void testvolatile() { check("\n" "#include <iostream>\n" "class K {};\n" "int main(int argc, char *argv[])\n" "{\n" " volatile K k(0);\n" " std::cout << k << std::endl;\n" " k++;\n" " std::cout << k << std::endl;\n" " return 0;\n" "}\n"); TODO_ASSERT_EQUALS("", "[test.cpp:8]: (performance) Prefer prefix ++/-- operators for non-primitive types.\n", errout.str()); }
void throw1() { // 3987 - Execution reach a 'throw' check("void f() {\n" " char *p = malloc(10);\n" " throw 123;\n" "}"); TODO_ASSERT_EQUALS("error", "", errout.str()); check("void f() {\n" " char *p;\n" " try {\n" " p = malloc(10);\n" " throw 123;\n" " } catch (...) { }\n" " free(p);\n" "}"); ASSERT_EQUALS("", errout.str()); }
void destructors() { check("class x {\n" " ~x() {\n" " throw e;\n" " }\n" "};"); ASSERT_EQUALS("[test.cpp:3]: (warning) Class x is not safe, destructor throws exception\n", errout.str()); check("class x {\n" " ~x();\n" "};\n" "x::~x() {\n" " throw e;\n" "}"); ASSERT_EQUALS("[test.cpp:5]: (warning) Class x is not safe, destructor throws exception\n", errout.str()); check("x::~x() {\n" " throw e;\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:3]: (warning) Class x is not safe, destructor throws exception\n", "", errout.str()); // #3858 - throwing exception in try block in destructor. check("class x {\n" " ~x() {\n" " try {\n" " throw e;\n" " } catch (...) {\n" " }\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); check("class x {\n" " ~x() {\n" " if(!std::uncaught_exception()) {\n" " throw e;\n" " }\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); }
void fp_operator() { // #2407 - FP when function is called from operator() check("class Fred\n" "{\n" "public:\n" " void operator()(int x) {\n" " startListening();\n" " }\n" "\n" "private:\n" " void startListening() {\n" " }\n" "};"); ASSERT_EQUALS("", errout.str()); check("class Fred\n" "{\n" "public:\n" " void operator()(int x) {\n" " }\n" "\n" "private:\n" " void startListening() {\n" " }\n" "};"); ASSERT_EQUALS("[test.cpp:8]: (style) Unused private function: 'Fred::startListening'\n", errout.str()); // #5059 check("class Fred {\n" " void* operator new(size_t obj_size, size_t buf_size) {}\n" "};"); TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Unused private function: 'Fred::operatornew'\n", "", errout.str()); // No message for operators - we currently cannot check their usage check("class Fred {\n" " void* operator new(size_t obj_size, size_t buf_size) {}\n" "public:\n" " void* foo() { return new(size) Fred(); }\n" "};"); ASSERT_EQUALS("", errout.str()); }
void checkPointerSizeofStruct() { check("void f() {\n" " struct foo *ptr;\n" " memset( ptr->bar, 0, sizeof ptr->bar );\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f() {\n" " struct foo {\n" " char bar[10];\n" " };\n" " memset( ptr->bar, 0, sizeof ptr->bar );\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f() {\n" " struct foo {\n" " char *bar;\n" " };\n" " memset( ptr->bar, 0, sizeof ptr->bar );\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:5]: (warning) Size of pointer 'bar' used instead of size of its data.\n", "", errout.str()); }
void test1() { check("class Fred\n" "{\n" "private:\n" " unsigned int f();\n" "public:\n" " Fred();\n" "};\n" "\n" "Fred::Fred()\n" "{ }\n" "\n" "unsigned int Fred::f()\n" "{ }\n"); ASSERT_EQUALS("[test.cpp:4]: (style) Unused private function 'Fred::f'\n", errout.str()); check("#file \"p.h\"\n" "class Fred\n" "{\n" "private:\n" " unsigned int f();\n" "public:\n" " Fred();\n" "};\n" "\n" "#endfile\n" "Fred::Fred()\n" "{ }\n" "\n" "unsigned int Fred::f()\n" "{ }\n"); TODO_ASSERT_EQUALS("[p.h:4]: (style) Unused private function 'Fred::f'\n", errout.str()); check("#file \"p.h\"\n" "class Fred\n" "{\n" "private:\n" "void f();\n" "};\n" "\n" "\n" "#endfile\n" "\n" "void Fred::f()\n" "{\n" "}\n" "\n"); TODO_ASSERT_EQUALS("[p.h:4]: (style) Unused private function 'Fred::f'\n", errout.str()); // Don't warn about include files which implementation we don't see check("#file \"p.h\"\n" "class Fred\n" "{\n" "private:\n" "void f();\n" "void g() {}\n" "};\n" "\n" "#endfile\n" "\n" "int main()\n" "{\n" "}\n" "\n"); ASSERT_EQUALS("", errout.str()); }
void testinvaliddealloc() { check("void func1() {\n" " char tmp1[256];\n" " free(tmp1);\n" " char tmp2[256];\n" " delete tmp2;\n" " char tmp3[256];\n" " delete tmp3;\n" " char tmp4[256];\n" " delete[] (tmp4);\n" " char tmp5[256];\n" " delete[] tmp5;\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" "[test.cpp:5]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" "[test.cpp:7]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" "[test.cpp:9]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" "[test.cpp:11]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); check("void func1() {\n" " char* tmp1[256];\n" " init(tmp1);\n" " delete tmp1[34];\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f()\n" "{\n" " char psz_title[10];\n" " {\n" " char *psz_title = 0;\n" " abc(0, psz_title);\n" " free(psz_title);\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); // #2298 new check: passing stack-address to free() check("int main() {\n" " int *p = malloc(4);\n" " free(&p);\n" " return 0;\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); check("int main() {\n" " int i;\n" " free(&i);\n" " return 0;\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); // #5732 check("int main() {\n" " long (*pKoeff)[256] = new long[9][256];\n" " delete[] pKoeff;\n" "}"); ASSERT_EQUALS("", errout.str()); check("int main() {\n" " long *pKoeff[256];\n" " delete[] pKoeff;\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", "", errout.str()); check("int main() {\n" " long *pKoeff[256];\n" " free (pKoeff);\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", "", errout.str()); check("void foo() {\n" " const intPtr& intref = Getter();\n" " delete intref;\n" "}"); ASSERT_EQUALS("", errout.str()); check("void test() {\n" " MyObj& obj = *new MyObj;\n" " delete &obj;\n" "}"); ASSERT_EQUALS("", errout.str()); // #6506 check("struct F {\n" " void free(void*) {}\n" "};\n" "void foo() {\n" " char c1[1];\n" " F().free(c1);\n" " char *c2 = 0;\n" " F().free(&c2);\n" "}"); ASSERT_EQUALS("", errout.str()); check("class foo {\n" " void free(void* );\n" " void someMethod() {\n" " char **dst_copy = NULL;\n" " free(&dst_copy);\n" " }\n" "};"); ASSERT_EQUALS("", errout.str()); }
void doublefree1() { // #3895 check("void f(char *p) {\n" " if (x)\n" " free(p);\n" " else\n" " p = 0;\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:6]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p) {\n" " free(p);\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p, char *r) {\n" " free(p);\n" " free(r);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo() {\n" " free(p);\n" " free(r);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " if (x < 3) free(p);\n" " else { if (x > 9) free(p); }\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " free(p);\n" " getNext(&p);\n" " free(p);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " free(p);\n" " bar();\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p) {\n" " free(p);\n" " printf(\"Freed memory at location %x\", p);\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(FILE *p) {\n" " fclose(p);\n" " fclose(p);\n" "}"); ASSERT_EQUALS("[test.c:3]: (error) Resource handle 'p' freed twice.\n", errout.str()); check( "void foo(FILE *p, FILE *r) {\n" " fclose(p);\n" " fclose(r);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(FILE *p) {\n" " if (x < 3) fclose(p);\n" " else { if (x > 9) fclose(p); }\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(FILE *p) {\n" " fclose(p);\n" " gethandle(&p);\n" " fclose(p);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(FILE *p) {\n" " fclose(p);\n" " gethandle();\n" " fclose(p);\n" "}"); ASSERT_EQUALS("[test.c:4]: (error) Resource handle 'p' freed twice.\n", errout.str()); check( "void foo(Data* p) {\n" " free(p->a);\n" " free(p->b);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void f() {\n" " char *p; p = malloc(100);\n" " if (x) {\n" " free(p);\n" " exit();\n" " }\n" " free(p);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void f() {\n" " char *p; p = malloc(100);\n" " if (x) {\n" " free(p);\n" " x = 0;\n" " }\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:7]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void f() {\n" " char *p; p = do_something();\n" " free(p);\n" " p = do_something();\n" " free(p);\n" "}"); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " delete p;\n" " delete p;\n" "}", true); ASSERT_EQUALS("[test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p, char *r) {\n" " delete p;\n" " delete r;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(P p) {\n" " delete p.x;\n" " delete p;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(char **p) {\n" " delete p[0];\n" " delete p[1];\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " delete p;\n" " getNext(&p);\n" " delete p;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " delete p;\n" " bar();\n" " delete p;\n" "}", true); ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p) {\n" " delete[] p;\n" " delete[] p;\n" "}", true); ASSERT_EQUALS("[test.cpp:3]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void foo(char *p, char *r) {\n" " delete[] p;\n" " delete[] r;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " delete[] p;\n" " getNext(&p);\n" " delete[] p;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(char *p) {\n" " delete[] p;\n" " bar();\n" " delete[] p;\n" "}", true); ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "~LineMarker() {\n" " delete pxpm;\n" "}\n" "LineMarker &operator=(const LineMarker &) {\n" " delete pxpm;\n" " pxpm = NULL;\n" " return *this;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo()\n" "{\n" " int* ptr; ptr = NULL;\n" " try\n" " {\n" " ptr = new int(4);\n" " }\n" " catch(...)\n" " {\n" " delete ptr;\n" " throw;\n" " }\n" " delete ptr;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "int foo()\n" "{\n" " int* a; a = new int;\n" " bool doDelete; doDelete = true;\n" " if (a != 0)\n" " {\n" " doDelete = false;\n" " delete a;\n" " }\n" " if(doDelete)\n" " delete a;\n" " return 0;\n" "}", true); TODO_ASSERT_EQUALS("", "[test.cpp:11]: (error) Memory pointed to by 'a' is freed twice.\n", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " while(true) {\n" " x = new char[100];\n" " if (y++ > 100)\n" " break;\n" " delete[] x;\n" " }\n" " delete[] x;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " for (int i = 0; i < 10000; i++) {\n" " x = new char[100];\n" " delete[] x;\n" " }\n" " delete[] x;\n" "}", true); TODO_ASSERT_EQUALS("[test.cpp:8]: (error) Memory pointed to by 'x' is freed twice.\n", "", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " while (isRunning()) {\n" " x = new char[100];\n" " delete[] x;\n" " }\n" " delete[] x;\n" "}", true); TODO_ASSERT_EQUALS("[test.cpp:8]: (error) Memory pointed to by 'x' is freed twice.\n", "", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " while (isRunning()) {\n" " x = malloc(100);\n" " free(x);\n" " }\n" " free(x);\n" "}"); TODO_ASSERT_EQUALS("[test.c:8]: (error) Memory pointed to by 'x' is freed twice.\n", "", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " for (;;) {\n" " x = new char[100];\n" " if (y++ > 100)\n" " break;\n" " delete[] x;\n" " }\n" " delete[] x;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void foo(int y)\n" "{\n" " char * x; x = NULL;\n" " do {\n" " x = new char[100];\n" " if (y++ > 100)\n" " break;\n" " delete[] x;\n" " } while (true);\n" " delete[] x;\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void f()\n" "{\n" " char *p; p = 0;\n" " if (x < 100) {\n" " p = malloc(10);\n" " free(p);\n" " }\n" " free(p);\n" "}"); ASSERT_EQUALS("[test.c:8]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); check( "void MyFunction()\n" "{\n" " char* data; data = new char[100];\n" " try\n" " {\n" " }\n" " catch(err)\n" " {\n" " delete[] data;\n" " MyThrow(err);\n" " }\n" " delete[] data;\n" "}\n" "void MyThrow(err)\n" "{\n" " throw(err);\n" "}", true); ASSERT_EQUALS("", errout.str()); check( "void MyFunction()\n" "{\n" " char* data; data = new char[100];\n" " try\n" " {\n" " }\n" " catch(err)\n" " {\n" " delete[] data;\n" " MyExit(err);\n" " }\n" " delete[] data;\n" "}\n" "void MyExit(err)\n" "{\n" " exit(err);\n" "}", true); ASSERT_EQUALS("", errout.str()); check( // #6252 "struct Wrapper {\n" " Thing* m_thing;\n" " Wrapper() : m_thing(0) {\n" " }\n" " ~Wrapper() {\n" " delete m_thing;\n" " }\n" " void changeThing() {\n" " delete m_thing;\n" " m_thing = new Thing;\n" " }\n" "};", true); ASSERT_EQUALS("", errout.str()); }
void comparisonOfBoolExpressionWithInt2() { check("void f(int x) {\n" " if (!x == 10) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str()); check("void f(int x) {\n" " if (!x != 10) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str()); check("void f(int x) {\n" " if (x != 10) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f(int x) {\n" " if (10 == !x) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str()); check("void f(int x) {\n" " if (10 != !x) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str()); check("void f(int x, int y) {\n" " if (y != !x) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f(int x, bool y) {\n" " if (y != !x) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f(int x) {\n" " if (10 != x) {\n" " printf(\"x not equal to 10\");\n" " }\n" "}"); ASSERT_EQUALS("", errout.str()); check("void f(int x, int y) {\n" " return (!y == !x);\n" "}"); ASSERT_EQUALS("", errout.str()); check("int f(int a) {\n" " return (x()+1 == !a);\n" "}"); TODO_ASSERT_EQUALS("error", "", errout.str()); check("void f() { if (!!a+!!b+!!c>1){} }"); ASSERT_EQUALS("",errout.str()); check("void f(int a, int b, int c) { if (a != !b || c) {} }"); ASSERT_EQUALS("",errout.str()); check("void f(int a, int b, int c) { if (1 < !!a + !!b + !!c) {} }"); ASSERT_EQUALS("",errout.str()); check("void f(int a, int b, int c) { if (1 < !(a+b)) {} }"); ASSERT_EQUALS("[test.cpp:1]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n",errout.str()); }