From e1e9eacccc273cf4a4e3a9b6540d1f05d2aaa929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 13 Nov 2016 22:59:56 +0100 Subject: [PATCH] ValueFlow: Added float type --- lib/token.cpp | 26 ++++++++++++++++++++------ lib/valueflow.cpp | 6 ++++++ lib/valueflow.h | 17 ++++++++++++++--- test/testvalueflow.cpp | 11 ++++++----- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/lib/token.cpp b/lib/token.cpp index 84dc469ac..e6a6419c1 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1325,10 +1325,17 @@ void Token::printValueFlow(bool xml, std::ostream &out) const for (std::list::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) { if (xml) { out << " isTokValue()) - out << "tokvalue=\"" << it->tokvalue << '\"'; - else if (it->isIntValue()) + switch (it->valueType) { + case ValueFlow::Value::INT: out << "intvalue=\"" << it->intvalue << '\"'; + break; + case ValueFlow::Value::TOK: + out << "tokvalue=\"" << it->tokvalue << '\"'; + break; + case ValueFlow::Value::FLOAT: + out << "floatvalue=\"" << it->floatValue << '\"'; + break; + } if (it->condition) out << " condition-line=\"" << it->condition->linenr() << '\"'; if (it->isKnown()) @@ -1341,10 +1348,17 @@ void Token::printValueFlow(bool xml, std::ostream &out) const else { if (it != tok->values.begin()) out << ","; - if (it->isTokValue()) - out << it->tokvalue->str(); - else if (it->isIntValue()) + switch (it->valueType) { + case ValueFlow::Value::INT: out << it->intvalue; + break; + case ValueFlow::Value::TOK: + out << it->tokvalue->str(); + break; + case ValueFlow::Value::FLOAT: + out << it->floatValue; + break; + } } } if (xml) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 6f87c7f20..4ea75e144 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -598,6 +598,12 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti ValueFlow::Value value(MathLib::toLongNumber(tok->str())); value.setKnown(); setTokenValue(const_cast(tok), value, settings); + } else if (tok->isNumber() && MathLib::isFloat(tok->str())) { + ValueFlow::Value value; + value.valueType = ValueFlow::Value::FLOAT; + value.floatValue = MathLib::toDoubleNumber(tok->str()); + value.setKnown(); + setTokenValue(const_cast(tok), value, settings); } else if (tok->enumerator() && tok->enumerator()->value_known) { ValueFlow::Value value(tok->enumerator()->value); value.setKnown(); diff --git a/lib/valueflow.h b/lib/valueflow.h index 4b7b6eee2..8f40007a3 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -33,8 +33,8 @@ class Settings; namespace ValueFlow { class CPPCHECKLIB Value { public: - explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} - Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} + explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} + Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} bool operator==(const Value &rhs) const { if (valueType != rhs.valueType) @@ -48,6 +48,11 @@ namespace ValueFlow { if (tokvalue != rhs.tokvalue) return false; break; + case FLOAT: + // TODO: Write some better comparison + if (floatValue > rhs.floatValue || floatValue < rhs.floatValue) + return false; + break; }; return varvalue == rhs.varvalue && @@ -59,13 +64,16 @@ namespace ValueFlow { valueKind == rhs.valueKind; } - enum ValueType { INT, TOK } valueType; + enum ValueType { INT, TOK, FLOAT } valueType; bool isIntValue() const { return valueType == INT; } bool isTokValue() const { return valueType == TOK; } + bool isFloatValue() const { + return valueType == FLOAT; + } /** int value */ long long intvalue; @@ -73,6 +81,9 @@ namespace ValueFlow { /** token value - the token that has the value. this is used for pointer aliases, strings, etc. */ const Token *tokvalue; + /** float value */ + double floatValue; + /** For calculated values - variable value that calculated value depends on */ long long varvalue; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 273d8d0f8..974a84561 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -24,7 +24,7 @@ #include #include - +#include class TestValueFlow : public TestFixture { public: @@ -91,7 +91,7 @@ private: if (tok->str() == "x" && tok->linenr() == linenr) { std::list::const_iterator it; for (it = tok->values.begin(); it != tok->values.end(); ++it) { - if (it->intvalue == value && !it->tokvalue) + if (it->isIntValue() && it->intvalue == value) return true; } } @@ -111,7 +111,7 @@ private: if (tok->str() == "x" && tok->linenr() == linenr) { std::list::const_iterator it; for (it = tok->values.begin(); it != tok->values.end(); ++it) { - if (Token::simpleMatch(it->tokvalue, value)) + if (it->isTokValue() && Token::simpleMatch(it->tokvalue, value)) return true; } } @@ -130,7 +130,7 @@ private: if (tok->str() == "x" && tok->linenr() == linenr) { std::list::const_iterator it; for (it = tok->values.begin(); it != tok->values.end(); ++it) { - if (it->intvalue == value && !it->tokvalue && it->condition) + if (it->isIntValue() && it->intvalue == value && it->condition) return true; } } @@ -162,11 +162,12 @@ private: ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) { std::list values = tokenValues(code, tokstr); - return values.size() == 1U && !values.front().tokvalue ? values.front() : ValueFlow::Value(); + return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value(); } void valueFlowNumber() { ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue); + ASSERT(std::fabs(valueOfTok("x=0.5;", "0.5").floatValue - 0.5f) < 0.1f); ASSERT_EQUALS(10, valueOfTok("enum {A=10,B=15}; x=A+0;", "+").intvalue); ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue); ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue);