ValueFlow: Added float type

This commit is contained in:
Daniel Marjamäki 2016-11-13 22:59:56 +01:00
parent 4732667488
commit e1e9eacccc
4 changed files with 46 additions and 14 deletions

View File

@ -1325,10 +1325,17 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
for (std::list<ValueFlow::Value>::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) {
if (xml) { if (xml) {
out << " <value "; out << " <value ";
if (it->isTokValue()) switch (it->valueType) {
out << "tokvalue=\"" << it->tokvalue << '\"'; case ValueFlow::Value::INT:
else if (it->isIntValue())
out << "intvalue=\"" << it->intvalue << '\"'; 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) if (it->condition)
out << " condition-line=\"" << it->condition->linenr() << '\"'; out << " condition-line=\"" << it->condition->linenr() << '\"';
if (it->isKnown()) if (it->isKnown())
@ -1341,10 +1348,17 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
else { else {
if (it != tok->values.begin()) if (it != tok->values.begin())
out << ","; out << ",";
if (it->isTokValue()) switch (it->valueType) {
out << it->tokvalue->str(); case ValueFlow::Value::INT:
else if (it->isIntValue())
out << it->intvalue; out << it->intvalue;
break;
case ValueFlow::Value::TOK:
out << it->tokvalue->str();
break;
case ValueFlow::Value::FLOAT:
out << it->floatValue;
break;
}
} }
} }
if (xml) if (xml)

View File

@ -598,6 +598,12 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
ValueFlow::Value value(MathLib::toLongNumber(tok->str())); ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value, settings); setTokenValue(const_cast<Token *>(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<Token *>(tok), value, settings);
} else if (tok->enumerator() && tok->enumerator()->value_known) { } else if (tok->enumerator() && tok->enumerator()->value_known) {
ValueFlow::Value value(tok->enumerator()->value); ValueFlow::Value value(tok->enumerator()->value);
value.setKnown(); value.setKnown();

View File

@ -33,8 +33,8 @@ class Settings;
namespace ValueFlow { namespace ValueFlow {
class CPPCHECKLIB Value { class CPPCHECKLIB Value {
public: 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) {} 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), varvalue(val), condition(c), 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 { bool operator==(const Value &rhs) const {
if (valueType != rhs.valueType) if (valueType != rhs.valueType)
@ -48,6 +48,11 @@ namespace ValueFlow {
if (tokvalue != rhs.tokvalue) if (tokvalue != rhs.tokvalue)
return false; return false;
break; break;
case FLOAT:
// TODO: Write some better comparison
if (floatValue > rhs.floatValue || floatValue < rhs.floatValue)
return false;
break;
}; };
return varvalue == rhs.varvalue && return varvalue == rhs.varvalue &&
@ -59,13 +64,16 @@ namespace ValueFlow {
valueKind == rhs.valueKind; valueKind == rhs.valueKind;
} }
enum ValueType { INT, TOK } valueType; enum ValueType { INT, TOK, FLOAT } valueType;
bool isIntValue() const { bool isIntValue() const {
return valueType == INT; return valueType == INT;
} }
bool isTokValue() const { bool isTokValue() const {
return valueType == TOK; return valueType == TOK;
} }
bool isFloatValue() const {
return valueType == FLOAT;
}
/** int value */ /** int value */
long long intvalue; 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. */ /** token value - the token that has the value. this is used for pointer aliases, strings, etc. */
const Token *tokvalue; const Token *tokvalue;
/** float value */
double floatValue;
/** For calculated values - variable value that calculated value depends on */ /** For calculated values - variable value that calculated value depends on */
long long varvalue; long long varvalue;

View File

@ -24,7 +24,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <cmath>
class TestValueFlow : public TestFixture { class TestValueFlow : public TestFixture {
public: public:
@ -91,7 +91,7 @@ private:
if (tok->str() == "x" && tok->linenr() == linenr) { if (tok->str() == "x" && tok->linenr() == linenr) {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++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; return true;
} }
} }
@ -111,7 +111,7 @@ private:
if (tok->str() == "x" && tok->linenr() == linenr) { if (tok->str() == "x" && tok->linenr() == linenr) {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++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; return true;
} }
} }
@ -130,7 +130,7 @@ private:
if (tok->str() == "x" && tok->linenr() == linenr) { if (tok->str() == "x" && tok->linenr() == linenr) {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++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; return true;
} }
} }
@ -162,11 +162,12 @@ private:
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) { ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
std::list<ValueFlow::Value> values = tokenValues(code, tokstr); std::list<ValueFlow::Value> 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() { void valueFlowNumber() {
ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue); 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(10, valueOfTok("enum {A=10,B=15}; x=A+0;", "+").intvalue);
ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue); ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue);
ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue); ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue);