From 2ff54c31c649a46373b5101e9bc3dfd78c8009c1 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 8 Oct 2021 23:24:58 -0500 Subject: [PATCH 01/10] Evaluate symbolic values --- lib/valueflow.cpp | 35 ++++++++++++++++++++++++++++++----- test/testvalueflow.cpp | 7 +++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index d570cc0a1ff..2f6b9bd3dc5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2186,24 +2186,37 @@ struct ValueFlowAnalyzer : Analyzer { virtual bool useSymbolicValues() const { return true; } + virtual bool useSymbolicValuesExact() const { + return false; + } - bool isSameSymbolicValue(const Token* tok, ErrorPath* errorPath = nullptr) const + bool isSameSymbolicValue(const Token* tok, const ValueFlow::Value ** value = nullptr, std::vector* result = nullptr) const { if (!useSymbolicValues()) return false; if (Token::Match(tok, "%assign%")) return false; + bool exact = useSymbolicValuesExact() || astIsBool(tok); for (const ValueFlow::Value& v : tok->values()) { if (!v.isSymbolicValue()) continue; if (!v.isKnown()) continue; - if (v.intvalue != 0) + if (exact && v.intvalue != 0) continue; if (match(v.tokvalue)) { - if (errorPath) - errorPath->insert(errorPath->end(), v.errorPath.begin(), v.errorPath.end()); + if (value) + *value = &v; return true; + } else if (!exact && !astIsBool(v.tokvalue)) { + std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); + if (!r.empty()) { + if (value) + *value = &v; + if (result) + *result = {r.front()}; + return true; + } } } return false; @@ -2383,7 +2396,15 @@ struct ValueFlowAnalyzer : Analyzer { // Make a copy of the value to modify it localValue = *value; value = &localValue; - isSameSymbolicValue(tok, &value->errorPath); + const ValueFlow::Value * symValue = nullptr; + std::vector e = {}; + isSameSymbolicValue(tok, &symValue, &e); + assert(symValue); + value->errorPath.insert(value->errorPath.end(), symValue->errorPath.begin(), symValue->errorPath.end()); + if (e.empty()) + value->intvalue += symValue->intvalue; + else + value->intvalue = e.front(); } // Read first when moving forward if (d == Direction::Forward && a.isRead()) @@ -2440,6 +2461,10 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { return true; } + virtual bool useSymbolicValuesExact() const OVERRIDE { + return !value.isIntValue(); + } + virtual void addErrorPath(const Token* tok, const std::string& s) OVERRIDE { value.errorPath.emplace_back(tok, s); } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index edd3577cd73..62d4de32465 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6357,6 +6357,13 @@ class TestValueFlow : public TestFixture { "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, "y", 0)); ASSERT_EQUALS(true, testValueOfXImpossible(code, 3U, "y", -1)); + + code = "void f(int y) {\n" + " int x = y - 1;\n" + " if (y == 1)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0)); } void valueFlowSmartPointer() From 4393bccdaff911586ed44dea0cd88d770343c0f3 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 8 Oct 2021 23:55:23 -0500 Subject: [PATCH 02/10] Fix FP with impossible values --- lib/valueflow.cpp | 4 ++-- test/testvalueflow.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2f6b9bd3dc5..96617f670b3 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2187,7 +2187,7 @@ struct ValueFlowAnalyzer : Analyzer { return true; } virtual bool useSymbolicValuesExact() const { - return false; + return true; } bool isSameSymbolicValue(const Token* tok, const ValueFlow::Value ** value = nullptr, std::vector* result = nullptr) const @@ -2462,7 +2462,7 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { } virtual bool useSymbolicValuesExact() const OVERRIDE { - return !value.isIntValue(); + return !value.isIntValue() || value.isImpossible(); } virtual void addErrorPath(const Token* tok, const std::string& s) OVERRIDE { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 62d4de32465..7a0d3abad1f 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6364,6 +6364,21 @@ class TestValueFlow : public TestFixture { " int a = x;\n" "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0)); + + code = "struct A {\n" + " A* b();\n" + " int c() const;\n" + "};\n" + "void f(A *d) {\n" + " if (!d || d->c() != 1)\n" + " return;\n" + " A * y = d;\n" + " d = d->b();\n" + " A * x = d;\n" + " A* z = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 11U, "d", 0)); + ASSERT_EQUALS(false, testValueOfXImpossible(code, 11U, 0)); } void valueFlowSmartPointer() From 9e2a8dca5dedeae6c11d2163626e501e07712c95 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 17:06:19 -0500 Subject: [PATCH 03/10] Update value instead --- lib/valueflow.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 96617f670b3..f1053158643 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2190,7 +2190,7 @@ struct ValueFlowAnalyzer : Analyzer { return true; } - bool isSameSymbolicValue(const Token* tok, const ValueFlow::Value ** value = nullptr, std::vector* result = nullptr) const + bool isSameSymbolicValue(const Token* tok, ValueFlow::Value * value = nullptr) const { if (!useSymbolicValues()) return false; @@ -2205,16 +2205,18 @@ struct ValueFlowAnalyzer : Analyzer { if (exact && v.intvalue != 0) continue; if (match(v.tokvalue)) { - if (value) - *value = &v; + if (value) { + value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); + value->intvalue += v.intvalue; + } return true; } else if (!exact && !astIsBool(v.tokvalue)) { std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); if (!r.empty()) { - if (value) - *value = &v; - if (result) - *result = {r.front()}; + if (value) { + value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); + value->intvalue = r.front(); + } return true; } } @@ -2396,15 +2398,7 @@ struct ValueFlowAnalyzer : Analyzer { // Make a copy of the value to modify it localValue = *value; value = &localValue; - const ValueFlow::Value * symValue = nullptr; - std::vector e = {}; - isSameSymbolicValue(tok, &symValue, &e); - assert(symValue); - value->errorPath.insert(value->errorPath.end(), symValue->errorPath.begin(), symValue->errorPath.end()); - if (e.empty()) - value->intvalue += symValue->intvalue; - else - value->intvalue = e.front(); + isSameSymbolicValue(tok, &localValue); } // Read first when moving forward if (d == Direction::Forward && a.isRead()) From 13fce106d3e196d03ecedb607a8400da9b88b110 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 18:33:27 -0500 Subject: [PATCH 04/10] Evaluate with bigint --- lib/analyzer.h | 5 +++-- lib/forwardanalyzer.cpp | 4 ++-- lib/reverseanalyzer.cpp | 2 +- lib/valueflow.cpp | 26 ++++++++++++++------------ test/testcondition.cpp | 2 +- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/lib/analyzer.h b/lib/analyzer.h index 224a1c877ec..deebd5fba1d 100644 --- a/lib/analyzer.h +++ b/lib/analyzer.h @@ -20,6 +20,7 @@ #define analyzerH #include "config.h" +#include "mathlib.h" #include #include #include @@ -155,8 +156,8 @@ struct Analyzer { /// Update the state of the value virtual void update(Token* tok, Action a, Direction d) = 0; /// Try to evaluate the value of a token(most likely a condition) - virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const = 0; - std::vector evaluate(const Token* tok, const Token* ctx = nullptr) const { + virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const = 0; + std::vector evaluate(const Token* tok, const Token* ctx = nullptr) const { return evaluate(Evaluate::Integral, tok, ctx); } /// Lower any values to possible diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 7a717e8796b..ce50a47b2b2 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -74,7 +74,7 @@ struct ForwardTraversal { std::pair evalCond(const Token* tok, const Token* ctx = nullptr) const { if (!tok) return std::make_pair(false, false); - std::vector result = analyzer->evaluate(tok, ctx); + std::vector result = analyzer->evaluate(tok, ctx); // TODO: We should convert to bool bool checkThen = std::any_of(result.begin(), result.end(), [](int x) { return x != 0; @@ -600,7 +600,7 @@ struct ForwardTraversal { if (conTok && updateRecursive(conTok) == Progress::Break) return Break(); bool isEmpty = false; - std::vector result = analyzer->evaluate(Analyzer::Evaluate::ContainerEmpty, conTok); + std::vector result = analyzer->evaluate(Analyzer::Evaluate::ContainerEmpty, conTok); if (result.empty()) analyzer->assume(conTok, false, Analyzer::Assume::ContainerEmpty); else diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 1ecedc8e4df..56927ee1105 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -18,7 +18,7 @@ struct ReverseTraversal { const Settings* settings; std::pair evalCond(const Token* tok) { - std::vector result = analyzer->evaluate(tok); + std::vector result = analyzer->evaluate(tok); // TODO: We should convert to bool bool checkThen = std::any_of(result.begin(), result.end(), [](int x) { return x == 1; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5b3701a8508..08908950d60 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2080,7 +2080,7 @@ struct ValueFlowAnalyzer : Analyzer { // Check if its assigned to the same value if (value && !value->isImpossible() && Token::simpleMatch(tok->astParent(), "=") && astIsLHS(tok) && astIsIntegral(tok->astParent()->astOperand2(), false)) { - std::vector result = evaluate(Evaluate::Integral, tok->astParent()->astOperand2()); + std::vector result = evaluate(Evaluate::Integral, tok->astParent()->astOperand2()); if (!result.empty() && value->equalTo(result.front())) return Action::Idempotent; } @@ -2187,8 +2187,11 @@ struct ValueFlowAnalyzer : Analyzer { virtual bool useSymbolicValues() const { return true; } - virtual bool useSymbolicValuesExact() const { - return true; + + const Token* findMatch(const Token* tok) const { + return findAstNode(tok, [&](const Token* child) { + return match(child); + }); } bool isSameSymbolicValue(const Token* tok, ValueFlow::Value * value = nullptr) const @@ -2197,7 +2200,10 @@ struct ValueFlowAnalyzer : Analyzer { return false; if (Token::Match(tok, "%assign%")) return false; - bool exact = useSymbolicValuesExact() || astIsBool(tok); + const ValueFlow::Value* currValue = getValue(tok); + if (!currValue) + return false; + const bool exact = !currValue->isIntValue() || currValue->isImpossible(); for (const ValueFlow::Value& v : tok->values()) { if (!v.isSymbolicValue()) continue; @@ -2211,8 +2217,8 @@ struct ValueFlowAnalyzer : Analyzer { value->intvalue += v.intvalue; } return true; - } else if (!exact && !astIsBool(v.tokvalue)) { - std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); + } else if (!exact && findMatch(v.tokvalue)) { + std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); if (!r.empty()) { if (value) { value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); @@ -2317,11 +2323,11 @@ struct ValueFlowAnalyzer : Analyzer { return Action::None; } - virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const OVERRIDE { + virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const OVERRIDE { if (e == Evaluate::Integral) { if (tok->hasKnownIntValue()) return {static_cast(tok->values().front().intvalue)}; - std::vector result; + std::vector result; ProgramMemory pm = pms.get(tok, ctx, getProgramState()); if (Token::Match(tok, "&&|%oror%")) { if (conditionIsTrue(tok, pm)) @@ -2456,10 +2462,6 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { return true; } - virtual bool useSymbolicValuesExact() const OVERRIDE { - return !value.isIntValue() || value.isImpossible(); - } - virtual void addErrorPath(const Token* tok, const std::string& s) OVERRIDE { value.errorPath.emplace_back(tok, s); } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index a9c3e576d5d..9281961cfb0 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -3834,7 +3834,7 @@ class TestCondition : public TestFixture { " return (index++) >= s;\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:6]: (style) Condition '(index++)>=s' is always false\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:6]: (style) Condition '(index++)>=s' is always false\n", errout.str()); check("struct a {\n" " a *b() const;\n" From 6c01ee31b9614572149c9cf21b9dc43187dde30a Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 19:10:02 -0500 Subject: [PATCH 05/10] Add test for calulation --- lib/valueflow.cpp | 3 ++- test/testvalueflow.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 08908950d60..10a0d25db12 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2217,12 +2217,13 @@ struct ValueFlowAnalyzer : Analyzer { value->intvalue += v.intvalue; } return true; - } else if (!exact && findMatch(v.tokvalue)) { + } else if (!exact && findMatch(v.tokvalue) && currValue->bound == ValueFlow::Value::Bound::Point) { std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); if (!r.empty()) { if (value) { value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); value->intvalue = r.front(); + value->bound = v.bound; } return true; } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 7a0d3abad1f..ec604d88a96 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6365,6 +6365,20 @@ class TestValueFlow : public TestFixture { "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0)); + code = "void f(int y) {\n" + " int x = y * y;\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 4)); + + code = "void f(int x, int y) {\n" + " if (x == y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 4)); + code = "struct A {\n" " A* b();\n" " int c() const;\n" From e5044820ceb57f0c2f24640c561fb94a878d715a Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 21:39:55 -0500 Subject: [PATCH 06/10] Handle impossible symbolic values --- lib/valueflow.cpp | 26 ++++++++++++++------------ test/testvalueflow.cpp | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 10a0d25db12..f5894a4a33a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2207,26 +2207,28 @@ struct ValueFlowAnalyzer : Analyzer { for (const ValueFlow::Value& v : tok->values()) { if (!v.isSymbolicValue()) continue; - if (!v.isKnown()) + const bool toImpossible = v.isImpossible() && currValue->isKnown(); + if (!v.isKnown() && !toImpossible) continue; if (exact && v.intvalue != 0) continue; + std::vector r; + ValueFlow::Value::Bound bound = currValue->bound; if (match(v.tokvalue)) { + r = {currValue->intvalue}; + } else if (!exact && findMatch(v.tokvalue) && bound == ValueFlow::Value::Bound::Point) { + r = evaluate(Evaluate::Integral, v.tokvalue, tok); + bound = v.bound; + } + if (!r.empty()) { if (value) { value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); - value->intvalue += v.intvalue; + value->intvalue = r.front() + v.intvalue; + if (toImpossible) + value->setImpossible(); + value->bound = bound; } return true; - } else if (!exact && findMatch(v.tokvalue) && currValue->bound == ValueFlow::Value::Bound::Point) { - std::vector r = evaluate(Evaluate::Integral, v.tokvalue, tok); - if (!r.empty()) { - if (value) { - value->errorPath.insert(value->errorPath.end(), v.errorPath.begin(), v.errorPath.end()); - value->intvalue = r.front(); - value->bound = v.bound; - } - return true; - } } } return false; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index ec604d88a96..c949dea4475 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6379,6 +6379,27 @@ class TestValueFlow : public TestFixture { "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 4)); + code = "void f(int x, int y) {\n" + " if (x > y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 4)); + + code = "void f(int x, int y) {\n" + " if (x != y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 4)); + + code = "void f(int x, int y) {\n" + " if (x >= y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 3)); + code = "struct A {\n" " A* b();\n" " int c() const;\n" From 44013f20855a756d2d653be0c58516b12c597008 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 22:01:22 -0500 Subject: [PATCH 07/10] Update bounds --- lib/valueflow.cpp | 5 +++-- test/testvalueflow.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f5894a4a33a..55ab187465c 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2216,9 +2216,10 @@ struct ValueFlowAnalyzer : Analyzer { ValueFlow::Value::Bound bound = currValue->bound; if (match(v.tokvalue)) { r = {currValue->intvalue}; - } else if (!exact && findMatch(v.tokvalue) && bound == ValueFlow::Value::Bound::Point) { + } else if (!exact && findMatch(v.tokvalue)) { r = evaluate(Evaluate::Integral, v.tokvalue, tok); - bound = v.bound; + if (bound == ValueFlow::Value::Bound::Point) + bound = v.bound; } if (!r.empty()) { if (value) { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index c949dea4475..410c1b7b82c 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6400,6 +6400,13 @@ class TestValueFlow : public TestFixture { "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 3)); + code = "void f(int x, int y) {\n" + " if (x == y*y)\n" + " if (y > 2)\n" + " int a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 9)); + code = "struct A {\n" " A* b();\n" " int c() const;\n" From cdca20d205883e4839d138ced1e912911dd303b5 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 22:08:13 -0500 Subject: [PATCH 08/10] Add TODO test case --- test/testvalueflow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 410c1b7b82c..7010251d07e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6400,6 +6400,13 @@ class TestValueFlow : public TestFixture { "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 3)); + code = "void f(int x, int y) {\n" + " if (x == y*y)\n" + " if (y != 2)\n" + " int a = x;\n" + "}\n"; + TODO_ASSERT_EQUALS(true, false, testValueOfXImpossible(code, 4U, 4)); + code = "void f(int x, int y) {\n" " if (x == y*y)\n" " if (y > 2)\n" From f04ca16c4a5946606b56756e9090062244f98489 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 9 Oct 2021 22:10:24 -0500 Subject: [PATCH 09/10] Format --- lib/analyzer.h | 3 +- lib/forwardanalyzer.cpp | 3 +- lib/valueflow.cpp | 10 +++-- test/testvalueflow.cpp | 86 ++++++++++++++++++++--------------------- 4 files changed, 53 insertions(+), 49 deletions(-) diff --git a/lib/analyzer.h b/lib/analyzer.h index deebd5fba1d..dd4fecdb10e 100644 --- a/lib/analyzer.h +++ b/lib/analyzer.h @@ -157,7 +157,8 @@ struct Analyzer { virtual void update(Token* tok, Action a, Direction d) = 0; /// Try to evaluate the value of a token(most likely a condition) virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const = 0; - std::vector evaluate(const Token* tok, const Token* ctx = nullptr) const { + std::vector evaluate(const Token* tok, const Token* ctx = nullptr) const + { return evaluate(Evaluate::Integral, tok, ctx); } /// Lower any values to possible diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index ce50a47b2b2..46575479d6d 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -600,7 +600,8 @@ struct ForwardTraversal { if (conTok && updateRecursive(conTok) == Progress::Break) return Break(); bool isEmpty = false; - std::vector result = analyzer->evaluate(Analyzer::Evaluate::ContainerEmpty, conTok); + std::vector result = + analyzer->evaluate(Analyzer::Evaluate::ContainerEmpty, conTok); if (result.empty()) analyzer->assume(conTok, false, Analyzer::Assume::ContainerEmpty); else diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 55ab187465c..35d8d532d82 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2188,13 +2188,14 @@ struct ValueFlowAnalyzer : Analyzer { return true; } - const Token* findMatch(const Token* tok) const { - return findAstNode(tok, [&](const Token* child) { + const Token* findMatch(const Token* tok) const + { + return findAstNode(tok, [&](const Token* child) { return match(child); }); } - bool isSameSymbolicValue(const Token* tok, ValueFlow::Value * value = nullptr) const + bool isSameSymbolicValue(const Token* tok, ValueFlow::Value* value = nullptr) const { if (!useSymbolicValues()) return false; @@ -2327,7 +2328,8 @@ struct ValueFlowAnalyzer : Analyzer { return Action::None; } - virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const OVERRIDE { + virtual std::vector evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const OVERRIDE + { if (e == Evaluate::Integral) { if (tok->hasKnownIntValue()) return {static_cast(tok->values().front().intvalue)}; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 7010251d07e..ebffa5cc247 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -6359,73 +6359,73 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(true, testValueOfXImpossible(code, 3U, "y", -1)); code = "void f(int y) {\n" - " int x = y - 1;\n" - " if (y == 1)\n" - " int a = x;\n" - "}\n"; + " int x = y - 1;\n" + " if (y == 1)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0)); code = "void f(int y) {\n" - " int x = y * y;\n" - " if (y == 2)\n" - " int a = x;\n" - "}\n"; + " int x = y * y;\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 4)); code = "void f(int x, int y) {\n" - " if (x == y*y)\n" - " if (y == 2)\n" - " int a = x;\n" - "}\n"; + " if (x == y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 4)); code = "void f(int x, int y) {\n" - " if (x > y*y)\n" - " if (y == 2)\n" - " int a = x;\n" - "}\n"; + " if (x > y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 4)); code = "void f(int x, int y) {\n" - " if (x != y*y)\n" - " if (y == 2)\n" - " int a = x;\n" - "}\n"; + " if (x != y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 4)); code = "void f(int x, int y) {\n" - " if (x >= y*y)\n" - " if (y == 2)\n" - " int a = x;\n" - "}\n"; + " if (x >= y*y)\n" + " if (y == 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 3)); code = "void f(int x, int y) {\n" - " if (x == y*y)\n" - " if (y != 2)\n" - " int a = x;\n" - "}\n"; + " if (x == y*y)\n" + " if (y != 2)\n" + " int a = x;\n" + "}\n"; TODO_ASSERT_EQUALS(true, false, testValueOfXImpossible(code, 4U, 4)); code = "void f(int x, int y) {\n" - " if (x == y*y)\n" - " if (y > 2)\n" - " int a = x;\n" - "}\n"; + " if (x == y*y)\n" + " if (y > 2)\n" + " int a = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 9)); code = "struct A {\n" - " A* b();\n" - " int c() const;\n" - "};\n" - "void f(A *d) {\n" - " if (!d || d->c() != 1)\n" - " return;\n" - " A * y = d;\n" - " d = d->b();\n" - " A * x = d;\n" - " A* z = x;\n" - "}\n"; + " A* b();\n" + " int c() const;\n" + "};\n" + "void f(A *d) {\n" + " if (!d || d->c() != 1)\n" + " return;\n" + " A * y = d;\n" + " d = d->b();\n" + " A * x = d;\n" + " A* z = x;\n" + "}\n"; ASSERT_EQUALS(true, testValueOfX(code, 11U, "d", 0)); ASSERT_EQUALS(false, testValueOfXImpossible(code, 11U, 0)); } From 69d5cb040c6254d086e134d4e8b0711d35c718a4 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 10 Oct 2021 14:31:44 -0500 Subject: [PATCH 10/10] Revert --- lib/valueflow.cpp | 8 ++++---- test/testcondition.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3b80b934fd2..7754ad70d70 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -803,11 +803,11 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se // increment else if (parent->str() == "++") { for (const ValueFlow::Value &val : tok->values()) { - if (!val.isIntValue() && !val.isFloatValue()) + if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue()) continue; ValueFlow::Value v(val); if (parent == tok->previous()) { - if (v.isIntValue()) + if (v.isIntValue() || v.isSymbolicValue()) v.intvalue = v.intvalue + 1; else v.floatValue = v.floatValue + 1.0; @@ -819,11 +819,11 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se // decrement else if (parent->str() == "--") { for (const ValueFlow::Value &val : tok->values()) { - if (!val.isIntValue() && !val.isFloatValue()) + if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue()) continue; ValueFlow::Value v(val); if (parent == tok->previous()) { - if (v.isIntValue()) + if (v.isIntValue() || v.isSymbolicValue()) v.intvalue = v.intvalue - 1; else v.floatValue = v.floatValue - 1.0; diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 4c1843f79db..9281961cfb0 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -3826,6 +3826,16 @@ class TestCondition : public TestFixture { "}\n"); ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'z<1' is always false\n", errout.str()); + check("bool f(int &index, const int s, const double * const array, double & x) {\n" + " if (index >= s)\n" + " return false;\n" + " else {\n" + " x = array[index];\n" + " return (index++) >= s;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:6]: (style) Condition '(index++)>=s' is always false\n", errout.str()); + check("struct a {\n" " a *b() const;\n" "} c;\n"