Blame test/testvalueflow.cpp

Packit 2035a7
/*
Packit 2035a7
 * Cppcheck - A tool for static C/C++ code analysis
Packit 2035a7
 * Copyright (C) 2007-2018 Cppcheck team.
Packit 2035a7
 *
Packit 2035a7
 * This program is free software: you can redistribute it and/or modify
Packit 2035a7
 * it under the terms of the GNU General Public License as published by
Packit 2035a7
 * the Free Software Foundation, either version 3 of the License, or
Packit 2035a7
 * (at your option) any later version.
Packit 2035a7
 *
Packit 2035a7
 * This program is distributed in the hope that it will be useful,
Packit 2035a7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 2035a7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 2035a7
 * GNU General Public License for more details.
Packit 2035a7
 *
Packit 2035a7
 * You should have received a copy of the GNU General Public License
Packit 2035a7
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 2035a7
 */
Packit 2035a7
Packit 2035a7
#include "library.h"
Packit 2035a7
#include "platform.h"
Packit 2035a7
#include "settings.h"
Packit 2035a7
#include "testsuite.h"
Packit 2035a7
#include "token.h"
Packit 2035a7
#include "tokenize.h"
Packit 2035a7
#include "valueflow.h"
Packit 2035a7
Packit 2035a7
#include <simplecpp.h>
Packit 2035a7
#include <cmath>
Packit 2035a7
#include <list>
Packit 2035a7
#include <map>
Packit 2035a7
#include <ostream>
Packit 2035a7
#include <string>
Packit 2035a7
#include <utility>
Packit 2035a7
#include <vector>
Packit 2035a7
Packit 2035a7
class TestValueFlow : public TestFixture {
Packit 2035a7
public:
Packit 2035a7
    TestValueFlow() : TestFixture("TestValueFlow") {
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
private:
Packit 2035a7
    Settings settings;
Packit 2035a7
Packit 2035a7
    void run() {
Packit 2035a7
        // strcpy, abort cfg
Packit 2035a7
        const char cfg[] = "\n"
Packit 2035a7
                           "<def>\n"
Packit 2035a7
                           "  <function name=\"strcpy\"> <arg nr=\"1\"><not-null/></arg> </function>\n"
Packit 2035a7
                           "  <function name=\"abort\"> <noreturn>true</noreturn> </function>\n" // abort is a noreturn function
Packit 2035a7
                           "</def>";
Packit 2035a7
        settings.library.loadxmldata(cfg, sizeof(cfg));
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowNumber);
Packit 2035a7
        TEST_CASE(valueFlowString);
Packit 2035a7
        TEST_CASE(valueFlowPointerAlias);
Packit 2035a7
        TEST_CASE(valueFlowArrayElement);
Packit 2035a7
        TEST_CASE(valueFlowMove);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowBitAnd);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowCalculations);
Packit 2035a7
        TEST_CASE(valueFlowSizeof);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowErrorPath);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowBeforeCondition);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionAndAndOrOrGuard);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionAssignIncDec);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionFunctionCall);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionGlobalVariables);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionGoto);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionIfElse);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionLoop);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionMacro);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionSizeof);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionSwitch);
Packit 2035a7
        TEST_CASE(valueFlowBeforeConditionTernaryOp);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowAfterAssign);
Packit 2035a7
        TEST_CASE(valueFlowAfterCondition);
Packit 2035a7
        TEST_CASE(valueFlowForwardCompoundAssign);
Packit 2035a7
        TEST_CASE(valueFlowForwardCorrelatedVariables);
Packit 2035a7
        TEST_CASE(valueFlowForwardFunction);
Packit 2035a7
        TEST_CASE(valueFlowForwardTernary);
Packit 2035a7
        TEST_CASE(valueFlowForwardLambda);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowSwitchVariable);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowForLoop);
Packit 2035a7
        TEST_CASE(valueFlowSubFunction);
Packit 2035a7
        TEST_CASE(valueFlowFunctionReturn);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowFunctionDefaultParameter);
Packit 2035a7
Packit 2035a7
        TEST_CASE(knownValue);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowSizeofForwardDeclaredEnum);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowGlobalVar);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowGlobalStaticVar);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowInlineAssembly);
Packit 2035a7
Packit 2035a7
        TEST_CASE(valueFlowUninit);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool testValueOfX(const char code[], unsigned int linenr, int value) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() == "x" && tok->linenr() == linenr) {
Packit 2035a7
                std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
                for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                    if (it->isIntValue() && it->intvalue == value)
Packit 2035a7
                        return true;
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool testValueOfX(const char code[], unsigned int linenr, float value, float diff) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() == "x" && tok->linenr() == linenr) {
Packit 2035a7
                std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
                for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                    if (it->isFloatValue() && it->floatValue >= value - diff && it->floatValue <= value + diff)
Packit 2035a7
                        return true;
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    std::string getErrorPathForX(const char code[], unsigned int linenr) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() != "x" || tok->linenr() != linenr)
Packit 2035a7
                continue;
Packit 2035a7
Packit 2035a7
            std::ostringstream ostr;
Packit 2035a7
            std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
            for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                for (ValueFlow::Value::ErrorPath::const_iterator ep = it->errorPath.begin(); ep != it->errorPath.end(); ++ep) {
Packit 2035a7
                    const Token *eptok = ep->first;
Packit 2035a7
                    const std::string &msg = ep->second;
Packit 2035a7
                    ostr << eptok->linenr() << ',' << msg << '\n';
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
            return ostr.str();
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return "";
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool testValueOfX(const char code[], unsigned int linenr, const char value[]) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() == "x" && tok->linenr() == linenr) {
Packit 2035a7
                std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
                for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                    if (it->isTokValue() && Token::simpleMatch(it->tokvalue, value))
Packit 2035a7
                        return true;
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool testValueOfX(const char code[], unsigned int linenr, ValueFlow::Value::MoveKind moveKind) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() == "x" && tok->linenr() == linenr) {
Packit 2035a7
                std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
                for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                    if (it->isMovedValue() && it->moveKind == moveKind)
Packit 2035a7
                        return true;
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool testConditionalValueOfX(const char code[], unsigned int linenr, int value) {
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
Packit 2035a7
            if (tok->str() == "x" && tok->linenr() == linenr) {
Packit 2035a7
                std::list<ValueFlow::Value>::const_iterator it;
Packit 2035a7
                for (it = tok->values().begin(); it != tok->values().end(); ++it) {
Packit 2035a7
                    if (it->isIntValue() && it->intvalue == value && it->condition)
Packit 2035a7
                        return true;
Packit 2035a7
                }
Packit 2035a7
            }
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        return false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void bailout(const char code[]) {
Packit 2035a7
        settings.debugwarnings = true;
Packit 2035a7
        errout.str("");
Packit 2035a7
Packit 2035a7
        std::vector<std::string> files;
Packit 2035a7
        files.push_back("test.cpp");
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        const simplecpp::TokenList tokens1(istr, files, files[0]);
Packit 2035a7
Packit 2035a7
        simplecpp::TokenList tokens2(files);
Packit 2035a7
        std::map<std::string, simplecpp::TokenList*> filedata;
Packit 2035a7
        simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
Packit 2035a7
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        tokenizer.createTokens(&tokens2);
Packit 2035a7
        tokenizer.simplifyTokens1("");
Packit 2035a7
Packit 2035a7
        settings.debugwarnings = false;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    std::list<ValueFlow::Value> tokenValues(const char code[], const char tokstr[]) {
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        errout.str("");
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
        const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
Packit 2035a7
        return tok ? tok->values() : std::list<ValueFlow::Value>();
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
Packit 2035a7
        std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
Packit 2035a7
        return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowNumber() {
Packit 2035a7
        ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue);
Packit 2035a7
        ASSERT(std::fabs(valueOfTok("x=0.5;", "0.5").floatValue - 0.5f) < 0.1f);
Packit 2035a7
        ASSERT_EQUALS(10, valueOfTok("enum {A=10,B=15}; x=A+0;", "+").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("x(NULL);", "NULL").intvalue);
Packit 2035a7
        ASSERT_EQUALS((int)('a'), valueOfTok("x='a';", "'a'").intvalue);
Packit 2035a7
        ASSERT_EQUALS((int)('\n'), valueOfTok("x='\\n';", "'\\n'").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0xFFFFFFFF00000000, valueOfTok("x=0xFFFFFFFF00000000;","18446744069414584320U").intvalue); // #7701
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowString() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        // valueFlowAfterAssign
Packit 2035a7
        code  = "const char * f() {\n"
Packit 2035a7
                "    static const char *x;\n"
Packit 2035a7
                "    if (a) x = \"123\";\n"
Packit 2035a7
                "    return x;\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4, "\"123\""));
Packit 2035a7
Packit 2035a7
        // valueFlowSubFunction
Packit 2035a7
        code  = "void dostuff(const char *x) {\n"
Packit 2035a7
                "  f(x);\n"
Packit 2035a7
                "}\n"
Packit 2035a7
                "\n"
Packit 2035a7
                "void test() { dostuff(\"abc\"); }";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2, "\"abc\""));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowPointerAlias() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code  = "const char * f() {\n"
Packit 2035a7
                "    static const char *x;\n"
Packit 2035a7
                "    static char ret[10];\n"
Packit 2035a7
                "    if (a) x = &ret[0];\n"
Packit 2035a7
                "    return x;\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5, "& ret [ 0 ]"));
Packit 2035a7
Packit 2035a7
        // dead pointer
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "  int *x;\n"
Packit 2035a7
                "  if (cond) { int i; x = &i; }\n"
Packit 2035a7
                "  *x = 0;\n"  // <- x can point at i
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4, "& i"));
Packit 2035a7
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "  struct X *x;\n"
Packit 2035a7
                "  x = &x[1];\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, tokenValues(code, "&").empty());
Packit 2035a7
        ASSERT_EQUALS(true, tokenValues(code, "x [").empty());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowArrayElement() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "    const int x[] = {43,23,12};\n"
Packit 2035a7
                "    return x;\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, "{ 43 , 23 , 12 }"));
Packit 2035a7
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "    const char x[] = \"abcd\";\n"
Packit 2035a7
                "    return x;\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, "\"abcd\""));
Packit 2035a7
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "    char x[32] = \"abcd\";\n"
Packit 2035a7
                "    return x;\n"
Packit 2035a7
                "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, "\"abcd\""));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int a[10];\n"
Packit 2035a7
               "  int *x = a;\n" // <- a value is a
Packit 2035a7
               "  *x = 0;\n"     // .. => x value is a
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4, "a"));
Packit 2035a7
Packit 2035a7
        code  = "char f() {\n"
Packit 2035a7
                "    const char *x = \"abcd\";\n"
Packit 2035a7
                "    return x[0];\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS((int)('a'), valueOfTok(code, "[").intvalue);
Packit 2035a7
Packit 2035a7
        code  = "char f() {\n"
Packit 2035a7
                "    const char *x = \"\";\n"
Packit 2035a7
                "    return x[0];\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok(code, "[").intvalue);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowMove() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::move(x));\n"
Packit 2035a7
               "   y=x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::forward<X>(x));\n"
Packit 2035a7
               "   y=x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, ValueFlow::Value::ForwardedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::move(x).getA());\n"   // Only parts of x might be moved out
Packit 2035a7
               "   y=x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::forward<X>(x).getA());\n" // Only parts of x might be moved out
Packit 2035a7
               "   y=x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::ForwardedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::move(x));\n"
Packit 2035a7
               "   x.clear();\n"
Packit 2035a7
               "   y=x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "   X x;\n"
Packit 2035a7
               "   g(std::move(x));\n"
Packit 2035a7
               "   y=x->y;\n"
Packit 2035a7
               "   z=x->z;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f(int i) {\n"
Packit 2035a7
               "    X x;\n"
Packit 2035a7
               "    z = g(std::move(x));\n"
Packit 2035a7
               "    y = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f(int i) {\n"
Packit 2035a7
               "    X x;\n"
Packit 2035a7
               "    y = g(std::move(x), \n"
Packit 2035a7
               "          x.size());\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "void f(int i) {\n"
Packit 2035a7
               "    X x;\n"
Packit 2035a7
               "    x = g(std::move(x));\n"
Packit 2035a7
               "    y = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "A f(int i) {\n"
Packit 2035a7
               "    X x;\n"
Packit 2035a7
               "    if (i)"
Packit 2035a7
               "        return g(std::move(x));\n"
Packit 2035a7
               "    return h(std::move(x));\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, ValueFlow::Value::MovedVariable));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowCalculations() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        // Different operators
Packit 2035a7
        ASSERT_EQUALS(5, valueOfTok("3 +  (a ? b : 2);", "+").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("3 -  (a ? b : 2);", "-").intvalue);
Packit 2035a7
        ASSERT_EQUALS(6, valueOfTok("3 *  (a ? b : 2);", "*").intvalue);
Packit 2035a7
        ASSERT_EQUALS(6, valueOfTok("13 / (a ? b : 2);", "/").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("13 % (a ? b : 2);", "%").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("3 == (a ? b : 2);", "==").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("3 != (a ? b : 2);", "!=").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("3 >  (a ? b : 2);", ">").intvalue);
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("3 >= (a ? b : 2);", ">=").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("3 <  (a ? b : 2);", "<").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("3 <= (a ? b : 2);", "<=").intvalue);
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok("(UNKNOWN_TYPE)1;","(").intvalue);
Packit 2035a7
        ASSERT(tokenValues("(UNKNOWN_TYPE)1000;","(").empty()); // don't know if there is truncation, sign extension
Packit 2035a7
        ASSERT_EQUALS(255, valueOfTok("(unsigned char)~0;", "(").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("(int)0;", "(").intvalue);
Packit 2035a7
        ASSERT_EQUALS(3, valueOfTok("(int)(1+2);", "(").intvalue);
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok("(UNKNOWN_TYPE*)0;","(").intvalue);
Packit 2035a7
        ASSERT_EQUALS(100, valueOfTok("(int)100.0;", "(").intvalue);
Packit 2035a7
Packit 2035a7
        // Don't calculate if there is UB
Packit 2035a7
        ASSERT(tokenValues(";-1<<10;","<<").empty());
Packit 2035a7
        ASSERT(tokenValues(";10<<-1;","<<").empty());
Packit 2035a7
        ASSERT(tokenValues(";10<<64;","<<").empty());
Packit 2035a7
        ASSERT(tokenValues(";-1>>10;",">>").empty());
Packit 2035a7
        ASSERT(tokenValues(";10>>-1;",">>").empty());
Packit 2035a7
        ASSERT(tokenValues(";10>>64;",">>").empty());
Packit 2035a7
Packit 2035a7
        // calculation using 1,2 variables/values
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    a = x+456;\n"
Packit 2035a7
                "    if (x==123) {}"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(579, valueOfTok(code, "+").intvalue);
Packit 2035a7
Packit 2035a7
        code  = "void f(int x, int y) {\n"
Packit 2035a7
                "    a = x+y;\n"
Packit 2035a7
                "    if (x==123 || y==456) {}"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(0, valueOfTok(code, "+").intvalue);
Packit 2035a7
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    a = x+x;\n"
Packit 2035a7
                "    if (x==123) {}"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(246, valueOfTok(code, "+").intvalue);
Packit 2035a7
Packit 2035a7
        code  = "void f(int x, int y) {\n"
Packit 2035a7
                "    a = x*x;\n"
Packit 2035a7
                "    if (x==2) {}\n"
Packit 2035a7
                "    if (x==4) {}\n"
Packit 2035a7
                "}";
Packit 2035a7
        std::list<ValueFlow::Value> values = tokenValues(code,"*");
Packit 2035a7
        ASSERT_EQUALS(2U, values.size());
Packit 2035a7
        ASSERT_EQUALS(4, values.front().intvalue);
Packit 2035a7
        ASSERT_EQUALS(16, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    if (x == 3) {}\n"
Packit 2035a7
                "    a = x * (1 - x - 1);\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(-9, valueOfTok(code, "*").intvalue);
Packit 2035a7
Packit 2035a7
        // addition of different variables with known values
Packit 2035a7
        code = "int f(int x) {\n"
Packit 2035a7
               "  int a = 1;\n"
Packit 2035a7
               "  while (x!=3) { x+=a; }\n"
Packit 2035a7
               "  return x/a;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(3, valueOfTok(code, "/").intvalue);
Packit 2035a7
Packit 2035a7
        // ? :
Packit 2035a7
        code = "x = y ? 2 : 3;\n";
Packit 2035a7
        values = tokenValues(code,"?");
Packit 2035a7
        ASSERT_EQUALS(2U, values.size());
Packit 2035a7
        ASSERT_EQUALS(2, values.front().intvalue);
Packit 2035a7
        ASSERT_EQUALS(3, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        code = "void f(int a) { x = a ? 2 : 3; }\n";
Packit 2035a7
        values = tokenValues(code,"?");
Packit 2035a7
        ASSERT_EQUALS(2U, values.size());
Packit 2035a7
        ASSERT_EQUALS(2, values.front().intvalue);
Packit 2035a7
        ASSERT_EQUALS(3, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        code = "x = (2<5) ? 2 : 3;\n";
Packit 2035a7
        values = tokenValues(code, "?");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(2, values.front().intvalue);
Packit 2035a7
Packit 2035a7
        code = "x = 123 ? : 456;\n";
Packit 2035a7
        values = tokenValues(code, "?");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(123, values.empty() ? 0 : values.front().intvalue);
Packit 2035a7
Packit 2035a7
        // ~
Packit 2035a7
        code  = "x = ~0U;";
Packit 2035a7
        settings.platform(cppcheck::Platform::Native); // ensure platform is native
Packit 2035a7
        values = tokenValues(code,"~");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(~0U, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // !
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    a = !x;\n"
Packit 2035a7
                "    if (x==0) {}\n"
Packit 2035a7
                "}";
Packit 2035a7
        values = tokenValues(code,"!");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(1, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // unary minus
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    a = -x;\n"
Packit 2035a7
                "    if (x==10) {}\n"
Packit 2035a7
                "}";
Packit 2035a7
        values = tokenValues(code,"-");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(-10, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // function call => calculation
Packit 2035a7
        code  = "void f(int x) {\n"
Packit 2035a7
                "    a = x + 8;\n"
Packit 2035a7
                "}\n"
Packit 2035a7
                "void callf() {\n"
Packit 2035a7
                "    f(7);\n"
Packit 2035a7
                "}";
Packit 2035a7
        ASSERT_EQUALS(15, valueOfTok(code, "+").intvalue);
Packit 2035a7
Packit 2035a7
        code  = "void f(int x, int y) {\n"
Packit 2035a7
                "    a = x + y;\n"
Packit 2035a7
                "}\n"
Packit 2035a7
                "void callf() {\n"
Packit 2035a7
                "    f(1,1);\n"
Packit 2035a7
                "    f(10,10);\n"
Packit 2035a7
                "}";
Packit 2035a7
        values = tokenValues(code, "+");
Packit 2035a7
        ASSERT_EQUALS(true, values.empty());
Packit 2035a7
        if (!values.empty()) {
Packit 2035a7
            /* todo.. */
Packit 2035a7
            ASSERT_EQUALS(2U, values.size());
Packit 2035a7
            ASSERT_EQUALS(2, values.front().intvalue);
Packit 2035a7
            ASSERT_EQUALS(22, values.back().intvalue);
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        // Comparison of string
Packit 2035a7
        values = tokenValues("f(\"xyz\" == \"xyz\");", "=="); // implementation defined
Packit 2035a7
        ASSERT_EQUALS(0U, values.size()); // <- no value
Packit 2035a7
Packit 2035a7
        values = tokenValues("f(\"xyz\" == 0);", "==");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(0, values.front().intvalue);
Packit 2035a7
Packit 2035a7
        values = tokenValues("f(0 == \"xyz\");", "==");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(0, values.front().intvalue);
Packit 2035a7
Packit 2035a7
        values = tokenValues("f(\"xyz\" != 0);", "!=");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(1, values.front().intvalue);
Packit 2035a7
Packit 2035a7
        values = tokenValues("f(0 != \"xyz\");", "!=");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(1, values.front().intvalue);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowSizeof() {
Packit 2035a7
        const char *code;
Packit 2035a7
        std::list<ValueFlow::Value> values;
Packit 2035a7
Packit 2035a7
#define CHECK(A, B)                              \
Packit 2035a7
        code = "void f() {\n"                    \
Packit 2035a7
               "    x = sizeof(" A ");\n"        \
Packit 2035a7
               "}";                              \
Packit 2035a7
        values = tokenValues(code,"( " A " )");  \
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());        \
Packit 2035a7
        ASSERT_EQUALS(B, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // standard types
Packit 2035a7
        CHECK("void *", settings.sizeof_pointer);
Packit 2035a7
        CHECK("char", 1U);
Packit 2035a7
        CHECK("short", settings.sizeof_short);
Packit 2035a7
        CHECK("int", settings.sizeof_int);
Packit 2035a7
        CHECK("long", settings.sizeof_long);
Packit 2035a7
#undef CHECK
Packit 2035a7
Packit 2035a7
        // array size
Packit 2035a7
        code  = "void f() {\n"
Packit 2035a7
                "    struct S *a[10];"
Packit 2035a7
                "    x = sizeof(a) / sizeof(a[0]);\n"
Packit 2035a7
                "}";
Packit 2035a7
        values = tokenValues(code,"/");
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());
Packit 2035a7
        ASSERT_EQUALS(10, values.back().intvalue);
Packit 2035a7
Packit 2035a7
#define CHECK(A, B, C, D)                         \
Packit 2035a7
        code = "enum " A " E " B " { E0, E1 };\n" \
Packit 2035a7
               "void f() {\n"                     \
Packit 2035a7
               "    x = sizeof(" C ");\n"         \
Packit 2035a7
               "}";                               \
Packit 2035a7
        values = tokenValues(code,"( " C " )");   \
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());         \
Packit 2035a7
        ASSERT_EQUALS(D, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // enums
Packit 2035a7
        CHECK("", "", "E", settings.sizeof_int);
Packit 2035a7
Packit 2035a7
        // typed enums
Packit 2035a7
        CHECK("", ": char", "E", 1U);
Packit 2035a7
        CHECK("", ": signed char", "E", 1U);
Packit 2035a7
        CHECK("", ": unsigned char", "E", 1U);
Packit 2035a7
        CHECK("", ": short", "E", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": signed short", "E", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": unsigned short", "E", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": int", "E", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": signed int", "E", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": unsigned int", "E", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": long", "E", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": signed long", "E", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": unsigned long", "E", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": long long", "E", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": signed long long", "E", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": unsigned long long", "E", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": wchar_t", "E", settings.sizeof_wchar_t);
Packit 2035a7
        CHECK("", ": size_t", "E", settings.sizeof_size_t);
Packit 2035a7
Packit 2035a7
        // enumerators
Packit 2035a7
        CHECK("", "", "E0", settings.sizeof_int);
Packit 2035a7
Packit 2035a7
        // typed enumerators
Packit 2035a7
        CHECK("", ": char", "E0", 1U);
Packit 2035a7
        CHECK("", ": signed char", "E0", 1U);
Packit 2035a7
        CHECK("", ": unsigned char", "E0", 1U);
Packit 2035a7
        CHECK("", ": short", "E0", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": signed short", "E0", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": unsigned short", "E0", settings.sizeof_short);
Packit 2035a7
        CHECK("", ": int", "E0", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": signed int", "E0", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": unsigned int", "E0", settings.sizeof_int);
Packit 2035a7
        CHECK("", ": long", "E0", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": signed long", "E0", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": unsigned long", "E0", settings.sizeof_long);
Packit 2035a7
        CHECK("", ": long long", "E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": signed long long", "E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": unsigned long long", "E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("", ": wchar_t", "E0", settings.sizeof_wchar_t);
Packit 2035a7
        CHECK("", ": size_t", "E0", settings.sizeof_size_t);
Packit 2035a7
Packit 2035a7
        // class typed enumerators
Packit 2035a7
        CHECK("class", ": char", "E :: E0", 1U);
Packit 2035a7
        CHECK("class", ": signed char", "E :: E0", 1U);
Packit 2035a7
        CHECK("class", ": unsigned char", "E :: E0", 1U);
Packit 2035a7
        CHECK("class", ": short", "E :: E0", settings.sizeof_short);
Packit 2035a7
        CHECK("class", ": signed short", "E :: E0", settings.sizeof_short);
Packit 2035a7
        CHECK("class", ": unsigned short", "E :: E0", settings.sizeof_short);
Packit 2035a7
        CHECK("class", ": int", "E :: E0", settings.sizeof_int);
Packit 2035a7
        CHECK("class", ": signed int", "E :: E0", settings.sizeof_int);
Packit 2035a7
        CHECK("class", ": unsigned int", "E :: E0", settings.sizeof_int);
Packit 2035a7
        CHECK("class", ": long", "E :: E0", settings.sizeof_long);
Packit 2035a7
        CHECK("class", ": signed long", "E :: E0", settings.sizeof_long);
Packit 2035a7
        CHECK("class", ": unsigned long", "E :: E0", settings.sizeof_long);
Packit 2035a7
        CHECK("class", ": long long", "E :: E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("class", ": signed long long", "E :: E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("class", ": unsigned long long", "E :: E0", settings.sizeof_long_long);
Packit 2035a7
        CHECK("class", ": wchar_t", "E :: E0", settings.sizeof_wchar_t);
Packit 2035a7
        CHECK("class", ": size_t", "E :: E0", settings.sizeof_size_t);
Packit 2035a7
#undef CHECK
Packit 2035a7
Packit 2035a7
#define CHECK(A, B)                                   \
Packit 2035a7
        code = "enum E " A " { E0, E1 };\n"           \
Packit 2035a7
               "void f() {\n"                         \
Packit 2035a7
               "    E arrE[] = { E0, E1 };\n"         \
Packit 2035a7
               "    x = sizeof(arrE);\n"              \
Packit 2035a7
               "}";                                   \
Packit 2035a7
        values = tokenValues(code,"( arrE )");        \
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());             \
Packit 2035a7
        ASSERT_EQUALS(B * 2U, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // enum array
Packit 2035a7
        CHECK("", settings.sizeof_int);
Packit 2035a7
Packit 2035a7
        // typed enum array
Packit 2035a7
        CHECK(": char", 1U);
Packit 2035a7
        CHECK(": signed char", 1U);
Packit 2035a7
        CHECK(": unsigned char", 1U);
Packit 2035a7
        CHECK(": short", settings.sizeof_short);
Packit 2035a7
        CHECK(": signed short", settings.sizeof_short);
Packit 2035a7
        CHECK(": unsigned short", settings.sizeof_short);
Packit 2035a7
        CHECK(": int", settings.sizeof_int);
Packit 2035a7
        CHECK(": signed int", settings.sizeof_int);
Packit 2035a7
        CHECK(": unsigned int", settings.sizeof_int);
Packit 2035a7
        CHECK(": long", settings.sizeof_long);
Packit 2035a7
        CHECK(": signed long", settings.sizeof_long);
Packit 2035a7
        CHECK(": unsigned long", settings.sizeof_long);
Packit 2035a7
        CHECK(": long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": signed long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": unsigned long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": wchar_t", settings.sizeof_wchar_t);
Packit 2035a7
        CHECK(": size_t", settings.sizeof_size_t);
Packit 2035a7
#undef CHECK
Packit 2035a7
Packit 2035a7
#define CHECK(A, B)                                   \
Packit 2035a7
        code = "enum class E " A " { E0, E1 };\n"     \
Packit 2035a7
               "void f() {\n"                         \
Packit 2035a7
               "    E arrE[] = { E::E0, E::E1 };\n"   \
Packit 2035a7
               "    x = sizeof(arrE);\n"              \
Packit 2035a7
               "}";                                   \
Packit 2035a7
        values = tokenValues(code,"( arrE )");        \
Packit 2035a7
        ASSERT_EQUALS(1U, values.size());             \
Packit 2035a7
        ASSERT_EQUALS(B * 2U, values.back().intvalue);
Packit 2035a7
Packit 2035a7
        // enum array
Packit 2035a7
        CHECK("", settings.sizeof_int);
Packit 2035a7
Packit 2035a7
        // typed enum array
Packit 2035a7
        CHECK(": char", 1U);
Packit 2035a7
        CHECK(": signed char", 1U);
Packit 2035a7
        CHECK(": unsigned char", 1U);
Packit 2035a7
        CHECK(": short", settings.sizeof_short);
Packit 2035a7
        CHECK(": signed short", settings.sizeof_short);
Packit 2035a7
        CHECK(": unsigned short", settings.sizeof_short);
Packit 2035a7
        CHECK(": int", settings.sizeof_int);
Packit 2035a7
        CHECK(": signed int", settings.sizeof_int);
Packit 2035a7
        CHECK(": unsigned int", settings.sizeof_int);
Packit 2035a7
        CHECK(": long", settings.sizeof_long);
Packit 2035a7
        CHECK(": signed long", settings.sizeof_long);
Packit 2035a7
        CHECK(": unsigned long", settings.sizeof_long);
Packit 2035a7
        CHECK(": long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": signed long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": unsigned long long", settings.sizeof_long_long);
Packit 2035a7
        CHECK(": wchar_t", settings.sizeof_wchar_t);
Packit 2035a7
        CHECK(": size_t", settings.sizeof_size_t);
Packit 2035a7
#undef CHECK
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowErrorPath() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 53;\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS("2,Assignment 'x=53', assigned value is 53\n",
Packit 2035a7
                      getErrorPathForX(code, 3U));
Packit 2035a7
Packit 2035a7
        code = "void f(int y) {\n"
Packit 2035a7
               "  int x = y;\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "  y += 12;\n"
Packit 2035a7
               "  if (y == 32) {}"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS("5,Assuming that condition 'y==32' is not redundant\n"
Packit 2035a7
                      "4,Compound assignment '+=', before assignment value is 20\n"
Packit 2035a7
                      "2,Assignment 'x=y', assigned value is 20\n",
Packit 2035a7
                      getErrorPathForX(code, 3U));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "  int x = 3;\n"
Packit 2035a7
               "  f1(x+1);\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS("5,Assignment 'x=3', assigned value is 3\n"
Packit 2035a7
                      "6,Calling function 'f1', 1st argument 'x' value is 4\n",
Packit 2035a7
                      getErrorPathForX(code, 2U));
Packit 2035a7
Packit 2035a7
        code = "void f(int a) {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = a; x < 50; x++) {}\n"
Packit 2035a7
               "  b = x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS("3,After for loop, x has value 50\n",
Packit 2035a7
                      getErrorPathForX(code, 4U));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeCondition() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x == 123) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f(unsigned int x) {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x >= 1) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 1));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(unsigned int x) {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x > 0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(unsigned int x) {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x > 1) {}\n" // not zero => don't consider > condition
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n" // not unsigned => don't consider > condition
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x > 0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int *x) {\n"
Packit 2035a7
               "    *x = 100;\n"
Packit 2035a7
               "    if (x) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "extern const int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x == 123) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        // after loop
Packit 2035a7
        code = "void f(struct X *x) {\n"
Packit 2035a7
               "  do {\n"
Packit 2035a7
               "    if (!x)\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "  } while (x->a);\n"
Packit 2035a7
               "  if (x) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionAssignIncDec() {  // assignment / increment
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   x = 2 + x;\n"
Packit 2035a7
               "   if (x == 65);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 65));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   x = y = 2 + x;\n"
Packit 2035a7
               "   if (x == 65);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 65));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a[x++] = 0;\n"
Packit 2035a7
               "   if (x == 5);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 5));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a = x;\n"
Packit 2035a7
               "   x++;\n"
Packit 2035a7
               "   if (x == 4);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 3));
Packit 2035a7
        ASSERT_EQUALS("4,Assuming that condition 'x==4' is not redundant\n"
Packit 2035a7
                      "3,x is incremented, before this increment the value is 3\n",
Packit 2035a7
                      getErrorPathForX(code, 2U));
Packit 2035a7
Packit 2035a7
        // compound assignment += , -= , ...
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a = x;\n"
Packit 2035a7
               "   x += 2;\n"
Packit 2035a7
               "   if (x == 4);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a = x;\n"
Packit 2035a7
               "   x -= 2;\n"
Packit 2035a7
               "   if (x == 4);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 6));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a = x;\n"
Packit 2035a7
               "   x *= 2;\n"
Packit 2035a7
               "   if (x == 42);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 21));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "   a = x;\n"
Packit 2035a7
               "   x /= 5;\n"
Packit 2035a7
               "   if (x == 42);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(tokenValues(code, "x ;").empty());
Packit 2035a7
Packit 2035a7
        // bailout: assignment
Packit 2035a7
        bailout("void f(int x) {\n"
Packit 2035a7
                "    x = y;\n"
Packit 2035a7
                "    if (x == 123) {}\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:1035:valueFlowReverse bailout: assignment of x\n", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionAndAndOrOrGuard() { // guarding by &&
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (!x || \n"  // <- x can be 0
Packit 2035a7
               "        a/x) {}\n" // <- x can't be 0
Packit 2035a7
               "    if (x==0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int *x) {\n"
Packit 2035a7
               "  ((x=ret())&&\n"
Packit 2035a7
               "   (*x==0));\n"  // <- x is not 0
Packit 2035a7
               "  if (x==0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int *x) {\n"
Packit 2035a7
               "  int a = (x && *x == '1');\n"
Packit 2035a7
               "  int b = a ? atoi(x) : 0;\n"  // <- x is not 0
Packit 2035a7
               "  if (x==0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionFunctionCall() { // function calls
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "  setx(x);\n"
Packit 2035a7
               "  if (x == 1) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX((std::string("void setx(int x);")+code).c_str(), 2U, 1));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX((std::string("void setx(int &x);")+code).c_str(), 2U, 1));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f(char* x) {\n"
Packit 2035a7
               "  strcpy(x,\"abc\");\n"
Packit 2035a7
               "  if (x) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void addNewFunction(Scope**scope, const Token**tok);\n"
Packit 2035a7
               "void f(Scope *x) {\n"
Packit 2035a7
               "  x->functionList.back();\n"
Packit 2035a7
               "  addNewFunction(&x,&tok;;\n" // address-of, x can be changed by subfunction
Packit 2035a7
               "  if (x) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionLoop() { // while, for, do-while
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n" // loop condition, x is not assigned inside loop => use condition
Packit 2035a7
               "  a = x;\n"  // x can be 37
Packit 2035a7
               "  while (x == 37) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 37));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n" // loop condition, x is assigned inside loop => don't use condition
Packit 2035a7
               "  a = x;\n"  // don't assume that x can be 37
Packit 2035a7
               "  while (x != 37) { x++; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 37));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "  for (; x!=1; x++) { }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f(menu *x) {\n"
Packit 2035a7
               "  a = x->parent;\n"
Packit 2035a7
               "  for (i=0;(i<10) && (x!=0); i++) { x = x->next; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"  // condition inside loop, x is NOT assigned inside loop => use condition
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "    do {\n"
Packit 2035a7
               "        if (x==76) {}\n"
Packit 2035a7
               "    } while (1);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 76));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"  // conditions inside loop, x is assigned inside do-while => don't use condition
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "    do {\n"
Packit 2035a7
               "        if (x!=76) { x=do_something(); }\n"
Packit 2035a7
               "    } while (1);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 76));
Packit 2035a7
Packit 2035a7
        code = "void f(X x) {\n"  // conditions inside loop, x is assigned inside do-while => don't use condition
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "    for (i=1;i<=count;i++) {\n"
Packit 2035a7
               "        BUGON(x==0)\n"
Packit 2035a7
               "        x = x.next;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionTernaryOp() { // bailout: ?:
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        bailout("void f(int x) {\n"
Packit 2035a7
                "    y = ((x<0) ? x : ((x==2)?3:4));\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:1113:valueFlowReverse bailout: no simplification of x within ?: expression\n", errout.str());
Packit 2035a7
Packit 2035a7
        bailout("int f(int x) {\n"
Packit 2035a7
                "  int r = x ? 1 / x : 0;\n"
Packit 2035a7
                "  if (x == 0) {}\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:1113:valueFlowReverse bailout: no simplification of x within ?: expression\n", errout.str());
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    int a =v x;\n"
Packit 2035a7
               "    a = b ? x/2 : 20/x;\n"
Packit 2035a7
               "    if (x == 123) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f(const s *x) {\n"
Packit 2035a7
               "  x->a = 0;\n"
Packit 2035a7
               "  if (x ? x->a : 0) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int x, int y) {\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "    if (y){}\n"
Packit 2035a7
               "    if (x==123){}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 123));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionSizeof() { // skip sizeof
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int *x) {\n"
Packit 2035a7
               "    sizeof(x[0]);\n"
Packit 2035a7
               "    if (x==63){}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 63));
Packit 2035a7
Packit 2035a7
        code = "void f(int *x) {\n"
Packit 2035a7
               "    char a[sizeof x.y];\n"
Packit 2035a7
               "    if (x==0){}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionIfElse() { // bailout: if/else/etc
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(X * x) {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "  if ((x != NULL) &&\n"
Packit 2035a7
               "      (a(x->name, html)) &&\n"
Packit 2035a7
               "      (a(x->name, body))) {}\n"
Packit 2035a7
               "  if (x != NULL) { }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
Packit 2035a7
Packit 2035a7
        bailout("void f(int x) {\n"
Packit 2035a7
                "    if (x != 123) { b = x; }\n"
Packit 2035a7
                "    if (x == 123) {}\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:1144:valueFlowReverse bailout: variable x stopping on }\n", errout.str());
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "  if (abc) { x = 1; }\n"  // <- condition must be false if x is 7 in next line
Packit 2035a7
               "  if (x == 7) { }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 7));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionGlobalVariables() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        // handle global variables
Packit 2035a7
        code = "int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    if (x == 123) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code,3,123));
Packit 2035a7
Packit 2035a7
        // bailout when there is function call
Packit 2035a7
        code = "class Fred { int x; void clear(); void f(); };\n"
Packit 2035a7
               "void Fred::f() {\n"
Packit 2035a7
               "    int a = x;\n"
Packit 2035a7
               "    clear();\n"  // <- x might be assigned
Packit 2035a7
               "    if (x == 234) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code,3,234));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionSwitch() {
Packit 2035a7
        // bailout: switch
Packit 2035a7
        // TODO : handle switch/goto more intelligently
Packit 2035a7
        bailout("void f(int x, int y) {\n"
Packit 2035a7
                "    switch (y) {\n"
Packit 2035a7
                "    case 1: a=x; break;\n"
Packit 2035a7
                "    case 2: if (x==5) {} break;\n"
Packit 2035a7
                "    };\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:3]: (debug) valueflow.cpp:1180:valueFlowReverse bailout: variable x stopping on break\n", errout.str());
Packit 2035a7
Packit 2035a7
        bailout("void f(int x, int y) {\n"
Packit 2035a7
                "    switch (y) {\n"
Packit 2035a7
                "    case 1: a=x; return 1;\n"
Packit 2035a7
                "    case 2: if (x==5) {} break;\n"
Packit 2035a7
                "    };\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:3]: (debug) valueflow.cpp:1180:valueFlowReverse bailout: variable x stopping on return\n", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionMacro() {
Packit 2035a7
        // bailout: condition is a expanded macro
Packit 2035a7
        bailout("#define M  if (x==123) {}\n"
Packit 2035a7
                "void f(int x) {\n"
Packit 2035a7
                "    a = x;\n"
Packit 2035a7
                "    M;\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:4]: (debug) valueflow.cpp:1260:valueFlowBeforeCondition bailout: variable x, condition is defined in macro\n", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBeforeConditionGoto() {
Packit 2035a7
        // bailout: goto label (TODO: handle gotos more intelligently)
Packit 2035a7
        bailout("void f(int x) {\n"
Packit 2035a7
                "    if (x == 123) { goto out; }\n"
Packit 2035a7
                "    a=x;\n"   // <- x is not 123
Packit 2035a7
                "out:"
Packit 2035a7
                "    if (x==123){}\n"
Packit 2035a7
                "}");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:4]: (debug) valueflow.cpp:1131:valueFlowReverse bailout: variable x stopping on goto label\n"
Packit 2035a7
                                          "[test.cpp:2]: (debug) valueflow.cpp:1813:valueFlowForward bailout: variable x. noreturn conditional scope.\n"
Packit 2035a7
                                          , errout.str());
Packit 2035a7
Packit 2035a7
        // #5721 - FP
Packit 2035a7
        bailout("static void f(int rc) {\n"
Packit 2035a7
                "    ABC* abc = getabc();\n"
Packit 2035a7
                "    if (!abc) { goto out };\n"
Packit 2035a7
                "\n"
Packit 2035a7
                "    abc->majortype = 0;\n"
Packit 2035a7
                "    if (FAILED(rc)) {}\n"
Packit 2035a7
                "\n"
Packit 2035a7
                "out:\n"
Packit 2035a7
                "    if (abc) {}\n"
Packit 2035a7
                "}\n");
Packit 2035a7
        ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:1035:valueFlowReverse bailout: assignment of abc\n"
Packit 2035a7
                                          "[test.cpp:8]: (debug) valueflow.cpp:1131:valueFlowReverse bailout: variable abc stopping on goto label\n"
Packit 2035a7
                                          "[test.cpp:3]: (debug) valueflow.cpp:1813:valueFlowForward bailout: variable abc. noreturn conditional scope.\n",
Packit 2035a7
                                          errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowAfterAssign() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    bool x = 32;\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    a = sizeof(x);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    a = 2 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 9;\n"
Packit 2035a7
               "    --x;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 9));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 8));
Packit 2035a7
        ASSERT_EQUALS("2,Assignment 'x=9', assigned value is 9\n"
Packit 2035a7
                      "3,x is decremented', new value is 8\n",
Packit 2035a7
                      getErrorPathForX(code, 4U));
Packit 2035a7
Packit 2035a7
        code = "void x() {\n"
Packit 2035a7
               "    int x = value ? 6 : 0;\n"
Packit 2035a7
               "    x =\n"
Packit 2035a7
               "        1 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 7));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    y = x += z;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    static int x = 2;\n"
Packit 2035a7
               "    x++;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    static int x = 2;\n"
Packit 2035a7
               "    a >> x;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    static int x = 0;\n"
Packit 2035a7
               "    if (x==0) x = getX();\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // function
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    char *x = 0;\n"
Packit 2035a7
               "    int success = getx((char**)&x);\n"
Packit 2035a7
               "    if (success) x[0] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    char *x = 0;\n"
Packit 2035a7
               "    getx(reinterpret_cast<void **>(&x);;\n"
Packit 2035a7
               "    *x = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // lambda
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    Q q = [&]() {\n"
Packit 2035a7
               "        if (x > 0) {}\n"
Packit 2035a7
               "        x++;\n"
Packit 2035a7
               "    };\n"
Packit 2035a7
               "    dosomething(q);\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // ?:
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 8;\n"
Packit 2035a7
               "    a = ((x > 10) ?\n"
Packit 2035a7
               "        x : 0);\n" // <- x is not 8
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 8));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #6973
Packit 2035a7
               "    char *x = \"\";\n"
Packit 2035a7
               "    a = ((x[0] == 'U') ?\n"
Packit 2035a7
               "        x[1] : 0);\n" // <- x is not ""
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, "\"\""));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #6973
Packit 2035a7
               "    char *x = getenv (\"LC_ALL\");\n"
Packit 2035a7
               "    if (x == NULL)\n"
Packit 2035a7
               "        x = \"\";\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "    if ( (x[0] == 'U') &&\n"  // x can be ""
Packit 2035a7
               "         (x[1] ?\n"           // x can't be ""
Packit 2035a7
               "          x[3] :\n"           // x can't be ""
Packit 2035a7
               "          x[2] ))\n"          // x can't be ""
Packit 2035a7
               "    {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 6U, "\"\""));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, "\"\""));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 8U, "\"\""));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 9U, "\"\""));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #7599
Packit 2035a7
               "  t *x = 0;\n"
Packit 2035a7
               "  y = (a ? 1 : x\n" // <- x is 0
Packit 2035a7
               "       && x->y ? 1 : 2);" // <- x is not 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #7599
Packit 2035a7
               "  t *x = 0;\n"
Packit 2035a7
               "  y = (a ? 1 : !x\n" // <- x is 0
Packit 2035a7
               "       || x->y ? 1 : 2);" // <- x is not 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // if/else
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    if (condition) return;\n"
Packit 2035a7
               "    a = 2 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 1;\n"
Packit 2035a7
               "    if (condition) x = 2;\n"
Packit 2035a7
               "    a = 2 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 1));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    if (condition1) x = 456;\n"
Packit 2035a7
               "    if (condition2) x = 789;\n"
Packit 2035a7
               "    a = 2 + x;\n" // <- either assignment "x=123" is redundant or x can be 123 here.
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 5U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f(int a) {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    if (a > 1)\n"
Packit 2035a7
               "        ++x;\n"
Packit 2035a7
               "    else\n"
Packit 2035a7
               "        ++x;\n"
Packit 2035a7
               "    return 2 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 1;\n"
Packit 2035a7
               "    if (condition1) x = 2;\n"
Packit 2035a7
               "    else return;\n"
Packit 2035a7
               "    a = 2 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f(){\n"
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    if (a>=0) { x = getx(); }\n"
Packit 2035a7
               "    if (x==0) { return; }\n"
Packit 2035a7
               "    return 123 / x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  X *x = getx();\n"
Packit 2035a7
               "  if(0) { x = 0; }\n"
Packit 2035a7
               "  else { x->y = 1; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #6239
Packit 2035a7
               "  int x = 4;\n"
Packit 2035a7
               "  if(1) { x = 0; }\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 4));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 32;\n"
Packit 2035a7
               "    if (x>=32) return;\n"
Packit 2035a7
               "    a[x]=0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 32));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 32;\n"
Packit 2035a7
               "    if (x>=32) {\n"
Packit 2035a7
               "        a[x] = 0;\n"  // <- should have possible value 32
Packit 2035a7
               "        return;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 32));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 33;\n"
Packit 2035a7
               "    if (x==33) goto fail;\n"
Packit 2035a7
               "    a[x]=0;\n"
Packit 2035a7
               "fail:\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 33));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 32;\n"
Packit 2035a7
               "    if (a==1) { z=x+12; }\n"
Packit 2035a7
               "    if (a==2) { z=x+32; }\n"
Packit 2035a7
               "    z = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 32));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 32));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 32));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #5656 - FP
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    if (!x) {\n"
Packit 2035a7
               "        x = getx();\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    y = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int y) {\n" // alias
Packit 2035a7
               "  int x = y;\n"
Packit 2035a7
               "  if (y == 54) {}\n"
Packit 2035a7
               "  else { a = x; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 54));
Packit 2035a7
Packit 2035a7
        code = "void f () {\n"
Packit 2035a7
               "    ST * x =  g_pST;\n"
Packit 2035a7
               "    if (x->y == 0) {\n"
Packit 2035a7
               "        x = NULL;\n"
Packit 2035a7
               "        return 1;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    a = x->y;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f () {\n"
Packit 2035a7
               "    ST * x =  g_pST;\n"
Packit 2035a7
               "    if (x->y == 0) {\n"
Packit 2035a7
               "        x = NULL;\n"
Packit 2035a7
               "        goto label;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    a = x->y;\n"
Packit 2035a7
               "label:\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #5752 - FP
Packit 2035a7
               "    int *x = 0;\n"
Packit 2035a7
               "    if (x && *x == 123) {\n"
Packit 2035a7
               "        getx(*x);\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    if (!x) {}\n"
Packit 2035a7
               "    else { y = x; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #6118 - FP
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    x = x & 0x1;\n"
Packit 2035a7
               "    if (x == 0) { x = 2; }\n"
Packit 2035a7
               "    y = 42 / x;\n" // <- x is 2
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #6118 - FN
Packit 2035a7
               "    int x = 0;\n"
Packit 2035a7
               "    x = x & 0x1;\n"
Packit 2035a7
               "    if (x == 0) { x += 2; }\n"
Packit 2035a7
               "    y = 42 / x;\n" // <- x is 2
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 5U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f(int mode) {\n"
Packit 2035a7
               "    struct ABC *x;\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "    if (mode) { x = &y; }\n"
Packit 2035a7
               "    else { x = NULL; }\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "    if (!x) exit(1);\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "    a = x->a;\n" // <- x can't be 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 9U, 0));
Packit 2035a7
Packit 2035a7
        // multivariables
Packit 2035a7
        code = "void f(int a) {\n"
Packit 2035a7
               "    int x = a;\n"
Packit 2035a7
               "    if (a!=132) { b = x; }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 132));
Packit 2035a7
Packit 2035a7
        code = "void f(int a) {\n"
Packit 2035a7
               "    int x = a;\n"
Packit 2035a7
               "    b = x;\n" // <- line 3
Packit 2035a7
               "    if (a!=132) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 132));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int a;\n"
Packit 2035a7
               "    if (n) { a = n; }\n"
Packit 2035a7
               "    else { a = 0; }\n"
Packit 2035a7
               "    int x = a;\n"
Packit 2035a7
               "    if (a > 0) { a = b / x; }\n" // <- line 6
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 0)); // x is not 0 at line 6
Packit 2035a7
Packit 2035a7
        code = "void f(int x1) {\n" // #6086
Packit 2035a7
               "  int x = x1;\n"
Packit 2035a7
               "  if (x1 >= 3) {\n"
Packit 2035a7
               "    return;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n"  // <- x is not 3
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 3));
Packit 2035a7
Packit 2035a7
        code = "int f(int *x) {\n" // #5980
Packit 2035a7
               "  if (!x) {\n"
Packit 2035a7
               "    switch (i) {\n"
Packit 2035a7
               "      default:\n"
Packit 2035a7
               "        throw std::runtime_error(msg);\n"
Packit 2035a7
               "    };\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  return *x;\n"  // <- x is not 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 8U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int a) {\n" // #6826
Packit 2035a7
               "    int x = a ? a : 87;\n"
Packit 2035a7
               "    if (a && x) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 87));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int first=-1, x=0;\n"
Packit 2035a7
               "  do {\n"
Packit 2035a7
               "    if (first >= 0) { a = x; }\n" // <- x is not 0
Packit 2035a7
               "    first++; x=3;\n"
Packit 2035a7
               "  } while (1);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // pointer/reference to x
Packit 2035a7
        code = "int f(void) {\n"
Packit 2035a7
               "  int x = 2;\n"
Packit 2035a7
               "  int *px = &x;\n"
Packit 2035a7
               "  for (int i = 0; i < 1; i++) {\n"
Packit 2035a7
               "    *px = 1;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 2));
Packit 2035a7
Packit 2035a7
        code = "int f(void) {\n"
Packit 2035a7
               "  int x = 5;\n"
Packit 2035a7
               "  int &rx = x;\n"
Packit 2035a7
               "  for (int i = 0; i < 1; i++) {\n"
Packit 2035a7
               "    rx = 1;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 5));
Packit 2035a7
Packit 2035a7
        // break
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  for (;;) {\n"
Packit 2035a7
               "    int x = 1;\n"
Packit 2035a7
               "    if (!abc()) {\n"
Packit 2035a7
               "      x = 2;\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    a = x;\n" // <- line 8
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 8U, 2)); // x is not 2 at line 8
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  switch (ab) {\n"
Packit 2035a7
               "    case A: x = 12; break;\n"
Packit 2035a7
               "    case B: x = 34; break;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  v = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 7U, 12));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 7U, 34));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #5981
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  switch (ab) {\n"
Packit 2035a7
               "    case A: x = 12; break;\n"
Packit 2035a7
               "    case B: x = 34; break;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  switch (ab) {\n"
Packit 2035a7
               "    case A: v = x; break;\n" // <- x is not 34
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 8U, 34));
Packit 2035a7
Packit 2035a7
        // while/for
