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) {
if (xml) {
out << " <value ";
if (it->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)

View File

@ -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<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) {
ValueFlow::Value value(tok->enumerator()->value);
value.setKnown();

View File

@ -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;

View File

@ -24,7 +24,7 @@
#include <vector>
#include <string>
#include <cmath>
class TestValueFlow : public TestFixture {
public:
@ -91,7 +91,7 @@ private:
if (tok->str() == "x" && tok->linenr() == linenr) {
std::list<ValueFlow::Value>::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<ValueFlow::Value>::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<ValueFlow::Value>::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<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() {
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);