From 606bb7829741cf5452745d974eb1701f0677cc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 20 Dec 2016 19:32:21 +0100 Subject: [PATCH] ValueFlow: Better handling of casts --- lib/valueflow.cpp | 35 ++++++++++++++++++++++++++++++----- test/testother.cpp | 2 +- test/testvalueflow.cpp | 6 ++++-- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5dc8d2035..79921a840 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -284,6 +284,21 @@ static bool addValue(Token *tok, const ValueFlow::Value &value) return true; } +static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign sign, unsigned int bit) +{ + if (value.isFloatValue()) { + value.valueType = ValueFlow::Value::INT; + value.intvalue = value.floatValue; + } + if (bit < 64) { + value.intvalue &= (1ULL << bit) - 1ULL; + if (sign == ValueType::Sign::SIGNED && value.intvalue & (1ULL << (bit - 1ULL))) { + value.intvalue |= ~((1ULL << bit) - 1ULL); + } + } + return value; +} + /** set ValueFlow value and perform calculations if possible */ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Settings *settings) { @@ -294,13 +309,23 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti if (!parent) return; - // TODO: Cast.. - /* if (parent->str() == "(" && tok == parent->link()->next()) { - setTokenValue(parent,value,settings); - } else .. */ + const ValueType &valueType = ValueType::parseDecl(parent->next(), settings); + if (valueType.pointer) + setTokenValue(parent,value,settings); + else if (valueType.type == ValueType::Type::CHAR) + setTokenValue(parent, castValue(value, valueType.sign, settings->char_bit), settings); + else if (valueType.type == ValueType::Type::SHORT) + setTokenValue(parent, castValue(value, valueType.sign, settings->short_bit), settings); + else if (valueType.type == ValueType::Type::INT) + setTokenValue(parent, castValue(value, valueType.sign, settings->int_bit), settings); + else if (valueType.type == ValueType::Type::LONG) + setTokenValue(parent, castValue(value, valueType.sign, settings->long_bit), settings); + else if (valueType.type == ValueType::Type::LONGLONG) + setTokenValue(parent, castValue(value, valueType.sign, settings->long_long_bit), settings); + } - if (parent->str() == ":") { + else if (parent->str() == ":") { setTokenValue(parent,value,settings); } diff --git a/test/testother.cpp b/test/testother.cpp index 849b3c86d..e029e899c 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -271,7 +271,7 @@ private: check("void foo() {\n" " cout << 42 / (int)0;\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout.str()); } void zeroDiv2() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index cde61e9e3..5559f428a 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -378,8 +378,10 @@ private: ASSERT_EQUALS(0, valueOfTok("3 <= (a ? b : 2);", "<=").intvalue); ASSERT(tokenValues("(UNKNOWN_TYPE)123;","(").empty()); - ASSERT(tokenValues("(unsigned char)~0;", "(").empty()); // TODO: should get value 255 - ASSERT(tokenValues("(int)0;", "(").empty()); // TODO: should get value 0 + ASSERT_EQUALS(255, valueOfTok("(unsigned char)~0;", "(").intvalue); + ASSERT_EQUALS(0, valueOfTok("(int)0;", "(").intvalue); + ASSERT_EQUALS(0, valueOfTok("(UNKNOWN_TYPE*)0;","(").intvalue); + ASSERT_EQUALS(100, valueOfTok("(int)100.0;", "(").intvalue); // Don't calculate if there is UB ASSERT(tokenValues(";-1<<10;","<<").empty());