Packit 2035a7
        code = "void f() {\n" // #6138
Packit 2035a7
               "  ENTRY *x = 0;\n"
Packit 2035a7
               "  while (x = get()) {\n"
Packit 2035a7
               "    set(x->value);\n"  // <- x is not 0
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(const int *buf) {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  for (int i = 0; i < 10; i++) {\n"
Packit 2035a7
               "    if (buf[i] == 123) {\n"
Packit 2035a7
               "      x = i;\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n" // <- x can be 0
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 9U, 0)); // x can be 0 at line 9
Packit 2035a7
Packit 2035a7
        code = "void f(const int *buf) {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  for (int i = 0; i < 10; i++) {\n"
Packit 2035a7
               "    if (buf[i] == 123) {\n"
Packit 2035a7
               "      x = i;\n"
Packit 2035a7
               "      ;\n" // <- no break
Packit 2035a7
               "    }\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n" // <- x can't be 0
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 9U, 0)); // x can't be 0 at line 9
Packit 2035a7
Packit 2035a7
        code = "void f(const int *buf) {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  while (++i < 10) {\n"
Packit 2035a7
               "    if (buf[i] == 123) {\n"
Packit 2035a7
               "      x = i;\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n" // <- x can be 0
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 9U, 0)); // x can be 0 at line 9
Packit 2035a7
Packit 2035a7
        code = "void f(const int a[]) {\n" // #6616
Packit 2035a7
               "  const int *x = 0;\n"
Packit 2035a7
               "  for (int i = 0; i < 10; i = *x) {\n" // <- x is not 0
Packit 2035a7
               "    x = a[i];\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // alias
Packit 2035a7
        code = "void f() {\n" // #7778
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  int *p = &x;\n"
Packit 2035a7
               "  x = 3;\n"
Packit 2035a7
               "  *p = 2;\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 3));
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 6U, 2));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowAfterCondition() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        // in if
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x == 123) {\n"
Packit 2035a7
               "        a = x;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x != 123) {\n"
Packit 2035a7
               "        a = x;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        // in else
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x == 123) {}\n"
Packit 2035a7
               "    else a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x != 123) {}\n"
Packit 2035a7
               "    else a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        // after if
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x == 10) {\n"
Packit 2035a7
               "        x++;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 10));
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 5U, 11));
Packit 2035a7
Packit 2035a7
        // !
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (!x) { a = x; }\n"
Packit 2035a7
               "    else a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int x, int y) {\n"
Packit 2035a7
               "    if (!(x&&y)) { return; }\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (!x) { { throw new string(); }; }\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // if (var)
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    if (x) { a = x; }\n"  // <- x is not 0
Packit 2035a7
               "    else { b = x; }\n"    // <- x is 0
