void valueFlowBeforeConditionAssignIncDec() { // assignment / increment const char *code; code = "void f(int x) {\n" " x = 2 + x;\n" " if (x == 65);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 65)); code = "void f(int x) {\n" " x = y = 2 + x;\n" " if (x == 65);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 65)); code = "void f(int x) {\n" " a[x++] = 0;\n" " if (x == 5);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 5)); code = "void f(int x) {\n" " a = x;\n" " x++;\n" " if (x == 4);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 3)); // bailout: assignment bailout("void f(int x) {\n" " x = y;\n" " if (x == 123) {}\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: assignment of x\n", errout.str()); }
void valueFlowBeforeConditionTernaryOp() { // bailout: ?: const char *code; bailout("void f(int x) {\n" " y = ((x<0) ? x : ((x==2)?3:4));\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: no simplification of x within ?: expression\n", errout.str()); bailout("int f(int x) {\n" " int r = x ? 1 / x : 0;\n" " if (x == 0) {}\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: no simplification of x within ?: expression\n", errout.str()); code = "void f(int x) {\n" " int a =v x;\n" " a = b ? x/2 : 20/x;\n" " if (x == 123) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 123)); code = "void f(int x, int y) {\n" " a = x;\n" " if (y){}\n" " if (x==123){}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 123)); }
void valueFlowBeforeConditionFunctionCall() { // function calls const char *code; code = "void f(int x) {\n" " a = x;\n" " setx(x);\n" " if (x == 1) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(std::string("void setx(int x);")+code, 2U, 1)); ASSERT_EQUALS(false, testValueOfX(std::string("void setx(int &x);")+code, 2U, 1)); ASSERT_EQUALS(false, testValueOfX(code, 2U, 1)); code = "void f(char* x) {\n" " strcpy(x,\"abc\");\n" " if (x) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); code = "void addNewFunction(Scope**scope, const Token**tok);\n" "void f(Scope *x) {\n" " x->functionList.back();\n" " addNewFunction(&x,&tok);\n" // address-of, x can be changed by subfunction " if (x) {}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); }
void valueFlowBeforeConditionIfElse() { // bailout: if/else/etc const char *code; code = "void f(X * x) {\n" " a = x;\n" " if ((x != NULL) &&\n" " (a(x->name, html)) &&\n" " (a(x->name, body))) {}\n" " if (x != NULL) { }\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); bailout("void f(int x) {\n" " if (x != 123) { b = x; }\n" " if (x == 123) {}\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: variable x stopping on }\n", errout.str()); code = "void f(int x) {\n" " a = x;\n" " if (abc) { x = 1; }\n" // <- condition must be false if x is 7 in next line " if (x == 7) { }\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 7)); }
void valueFlowSubFunction() { const char *code; code = "void f1(int x) { return x; }\n" "void f2(int x) {\n" " f1(123);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 123)); code = "void f1(int x) { return x; }\n" "void f2(int x) {\n" " f1(x);\n" " if (x==0){}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 0)); code = "void f1(int x) {\n" " if (x == 0) return;\n" " int y = 1234 / x;\n" "}\n" "\n" "void f2() {\n" " f1(0);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); code = "void f1(int x) { a=x; }\n" "void f2(int y) { f1(y<123); }\n"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 1U, 1)); code = "void f1(int x) { a=(abc)x; }\n" "void f2(int y) { f1(123); }\n"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 123)); code = "void f1(int x) {\n" " x ?\n" " 1024 / x :\n" " 0; }\n" "void f2() { f1(0); }"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); // #5861 - fp with float code = "void f1(float x) {\n" " return 1.0 / x;\n" "}\n" "void f2() { f1(0.5); }"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); code = "void dostuff(int x) {\n" " return x/x;\n" "}\n" "\n" "void test(int x) {\n" " if(x==1) {}\n" " dostuff(x+1);\n" "}\n"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 2)); }
void valueFlowBitAnd() { const char *code; code = "int f(int a) {\n" " int x = a & 0x80;\n" " return x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code,3U,0)); ASSERT_EQUALS(true, testValueOfX(code,3U,0x80)); }
void valueFlowForLoop() { const char *code; code = "void f() {\n" " for (int x = 0; x < 10; x++)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 10)); code = "void f() {\n" " for (int x = 0; x < ((short)10); x++)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 10)); code = "void f() {\n" " for (int x = 0; x < 10; x++)\n" " x<4 ?\n" " a[x] : 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); ASSERT_EQUALS(false, testValueOfX(code, 4U, 9)); }
void valueFlowBeforeConditionSizeof() { // skip sizeof const char *code; code = "void f(int *x) {\n" " sizeof(x[0]);\n" " if (x==63){}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 63)); code = "void f(int *x) {\n" " char a[sizeof x.y];\n" " if (x==0){}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); }
void valueFlowBeforeConditionAndAndOrOrGuard() { // guarding by && const char *code; code = "void f(int x) {\n" " if (!x || \n" // <- x can be 0 " a/x) {}\n" // <- x can't be 0 " if (x==0) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); code = "void f(int *x) {\n" " ((x=ret())&&\n" " (*x==0));\n" // <- x is not 0 " if (x==0) {}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); }
void valueFlowString() { const char *code; // valueFlowAfterAssign code = "const char * f() {\n" " static const char *x;\n" " if (a) x = \"123\";\n" " return x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4, "\"123\"")); // valueFlowSubFunction code = "void dostuff(const char *x) {\n" " f(x);\n" "}\n" "\n" "void test() { dostuff(\"abc\"); }"; ASSERT_EQUALS(true, testValueOfX(code, 2, "\"abc\"")); }
void valueFlowPointerAlias() { const char *code; code = "const char * f() {\n" " static const char *x;\n" " static char ret[10];\n" " if (a) x = &ret[0];\n" " return x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 5, "& ret [ 0 ]")); // dead pointer code = "void f() {\n" " int *x;\n" " if (cond) { int i; x = &i; }\n" " *x = 0;\n" // <- x can point at i "}"; ASSERT_EQUALS(true, testValueOfX(code, 4, "& i")); }
void valueFlowSubFunction() { const char *code; code = "void f1(int x) { return x; }\n" "void f2(int x) {\n" " f1(123);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 123)); code = "void f1(int x) { return x; }\n" "void f2(int x) {\n" " f1(x);\n" " if (x==0){}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 0)); code = "void f1(int x) {\n" " if (x == 0) return;\n" " int y = 1234 / x;\n" "}\n" "\n" "void f2() {\n" " f1(0);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); code = "void f1(int x) { a=x; }\n" "void f2(int y) { f1(y<123); }\n"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 1U, 1)); code = "void f1(int x) { a=(abc)x; }\n" "void f2(int y) { f1(123); }\n"; ASSERT_EQUALS(true, testValueOfX(code, 1U, 123)); }
void valueFlowBeforeConditionLoop() { // while, for, do-while const char *code; code = "void f(int x) {\n" // loop condition, x is not assigned inside loop => use condition " a = x;\n" // x can be 37 " while (x == 37) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 37)); code = "void f(int x) {\n" // loop condition, x is assigned inside loop => dont use condition " a = x;\n" // don't assume that x can be 37 " while (x != 37) { x++; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 37)); code = "void f(menu *x) {\n" " a = x->parent;\n" " for (i=0;(i<10) && (x!=0); i++) { x = x->next; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); code = "void f(int x) {\n" // condition inside loop, x is NOT assigned inside loop => use condition " a = x;\n" " do {\n" " if (x==76) {}\n" " } while (1);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 76)); code = "void f(int x) {\n" // conditions inside loop, x is assigned inside do-while => dont use condition " a = x;\n" " do {\n" " if (x!=76) { x=do_something(); }\n" " } while (1);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 76)); code = "void f(X x) {\n" // conditions inside loop, x is assigned inside do-while => dont use condition " a = x;\n" " for (i=1;i<=count;i++) {\n" " BUGON(x==0)\n" " x = x.next;\n" " }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); code = "void f(unsigned int x) {\n" " for (int a = 1000 / x;\n" " x > 0;\n" " x--) {}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); }
void valueFlowAfterAssign() { const char *code; code = "void f() {\n" " int x = 123;\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = sizeof(x);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); // if/else code = "void f() {\n" " int x = 123;\n" " if (condition) return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition) x = 2;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 1)); code = "void f() {\n" " int x = 123;\n" " if (condition1) x = 456;\n" " if (condition2) x = 789;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition1) x = 2;\n" " else return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 1)); }
void valueFlowBeforeCondition() { const char *code; code = "void f(int x) {\n" " int a = x;\n" " if (x == 123) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 123)); code = "void f(unsigned int x) {\n" " int a = x;\n" " if (x >= 1) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 1)); ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); code = "void f(unsigned int x) {\n" " int a = x;\n" " if (x > 0) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); code = "void f(unsigned int x) {\n" " int a = x;\n" " if (x > 1) {}\n" // not zero => don't consider > condition "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 1)); code = "void f(int x) {\n" // not unsigned => don't consider > condition " int a = x;\n" " if (x > 0) {}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); code = "void f(int *x) {\n" " *x = 100;\n" " if (x) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); code = "extern const int x;\n" "void f() {\n" " int a = x;\n" " if (x == 123) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); }
void valueFlowBeforeConditionGlobalVariables() { // bailout: global variables bailout("int x;\n" "void f() {\n" " int a = x;\n" " if (x == 123) {}\n" "}"); ASSERT_EQUALS("[test.cpp:4]: (debug) ValueFlow bailout: global variable x\n", errout.str()); // class variable const char *code; code = "class Fred { int x; void clear(); void f(); };\n" "void Fred::f() {\n" " int a = x;\n" " clear();\n" // <- x might be assigned " if (x == 234) {}\n" "}"; ASSERT_EQUALS(false, testValueOfX(code,3,234)); }
void valueFlowAfterAssign() { const char *code; code = "void f() {\n" " int x = 123;\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = sizeof(x);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 9;\n" " --x;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 9)); code = "void f() {\n" " static int x = 2;\n" " x++;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); code = "void f() {\n" " static int x = 2;\n" " a >> x;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); // function code = "void f() {\n" " char *x = 0;\n" " int success = getx((char**)&x);\n" " if (success) x[0] = 0;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); // if/else code = "void f() {\n" " int x = 123;\n" " if (condition) return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition) x = 2;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 1)); code = "void f() {\n" " int x = 123;\n" " if (condition1) x = 456;\n" " if (condition2) x = 789;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); code = "void f(int a) {\n" " int x = 123;\n" " if (a > 1)\n" " ++x;\n" " else\n" " ++x;\n" " return 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition1) x = 2;\n" " else return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 1)); code = "void f(){\n" " int x = 0;\n" " if (a>=0) { x = getx(); }\n" " if (x==0) { return; }\n" " return 123 / x;\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); code = "void f() {\n" " X *x = getx();\n" " if(false) { x = 0; }\n" " else { x->y = 1; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); // multivariables code = "void f(int a) {\n" " int x = a;\n" " if (a!=132) { b = x; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 132)); code = "void f(int a) {\n" " int x = a;\n" " b = x;\n" // <- line 3 " if (a!=132) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 132)); code = "void f() {\n" " int a;\n" " if (n) { a = n; }\n" " else { a = 0; }\n" " int x = a;\n" " if (a > 0) { a = b / x; }\n" // <- line 6 "}"; ASSERT_EQUALS(false, testValueOfX(code, 6U, 0)); // x is not 0 at line 6 // break code = "void f() {\n" " for (;;) {\n" " int x = 1;\n" " if (!abc()) {\n" " x = 2;\n" " break;\n" " }\n" " a = x;\n" // <- line 8 " }\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 8U, 2)); // x is not 2 at line 8 }
void valueFlowAfterAssign() { const char *code; code = "void f() {\n" " int x = 123;\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = sizeof(x);\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 123;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f() {\n" " int x = 9;\n" " --x;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 9)); code = "void f() {\n" " int x = 0;\n" " y = x += z;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " static int x = 2;\n" " x++;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); code = "void f() {\n" " static int x = 2;\n" " a >> x;\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); code = "void f() {\n" " static int x = 0;\n" " if (x==0) x = getX();\n" " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); // function code = "void f() {\n" " char *x = 0;\n" " int success = getx((char**)&x);\n" " if (success) x[0] = 0;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " char *x = 0;\n" " getx(reinterpret_cast<void **>(&x));\n" " *x = 0;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); // if/else code = "void f() {\n" " int x = 123;\n" " if (condition) return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition) x = 2;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 1)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 2)); code = "void f() {\n" " int x = 123;\n" " if (condition1) x = 456;\n" " if (condition2) x = 789;\n" " a = 2 + x;\n" // <- either assignment "x=123" is redundant or x can be 123 here. "}"; ASSERT_EQUALS(true, testValueOfX(code, 5U, 123)); code = "void f(int a) {\n" " int x = 123;\n" " if (a > 1)\n" " ++x;\n" " else\n" " ++x;\n" " return 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); code = "void f() {\n" " int x = 1;\n" " if (condition1) x = 2;\n" " else return;\n" " a = 2 + x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 1)); code = "void f(){\n" " int x = 0;\n" " if (a>=0) { x = getx(); }\n" " if (x==0) { return; }\n" " return 123 / x;\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); code = "void f() {\n" " X *x = getx();\n" " if(false) { x = 0; }\n" " else { x->y = 1; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " int x = 32;\n" " if (x>=32) return;\n" " a[x]=0;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 32)); code = "void f() {\n" " int x = 32;\n" " if (x>=32) {\n" " a[x] = 0;\n" // <- should have possible value 32 " return;\n" " }\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 32)); code = "void f() {\n" " int x = 32;\n" " if (a==1) { z=x+12; }\n" " if (a==2) { z=x+32; }\n" " z = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 32)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 32)); ASSERT_EQUALS(true, testValueOfX(code, 5U, 32)); code = "void f() {\n" // #5656 - FP " int x = 0;\n" " if (!x) {\n" " x = getx();\n" " }\n" " y = x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 6U, 0)); code = "void f () {\n" " ST * x = g_pST;\n" " if (x->y == 0) {\n" " x = NULL;\n" " return 1;\n" " }\n" " a = x->y;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 7U, 0)); code = "void f () {\n" " ST * x = g_pST;\n" " if (x->y == 0) {\n" " x = NULL;\n" " goto label;\n" " }\n" " a = x->y;\n" "label:\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 7U, 0)); code = "void f() {\n" // #5752 - FP " int *x = 0;\n" " if (x && *x == 123) {\n" " getx(*x);\n" " }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " int x = 0;\n" " if (!x) {}\n" " else { y = x; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); // multivariables code = "void f(int a) {\n" " int x = a;\n" " if (a!=132) { b = x; }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 132)); code = "void f(int a) {\n" " int x = a;\n" " b = x;\n" // <- line 3 " if (a!=132) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 132)); code = "void f() {\n" " int a;\n" " if (n) { a = n; }\n" " else { a = 0; }\n" " int x = a;\n" " if (a > 0) { a = b / x; }\n" // <- line 6 "}"; ASSERT_EQUALS(false, testValueOfX(code, 6U, 0)); // x is not 0 at line 6 // break code = "void f() {\n" " for (;;) {\n" " int x = 1;\n" " if (!abc()) {\n" " x = 2;\n" " break;\n" " }\n" " a = x;\n" // <- line 8 " }\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 8U, 2)); // x is not 2 at line 8 code = "void f() {\n" " int x;\n" " switch (ab) {\n" " case A: x = 12; break;\n" " case B: x = 34; break;\n" " }\n" " v = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 7U, 12)); ASSERT_EQUALS(true, testValueOfX(code, 7U, 34)); code = "void f() {\n" // #5981 " int x;\n" " switch (ab) {\n" " case A: x = 12; break;\n" " case B: x = 34; break;\n" " }\n" " switch (ab) {\n" " case A: v = x; break;\n" // <- x is not 34 " }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 8U, 34)); }
void valueFlowAfterCondition() { const char *code; // if code = "void f(int x) {\n" " if (x == 123) {\n" " a = x;\n" " }\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f(int x) {\n" " if (x != 123) {\n" " a = x;\n" " }\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); // else code = "void f(int x) {\n" " if (x == 123) {}\n" " else a = x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); code = "void f(int x) {\n" " if (x != 123) {}\n" " else a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); // ! code = "void f(int x) {\n" " if (!x) { a = x; }\n" " else a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); code = "void f(int x, int y) {\n" " if (!(x&&y)) { return; }\n" " a = x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); // if (var) code = "void f(int x) {\n" " if (x) { a = x; }\n" // <- x is not 0 " else { b = x; }\n" // <- x is 0 " c = x;\n" // <- x might be 0 "}"; ASSERT_EQUALS(false, testValueOfX(code, 2U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 0)); // After while code = "void f(int x) {\n" " while (x != 3) {}\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 3)); // conditional code after if/else/while code = "void f(int x) {\n" " if (x == 2) {}\n" " if (x > 0)\n" " a = x;\n" " else\n" " b = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 2)); ASSERT_EQUALS(false, testValueOfX(code, 6U, 2)); // condition with 2nd variable code = "void f(int x) {\n" " int y = 0;\n" " if (x == 7) { y = 1; }\n" " if (!y)\n" " a = x;\n" // <- x can not be 7 here "}"; ASSERT_EQUALS(false, testValueOfX(code, 5U, 7)); // In condition, after && and || code = "void f(int x) {\n" " a = (x != 3 ||\n" " x);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 3)); code = "void f(int x) {\n" " a = (x == 4 &&\n" " x);\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 4)); // TODO: float code = "void f(float x) {\n" " if (x == 0.5) {}\n" " a = x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); }
void valueFlowForLoop() { const char *code; code = "void f() {\n" " for (int x = 0; x < 10; x++)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 10)); code = "void f(int a) {\n" " for (int x = a; x < 10; x++)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); code = "void f() {\n" " for (int x = 0; x < 10; x = x + 2)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 8)); ASSERT_EQUALS(false, testValueOfX(code, 3U, 10)); code = "void f() {\n" " for (int x = 0; x < 10; x = x / 0)\n" " a[x] = 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); // don't crash code = "void f() {\n" " for (int x = 0; x < 10; x++)\n" " x<4 ?\n" " a[x] : 0;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 9)); ASSERT_EQUALS(false, testValueOfX(code, 4U, 9)); code = "void f() {\n" " for (int x = 0; x < 10; x++)\n" " x==0 ?\n" " 0 : a[x];\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " int x;\n" " for (int i = 0; x = bar[i]; i++)\n" " x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" // #5939 " int x;\n" " for (int x = 0; (x = do_something()) != 0;)\n" " x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); code = "void f() {\n" " int x;\n" " for (int x = 0; x < 10 && y = do_something();)\n" " x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 0)); code = "void foo(double recoveredX) {\n" " for (double x = 1e-18; x < 1e40; x *= 1.9) {\n" " double relativeError = (x - recoveredX) / x;\n" " }\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); // && code = "void foo() {\n" " for (int x = 0; x < 10; x++) {\n" " if (x > 1\n" " && x) {}" // <- x is not 0 " }\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 9)); // || code = "void foo() {\n" " for (int x = 0; x < 10; x++) {\n" " if (x == 0\n" " || x) {}" // <- x is not 0 " }\n" "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 9)); }