Packit 2035a7
               "    c = x;\n"             // <- x might be 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // After while
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    while (x != 3) {}\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    while (11 != (x = dostuff())) {}\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 11));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    while (11 != (x = dostuff()) && y) {}\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 11));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    while (x = dostuff()) {}\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(const Token *x) {\n" // #5866
Packit 2035a7
               "    x = x->next();\n"
Packit 2035a7
               "    while (x) { x = x->next(); }\n"
Packit 2035a7
               "    if (x->str()) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(const Token *x) {\n"
Packit 2035a7
               "  while (0 != (x = x->next)) {}\n"
Packit 2035a7
               "  x->ab = 0;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(const Token* x) {\n"
Packit 2035a7
               "  while (0 != (x = x->next)) {}\n"
Packit 2035a7
               "  if (x->str) {\n" // <- possible value 0
Packit 2035a7
               "    x = y;\n" // <- this caused some problem
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // conditional code after if/else/while
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  if (x == 2) {}\n"
Packit 2035a7
               "  if (x > 0)\n"
Packit 2035a7
               "    a = x;\n"  // <- TODO, x can be 2
Packit 2035a7
               "  else\n"
Packit 2035a7
               "    b = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 2));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 2));
Packit 2035a7
Packit 2035a7
        // condition with 2nd variable
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  int y = 0;\n"
Packit 2035a7
               "  if (x == 7) { y = 1; }\n"
Packit 2035a7
               "  if (!y)\n"
Packit 2035a7
               "    a = x;\n" // <- x can not be 7 here
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 7));
Packit 2035a7
Packit 2035a7
        code = "void f(struct X *x) {\n"
Packit 2035a7
               "  bool b = TRUE;\n"
Packit 2035a7
               "  if(x) { }\n"
Packit 2035a7
               "  else\n"
Packit 2035a7
               "    b = FALSE;\n"
Packit 2035a7
               "  if (b)\n"
Packit 2035a7
               "    abc(x->value);\n" // <- x is not 0
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 0));
Packit 2035a7
Packit 2035a7
        // In condition, after && and ||
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  a = (x != 3 ||\n"
Packit 2035a7
               "       x);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  a = (x == 4 &&\n"
Packit 2035a7
               "       x);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 4));
Packit 2035a7
Packit 2035a7
        // protected usage with &&
Packit 2035a7
        code = "void f(const Token* x) {\n"
Packit 2035a7
               "    if (x) {}\n"
Packit 2035a7
               "    for (; x && \n"
Packit 2035a7
               "         x->str() != y; x = x->next()) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f(const Token* x) {\n"
Packit 2035a7
               "    if (x) {}\n"
Packit 2035a7
               "    if (x && \n"
Packit 2035a7
               "        x->str() != y) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        // return
Packit 2035a7
        code = "void f(int x) {\n" // #6024
Packit 2035a7
               "  if (x == 5) {\n"
Packit 2035a7
               "    if (z) return; else return;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 5));
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n" // #6730
Packit 2035a7
               "  if (x == 5) {\n"
Packit 2035a7
               "    if (z) continue; else throw e;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 5));
Packit 2035a7
Packit 2035a7
        // TODO: float
Packit 2035a7
        code = "void f(float x) {\n"
Packit 2035a7
               "  if (x == 0.5) {}\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // aliased variable
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 1;\n"
Packit 2035a7
               "  int *data = &x;\n"
Packit 2035a7
               "  if (!x) {\n"
Packit 2035a7
               "    calc(data);\n"
Packit 2035a7
               "    a = x;\n"  // <- x might be changed by calc
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForwardCompoundAssign() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    x += 43;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 166));
Packit 2035a7
        ASSERT_EQUALS("2,Assignment 'x=123', assigned value is 123\n"
Packit 2035a7
                      "3,Compound assignment '+=', assigned value is 166\n",
Packit 2035a7
                      getErrorPathForX(code, 4U));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 123;\n"
Packit 2035a7
               "    x /= 0;\n" // don't crash when evaluating x/=0
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    float x = 123.45;\n"
Packit 2035a7
               "    x += 67;\n"
Packit 2035a7
               "    return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 123.45F + 67, 0.01F));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForwardCorrelatedVariables() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f(int x = 0) {\n"
Packit 2035a7
               "  bool zero(x==0);\n"
Packit 2035a7
               "  if (zero) a = x;\n"  // <- x is 0
Packit 2035a7
               "  else b = x;\n"  // <- x is not 0
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForwardFunction() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "class C {\n"
Packit 2035a7
               "public:\n"
Packit 2035a7
               "  C(int &i);\n" // non-const argument => might be changed
Packit 2035a7
               "};\n"
Packit 2035a7
               "int f() {\n"
Packit 2035a7
               "  int x=1;\n"
Packit 2035a7
               "  C c(x);\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 8U, 1));
Packit 2035a7
Packit 2035a7
        code = "class C {\n"
Packit 2035a7
               "public:\n"
Packit 2035a7
               "  C(const int &i);\n" // const argument => is not changed
Packit 2035a7
               "};\n"
Packit 2035a7
               "int f() {\n"
Packit 2035a7
               "  int x=1;\n"
Packit 2035a7
               "  C c(x);\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 8U, 1));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForwardTernary() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "int f() {\n"
Packit 2035a7
               "  int x=5;\n"
Packit 2035a7
               "  a = b ? init1(&x) : init2(&x);\n"
Packit 2035a7
               "  return 1 + x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 5));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 5));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForwardLambda() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x=1;\n"
Packit 2035a7
               "  auto f = [&](){ a=x; }\n"  // x is not 1
Packit 2035a7
               "  x = 2;\n"
Packit 2035a7
               "  f();\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 1));
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x=3;\n"
Packit 2035a7
               "  auto f = [&](){ a=x; }\n"  // todo: x is 3
Packit 2035a7
               "  f();\n"
Packit 2035a7
               "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 3));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowBitAnd() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "int f(int a) {\n"
Packit 2035a7
               "  int x = a & 0x80;\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code,3U,0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code,3U,0x80));
Packit 2035a7
Packit 2035a7
        code = "int f(int a) {\n"
Packit 2035a7
               "  int x = a & 0x80 ? 1 : 2;\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code,3U,0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code,3U,0x80));
Packit 2035a7
Packit 2035a7
        code = "int f() {\n"
Packit 2035a7
               "  int x = (19 - 3) & 15;\n"
Packit 2035a7
               "  return x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code,3U,0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code,3U,16));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowSwitchVariable() {
Packit 2035a7
        const char *code;
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "    a = x - 1;\n"  // <- x can be 14
Packit 2035a7
               "    switch (x) {\n"
Packit 2035a7
               "    case 14: a=x+2; break;\n"  // <- x is 14
Packit 2035a7
               "    };\n"
Packit 2035a7
               "    a = x;\n"  // <- x can be 14
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testConditionalValueOfX(code, 2U, 14));
Packit 2035a7
        ASSERT_EQUALS(true, testConditionalValueOfX(code, 4U, 14));
Packit 2035a7
        ASSERT_EQUALS(true, testConditionalValueOfX(code, 6U, 14));
Packit 2035a7
Packit 2035a7
        ValueFlow::Value value1 = valueOfTok(code, "-");
Packit 2035a7
        ASSERT_EQUALS(13, value1.intvalue);
Packit 2035a7
        ASSERT(!value1.isKnown());
Packit 2035a7
Packit 2035a7
        ValueFlow::Value value2 = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(16, value2.intvalue);
Packit 2035a7
        ASSERT(value2.isKnown());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowForLoop() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    for (int x = 0; x < 10; x++)\n"
Packit 2035a7
               "        a[x] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 9));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 10));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (x = 2; x < 1; x++)\n"
Packit 2035a7
               "        a[x] = 0;\n" // <- not 2
Packit 2035a7
               "    b = x;\n" // 2
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 2));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 2));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (x = 2; x < 1; ++x)\n"
Packit 2035a7
               "        a[x] = 0;\n" // <- not 2
Packit 2035a7
               "    b = x;\n" // 2
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 2));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 2));
Packit 2035a7
Packit 2035a7
        code = "enum AB {A,B};\n" // enum => handled by valueForLoop2
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (x = 1; x < B; ++x)\n"
Packit 2035a7
               "        a[x] = 0;\n" // <- not 1
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f(int a) {\n"
Packit 2035a7
               "    for (int x = a; x < 10; x++)\n"
Packit 2035a7
               "        a[x] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 9));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    for (int x = 0; x < 10; x = x + 2)\n"
Packit 2035a7
               "        a[x] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 8));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 10));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    for (int x = 0; x < 10; x = x / 0)\n"
Packit 2035a7
               "        a[x] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); // don't crash
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    for (int x = 0; x < 10; x++)\n"
Packit 2035a7
               "        x<4 ?\n"
Packit 2035a7
               "        a[x] : 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 9));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 9));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    for (int x = 0; x < 10; x++)\n"
Packit 2035a7
               "        x==0 ?\n"
Packit 2035a7
               "        0 : a[x];\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #5223
Packit 2035a7
               "    for (int x = 0; x < 300 && x < 18; x++)\n"
Packit 2035a7
               "        x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 17));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 299));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (int i = 0; x = bar[i]; i++)\n"
Packit 2035a7
               "        x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    const char abc[] = \"abc\";\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (x = 0; abc[x] != '\\0'; x++) {}\n"
Packit 2035a7
               "    a[x] = 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #5939
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (int x = 0; (x = do_something()) != 0;)\n"
Packit 2035a7
               "        x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    for (int x = 0; x < 10 && y = do_something();)\n"
Packit 2035a7
               "        x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x,y;\n"
Packit 2035a7
               "    for (x = 0, y = 0; x < 10, y < 10; x++, y++)\n" // usage of ,
Packit 2035a7
               "        x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
Packit 2035a7
Packit 2035a7
        code = "void foo(double recoveredX) {\n"
Packit 2035a7
               "  for (double x = 1e-18; x < 1e40; x *= 1.9) {\n"
Packit 2035a7
               "    double relativeError = (x - recoveredX) / x;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // Ticket #7139
Packit 2035a7
        // "<<" in third expression of for
Packit 2035a7
        code = "void f(void) {\n"
Packit 2035a7
               "    int bit, x;\n"
Packit 2035a7
               "    for (bit = 1, x = 0; bit < 128; bit = bit << 1, x++) {\n"
Packit 2035a7
               "        z = x;\n"       // <- known value [0..6]
Packit 2035a7
               "    }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 6));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 7));
Packit 2035a7
Packit 2035a7
        // &&
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  for (int x = 0; x < 10; x++) {\n"
Packit 2035a7
               "    if (x > 1\n"
Packit 2035a7
               "        && x) {}" // <- x is not 0
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 4U, 9));
Packit 2035a7
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  for (int x = 0; x < 10; x++) {\n"
Packit 2035a7
               "    if (x < value\n"
Packit 2035a7
               "        && x) {}" // <- maybe x is not 9
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 9));
Packit 2035a7
Packit 2035a7
        // ||
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  for (int x = 0; x < 10; x++) {\n"
Packit 2035a7
               "    if (x == 0\n"
Packit 2035a7
               "        || x) {}" // <- x is not 0
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 4U, 9));
Packit 2035a7
Packit 2035a7
        // After loop
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = 0; x < 10; x++) {}\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 4U, 10));
Packit 2035a7
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = 0; 2 * x < 20; x++) {}\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 4U, 10));
Packit 2035a7
Packit 2035a7
        code = "void foo() {\n" // related with #887
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = 0; x < 20; x++) {}\n"
Packit 2035a7
               "  a = x++;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 20));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = 0; x < 5; x++) {}\n"
Packit 2035a7
               "  if (x == 5) {\n"
Packit 2035a7
               "    panic();\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  a = x;\n" // <- x can't be 5
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 7U, 5));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  for (x = 0; x < 5; x++) {}\n"
Packit 2035a7
               "  if (x < 5) {}\n"
Packit 2035a7
               "  else return;\n"
Packit 2035a7
               "  a = x;\n" // <- x can't be 5
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 5));
Packit 2035a7
Packit 2035a7
        // assert after for loop..
Packit 2035a7
        code = "static void f() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  int ctls[10];\n"
Packit 2035a7
               "  for (x = 0; x <= 10; x++) {\n"
Packit 2035a7
               "    if (cond)\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  assert(x <= 10);\n"
Packit 2035a7
               "  ctls[x] = 123;\n" // <- x can't be 11
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 9U, 11));
Packit 2035a7
Packit 2035a7
        // hang
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  for(int i = 0; i < 20; i++)\n"
Packit 2035a7
               "    n = (int)(i < 10 || abs(negWander) < abs(negTravel));\n"
Packit 2035a7
               "}";
Packit 2035a7
        testValueOfX(code,0,0); // <- don't hang
Packit 2035a7
Packit 2035a7
        // conditional code in loop
Packit 2035a7
        code = "void f(int mask) {\n" // #6000
Packit 2035a7
               "  for (int x = 10; x < 14; x++) {\n"
Packit 2035a7
               "    int bit = mask & (1 << i);\n"
Packit 2035a7
               "    if (bit) {\n"
Packit 2035a7
               "      if (bit == (1 << 10)) {}\n"
Packit 2035a7
               "      else { a = x; }\n" // <- x is not 10
Packit 2035a7
               "    }\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 6U, 10));
Packit 2035a7
Packit 2035a7
        // #7886 - valueFlowForLoop must be called after valueFlowAfterAssign
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int sz = 4;\n"
Packit 2035a7
               "  int x,y;\n"
Packit 2035a7
               "  for(x=0,y=0; x < sz && y < 10; x++)\n"
Packit 2035a7
               "    a = x;\n" // <- max value is 3
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowSubFunction() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) { return x; }\n"
Packit 2035a7
               "void f2(int x) {\n"
Packit 2035a7
               "    f1(123);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 1U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) { return x; }\n"
Packit 2035a7
               "void f2(int x) {\n"
Packit 2035a7
               "    f1(x);\n"
Packit 2035a7
               "    if (x==0){}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 1U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) {\n"
Packit 2035a7
               "    if (x == 0) return;\n"
Packit 2035a7
               "    int y = 1234 / x;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "    f1(0);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) {\n"
Packit 2035a7
               "    if (x == 0) return;\n"
Packit 2035a7
               "    int y = x;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "    f1(x&4;;\n" // possible {0,4}
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 4));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) { a=x; }\n"
Packit 2035a7
               "void f2(int y) { f1(y<123); }\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 1U, 0));
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 1U, 1));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) { a=(abc)x; }\n"
Packit 2035a7
               "void f2(int y) { f1(123); }\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 1U, 123));
Packit 2035a7
Packit 2035a7
        code = "void f1(int x) {\n"
Packit 2035a7
               "  x ?\n"
Packit 2035a7
               "  1024 / x :\n"
Packit 2035a7
               "  0; }\n"
Packit 2035a7
               "void f2() { f1(0); }";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 2U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "void f1(int *x) {\n"
Packit 2035a7
               "  if (x &&\n"
Packit 2035a7
               "      *x) {}\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() { f1(0); }";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 2U, 0));
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        // #5861 - fp with float
Packit 2035a7
        code = "void f1(float x) {\n"
Packit 2035a7
               "  return 1.0 / x;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() { f1(0.5); }";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
Packit 2035a7
Packit 2035a7
        code = "void dostuff(int x) {\n"
Packit 2035a7
               "  return x/x;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "void test(int x) {\n"
Packit 2035a7
               "  if(x==1) {}\n"
Packit 2035a7
               "  dostuff(x+1);\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 2U, 2));
Packit 2035a7
Packit 2035a7
        code = "void leaveNotifyEvent(const XCrossingEvent * const) { }\n"
Packit 2035a7
               "void motionNotifyEvent() {\n"
Packit 2035a7
               "    leaveNotifyEvent(0);\n"
Packit 2035a7
               "}";
Packit 2035a7
        testValueOfX(code, 2U, 2); // No complaint about Token::Match called with varid 0. (#6443)
Packit 2035a7
Packit 2035a7
        // #6560 - multivariables
Packit 2035a7
        code = "void f1(int x) {\n"
Packit 2035a7
               "  int a = x && y;\n"
Packit 2035a7
               "  int b = a ? x : 0;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "  f1(0);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
Packit 2035a7
Packit 2035a7
        code = "class A\n"
Packit 2035a7
               "{\n"
Packit 2035a7
               "    void f1(int x) { return x; }\n"
Packit 2035a7
               "    void f2(int x) {\n"
Packit 2035a7
               "        f1(123);\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "};";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "class A\n"
Packit 2035a7
               "{\n"
Packit 2035a7
               "    virtual void f1(int x) { return x; }\n"
Packit 2035a7
               "    void f2(int x) {\n"
Packit 2035a7
               "        f1(123);\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "};";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
Packit 2035a7
Packit 2035a7
        code = "void foo(int x, int y) {\n"
Packit 2035a7
               "  if (y == 1) {\n"
Packit 2035a7
               "    a = x;\n"  // <- x is not 1
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "\n"
Packit 2035a7
               "void bar() {\n"
Packit 2035a7
               "  foo(1, 10);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 1));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowFunctionReturn() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "int f1(int x) {\n"
Packit 2035a7
               "  return x+1;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "    x = 10 - f1(2);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(7, valueOfTok(code, "-").intvalue);
Packit 2035a7
        ASSERT_EQUALS(true, valueOfTok(code, "-").isKnown());
Packit 2035a7
Packit 2035a7
        code = "int add(int x, int y) {\n"
Packit 2035a7
               "  return x+y;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "    x = 1 * add(10+1,4);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(15, valueOfTok(code, "*").intvalue);
Packit 2035a7
        ASSERT_EQUALS(true, valueOfTok(code, "*").isKnown());
Packit 2035a7
Packit 2035a7
        code = "int one() { return 1; }\n"
Packit 2035a7
               "void f() { x = 1 * one(); }";
Packit 2035a7
        ASSERT_EQUALS(1, valueOfTok(code, "*").intvalue);
Packit 2035a7
        ASSERT_EQUALS(true, valueOfTok(code, "*").isKnown());
Packit 2035a7
Packit 2035a7
        code = "int add(int x, int y) {\n"
Packit 2035a7
               "  return x+y;\n"
Packit 2035a7
               "}\n"
Packit 2035a7
               "void f2() {\n"
Packit 2035a7
               "    x = 1 * add(1,add(2,3));\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(6, valueOfTok(code, "*").intvalue);
Packit 2035a7
        ASSERT_EQUALS(true, valueOfTok(code, "*").isKnown());
Packit 2035a7
Packit 2035a7
        code = "int f(int i, X x) {\n"
Packit 2035a7
               "    if (i)\n"
Packit 2035a7
               "        return g(std::move(x));\n"
Packit 2035a7
               "    g(x);\n"
Packit 2035a7
               "    return 0;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
Packit 2035a7
Packit 2035a7
        code = "class A\n"
Packit 2035a7
               "{\n"
Packit 2035a7
               "    int f1(int x) {\n"
Packit 2035a7
               "        return x+1;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    void f2() {\n"
Packit 2035a7
               "        x = 10 - f1(2);\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "};";
Packit 2035a7
        ASSERT_EQUALS(7, valueOfTok(code, "-").intvalue);
Packit 2035a7
        ASSERT_EQUALS(true, valueOfTok(code, "-").isKnown());
Packit 2035a7
Packit 2035a7
        code = "class A\n"
Packit 2035a7
               "{\n"
Packit 2035a7
               "    virtual int f1(int x) {\n"
Packit 2035a7
               "        return x+1;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "    void f2() {\n"
Packit 2035a7
               "        x = 10 - f1(2);\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "};";
Packit 2035a7
        ASSERT_EQUALS(7, valueOfTok(code, "-").intvalue);
Packit 2035a7
        ASSERT_EQUALS(false, valueOfTok(code, "-").isKnown());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowFunctionDefaultParameter() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "class continuous_src_time {\n"
Packit 2035a7
               "    continuous_src_time(std::complex<double> f, double st = 0.0, double et = infinity) {}\n"
Packit 2035a7
               "};";
Packit 2035a7
        testValueOfX(code, 2U, 2); // Don't crash (#6494)
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    bool isNotKnownValues(const char code[], const char str[]) {
Packit 2035a7
        const std::list<ValueFlow::Value> values = tokenValues(code, str);
Packit 2035a7
        for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
Packit 2035a7
            if (it->isKnown())
Packit 2035a7
                return false;
Packit 2035a7
        }
Packit 2035a7
        return true;
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void knownValue() {
Packit 2035a7
        const char *code;
Packit 2035a7
        ValueFlow::Value value;
Packit 2035a7
Packit 2035a7
        ASSERT(valueOfTok("x = 1;", "1").isKnown());
Packit 2035a7
Packit 2035a7
        // after assignment
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 1;\n"
Packit 2035a7
               "  return x + 2;\n" // <- known value
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(3, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            code = "void f() {\n"
Packit 2035a7
                   "  int x = 15;\n"
Packit 2035a7
                   "  if (x == 15) { x += 7; }\n" // <- condition is true
Packit 2035a7
                   "}";
Packit 2035a7
            value = valueOfTok(code, "==");
Packit 2035a7
            ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
            ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
            code = "int f() {\n"
Packit 2035a7
                   "    int a = 0, x = 0;\n"
Packit 2035a7
                   "    a = index();\n"
Packit 2035a7
                   "    if (a != 0)\n"
Packit 2035a7
                   "        x = next();\n"
Packit 2035a7
                   "    return x + 1;\n"
Packit 2035a7
                   "}\n";
Packit 2035a7
            value = valueOfTok(code, "+");
Packit 2035a7
            ASSERT(value.isPossible());
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  if (ab) { x = 7; }\n"
Packit 2035a7
               "  return x + 2;\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(9, value.intvalue);
Packit 2035a7
        ASSERT(value.isPossible());
Packit 2035a7
Packit 2035a7
        code = "void f(int c) {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  if (c) {} else { x++; }\n"
Packit 2035a7
               "  return x + 2;\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "+"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(&x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(0 ? ptr : &x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(unknown ? ptr : &x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  fred.dostuff(x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void dostuff(int x);\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        value = valueOfTok(code, "<");
Packit 2035a7
        ASSERT_EQUALS(0, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        code = "void dostuff(int & x);\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void dostuff(const int & x);\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  dostuff(x);\n"
Packit 2035a7
               "  if (x < 0) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        value = valueOfTok(code, "<");
Packit 2035a7
        ASSERT_EQUALS(0, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  do {\n"
Packit 2035a7
               "    if (x < 0) {}\n"
Packit 2035a7
               "    fred.dostuff(x);\n"
Packit 2035a7
               "  } while (abc);\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  x = 4;\n"
Packit 2035a7
               "  while (1) {\n"
Packit 2035a7
               "    a = x+2;\n"
Packit 2035a7
               "    dostuff();\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "+"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  if (y) { dostuff(x); }\n"
Packit 2035a7
               "  if (!x) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "!"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  MACRO( v, { if (y) { x++; } } );\n"
Packit 2035a7
               "  if (!x) {}\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "!"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  for (int i = 0; i < 10; i++) {\n"
Packit 2035a7
               "    if (cond) {\n"
Packit 2035a7
               "      x = 1;\n"
Packit 2035a7
               "      break;\n"
Packit 2035a7
               "    }\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  if (!x) {}\n"  // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "!"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  switch (state) {\n"
Packit 2035a7
               "  case 1:\n"
Packit 2035a7
               "    x = 1;\n"
Packit 2035a7
               "    break;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "  if (!x) {}\n"  // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "!"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n" // #7049
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  switch (a) {\n"
Packit 2035a7
               "  case 1:\n"
Packit 2035a7
               "    x = 1;\n"
Packit 2035a7
               "  case 2:\n"
Packit 2035a7
               "    if (!x) {}\n" // <- possible value
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "!"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  while (!x) {\n" // <- possible value
Packit 2035a7
               "    scanf(\"%d\", &x);\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "!");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT(value.isPossible());
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "  do { } while (++x < 12);\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, "<"));
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  static int x = 0;\n"
Packit 2035a7
               "  return x + 1;\n" // <- known value
Packit 2035a7
               "}\n";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "  int x = 0;\n"
Packit 2035a7
               "a:\n"
Packit 2035a7
               "  a = x + 1;\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT(value.isPossible());
Packit 2035a7
Packit 2035a7
        // in conditional code
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  if (!x) {\n"
Packit 2035a7
               "    a = x+1;\n" // <- known value
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        code = "void f(int x) {\n"
Packit 2035a7
               "  if (a && 4==x && y) {\n"
Packit 2035a7
               "    a = x+12;\n" // <- known value
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(16, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        // after condition
Packit 2035a7
        code = "int f(int x) {\n"
Packit 2035a7
               "  if (x == 4) {}\n"
Packit 2035a7
               "  return x + 1;\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(5, value.intvalue);
Packit 2035a7
        ASSERT(value.isPossible());
Packit 2035a7
Packit 2035a7
        code = "int f(int x) {\n"
Packit 2035a7
               "  if (x < 2) {}\n"
Packit 2035a7
               "  else if (x >= 2) {}\n" // <- known value
Packit 2035a7
               "}";
Packit 2035a7
        value = valueOfTok(code, ">=");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        code = "int f(int x) {\n"
Packit 2035a7
               "  if (x < 2) {}\n"
Packit 2035a7
               "  else if (x > 2) {}\n" // <- possible value
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT(isNotKnownValues(code, ">"));
Packit 2035a7
Packit 2035a7
        // function
Packit 2035a7
        code = "int f(int x) { return x + 1; }\n" // <- possible value
Packit 2035a7
               "void a() { f(12); }";
Packit 2035a7
        value = valueOfTok(code, "+");
Packit 2035a7
        ASSERT_EQUALS(13, value.intvalue);
Packit 2035a7
        ASSERT(value.isPossible());
Packit 2035a7
Packit 2035a7
        // known and possible value
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x = 1;\n"
Packit 2035a7
               "    int y = 2 + x;\n" // <- known value, don't care about condition
Packit 2035a7
               "    if (x == 2) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true,  testValueOfX(code, 3U, 1)); // value of x can be 1
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 2)); // value of x can't be 2
Packit 2035a7
Packit 2035a7
        // calculation with known result
Packit 2035a7
        code = "int f(int x) { a = x & 0; }"; // <- & is 0
Packit 2035a7
        value = valueOfTok(code, "&";;
Packit 2035a7
        ASSERT_EQUALS(0, value.intvalue);
Packit 2035a7
        ASSERT(value.isKnown());
Packit 2035a7
Packit 2035a7
        // template parameters are not known
Packit 2035a7
        code = "template <int X> void f() { a = X; }\n"
Packit 2035a7
               "f<1>();";
Packit 2035a7
        value = valueOfTok(code, "1");
Packit 2035a7
        ASSERT_EQUALS(1, value.intvalue);
Packit 2035a7
        ASSERT_EQUALS(false, value.isKnown());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowSizeofForwardDeclaredEnum() {
Packit 2035a7
        const char *code = "enum E; sz=sizeof(E);";
Packit 2035a7
        valueOfTok(code, "="); // Don't crash (#7775)
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowGlobalVar() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    x = 4;\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 4));
Packit 2035a7
Packit 2035a7
        code = "int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    if (x == 4) {}\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 4U, 4));
Packit 2035a7
Packit 2035a7
        code = "int x;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "    x = 42;\n"
Packit 2035a7
               "    unknownFunction();\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 42));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowGlobalStaticVar() {
Packit 2035a7
        const char *code;
Packit 2035a7
Packit 2035a7
        code = "static int x = 321;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(true, testValueOfX(code, 3U, 321));
Packit 2035a7
Packit 2035a7
        code = "static int x = 321;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}"
Packit 2035a7
               "void other() { x=a; }\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
Packit 2035a7
Packit 2035a7
        code = "static int x = 321;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}"
Packit 2035a7
               "void other() { p = &x; }\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
Packit 2035a7
Packit 2035a7
        code = "static int x = 321;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}"
Packit 2035a7
               "void other() { x++; }\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
Packit 2035a7
Packit 2035a7
        code = "static int x = 321;\n"
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}"
Packit 2035a7
               "void other() { foo(x); }\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
Packit 2035a7
Packit 2035a7
        code = "static int x = 1;\n" // compound assignment
Packit 2035a7
               "void f() {\n"
Packit 2035a7
               "  a = x;\n"
Packit 2035a7
               "}"
Packit 2035a7
               "void other() { x += b; }\n";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 3U, 1));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowInlineAssembly() {
Packit 2035a7
        const char* code = "void f() {\n"
Packit 2035a7
                           "    int x = 42;\n"
Packit 2035a7
                           "    asm(\"\");\n"
Packit 2035a7
                           "    a = x;\n"
Packit 2035a7
                           "}";
Packit 2035a7
        ASSERT_EQUALS(false, testValueOfX(code, 5U, 42));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void valueFlowUninit() {
Packit 2035a7
        const char* code;
Packit 2035a7
        std::list<ValueFlow::Value> values;
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    switch (x) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        values = tokenValues(code, "x )");
Packit 2035a7
        ASSERT_EQUALS(true, values.size()==1U && values.front().isUninitValue());
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    C *c;\n"
Packit 2035a7
               "    if (c->x() == 4) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        values = tokenValues(code, "c .");
Packit 2035a7
        ASSERT_EQUALS(true, values.size()==1U && values.front().isUninitValue());
Packit 2035a7
Packit 2035a7
        code = "void f() {\n"
Packit 2035a7
               "    int **x;\n"
Packit 2035a7
               "    y += 10;\n"
Packit 2035a7
               "    x = dostuff(sizeof(*x)*y);\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(0U, tokenValues(code, "x )").size());
Packit 2035a7
Packit 2035a7
        // #8036
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    f(x=3), return x+3;\n"
Packit 2035a7
               "}";
Packit 2035a7
        ASSERT_EQUALS(0U, tokenValues(code, "x +").size());
Packit 2035a7
Packit 2035a7
        // #8195
Packit 2035a7
        code = "void foo(std::istream &is) {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  if (is >> x) {\n"
Packit 2035a7
               "    a = x;\n"
Packit 2035a7
               "  }\n"
Packit 2035a7
               "}";
Packit 2035a7
        values = tokenValues(code, "x ; }");
Packit 2035a7
        ASSERT_EQUALS(true, values.empty());
Packit 2035a7
Packit 2035a7
        // return (#8173)
Packit 2035a7
        code = "int repeat() {\n"
Packit 2035a7
               "  const char *n;\n"
Packit 2035a7
               "  return((n=42) && *n == 'A');\n"
Packit 2035a7
               "}";
Packit 2035a7
        values = tokenValues(code, "n ==");
Packit 2035a7
        ASSERT_EQUALS(true, values.size() != 1U || !values.front().isUninitValue());
Packit 2035a7
Packit 2035a7
        // #8233
Packit 2035a7
        code = "void foo() {\n"
Packit 2035a7
               "  int x;\n"
Packit 2035a7
               "  int y = 1;\n"
Packit 2035a7
               "  if (y>1)\n"
Packit 2035a7
               "    x = 1;\n"
Packit 2035a7
               "  else\n"
Packit 2035a7
               "    x = 1;\n"
Packit 2035a7
               "  if (x>1) {}\n"
Packit 2035a7
               "}";
Packit 2035a7
        values = tokenValues(code, "x >");
Packit 2035a7
        ASSERT_EQUALS(true, values.size() == 1U && values.front().isIntValue());
Packit 2035a7
Packit 2035a7
        // #8348 - noreturn else
Packit 2035a7
        code = "int test_input_int(int a, int b) {\n"
Packit 2035a7
               "    int x;\n"
Packit 2035a7
               "    if (a == 1)\n"
Packit 2035a7
               "        x = b;\n"
Packit 2035a7
               "    else\n"
Packit 2035a7
               "        abort();\n"
Packit 2035a7
               "    a = x + 1;\n"
Packit 2035a7
               "}\n";
Packit 2035a7
        values = tokenValues(code, "x +");
Packit 2035a7
        ASSERT_EQUALS(true, values.empty());
Packit 2035a7
    }
Packit 2035a7
};
Packit 2035a7
Packit 2035a7
REGISTER_TEST(TestValueFlow)