Fix 11124: FP knownConditionTrueFalse with fruit (#4196)
* Update valueType * Allow comparisons * Fix compare op * Add test * Format * Fix FP * Format
This commit is contained in:
parent
8579feb3aa
commit
8945c151f5
|
@ -548,6 +548,11 @@ struct assign {
|
|||
}
|
||||
};
|
||||
|
||||
static bool isIntegralValue(const ValueFlow::Value& value)
|
||||
{
|
||||
return value.isIntValue() || value.isIteratorValue() || value.isSymbolicValue();
|
||||
}
|
||||
|
||||
static ValueFlow::Value evaluate(const std::string& op, const ValueFlow::Value& lhs, const ValueFlow::Value& rhs)
|
||||
{
|
||||
ValueFlow::Value result;
|
||||
|
@ -569,14 +574,33 @@ static ValueFlow::Value evaluate(const std::string& op, const ValueFlow::Value&
|
|||
return result;
|
||||
}
|
||||
}
|
||||
result.valueType = ValueFlow::Value::ValueType::INT;
|
||||
if (op == "+") {
|
||||
if (lhs.isIteratorValue())
|
||||
result.valueType = lhs.valueType;
|
||||
else if (rhs.isIteratorValue())
|
||||
result.valueType = rhs.valueType;
|
||||
} else if (lhs.valueType != rhs.valueType) {
|
||||
// Must be integral types
|
||||
if (!isIntegralValue(lhs) && !isIntegralValue(rhs))
|
||||
return ValueFlow::Value::unknown();
|
||||
// If not the same type then one must be int
|
||||
if (lhs.valueType != rhs.valueType && !lhs.isIntValue() && !rhs.isIntValue())
|
||||
return ValueFlow::Value::unknown();
|
||||
bool compareOp = contains({"==", "!=", "<", ">", ">=", "<="}, op);
|
||||
// Comparison must be the same type
|
||||
if (compareOp && lhs.valueType != rhs.valueType)
|
||||
return ValueFlow::Value::unknown();
|
||||
// Only add, subtract, and compare for non-integers
|
||||
if (!compareOp && !contains({"+", "-"}, op) && !lhs.isIntValue() && !rhs.isIntValue())
|
||||
return ValueFlow::Value::unknown();
|
||||
// Both cant be iterators for non-compare
|
||||
if (!compareOp && lhs.isIteratorValue() && rhs.isIteratorValue())
|
||||
return ValueFlow::Value::unknown();
|
||||
// Symbolic values must be in the same ring
|
||||
if (lhs.isSymbolicValue() && rhs.isSymbolicValue() && lhs.tokvalue != rhs.tokvalue)
|
||||
return ValueFlow::Value::unknown();
|
||||
if (!lhs.isIntValue() && !compareOp) {
|
||||
result.valueType = lhs.valueType;
|
||||
result.tokvalue = lhs.tokvalue;
|
||||
} else if (!rhs.isIntValue() && !compareOp) {
|
||||
result.valueType = rhs.valueType;
|
||||
result.tokvalue = rhs.tokvalue;
|
||||
} else {
|
||||
result.valueType = ValueFlow::Value::ValueType::INT;
|
||||
}
|
||||
bool error = false;
|
||||
result.intvalue = calculate(op, lhs.intvalue, rhs.intvalue, &error);
|
||||
|
|
|
@ -4364,6 +4364,32 @@ private:
|
|||
" return 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'b' is always false\n", errout.str());
|
||||
|
||||
// #11124
|
||||
check("struct Basket {\n"
|
||||
" std::vector<int> getApples() const;\n"
|
||||
" std::vector<int> getBananas() const; \n"
|
||||
"};\n"
|
||||
"int getFruit(const Basket & b, bool preferApples)\n"
|
||||
"{\n"
|
||||
" std::vector<int> apples = b.getApples();\n"
|
||||
" int apple = apples.empty() ? -1 : apples.front();\n"
|
||||
" std::vector<int> bananas = b.getBananas();\n"
|
||||
" int banana = bananas.empty() ? -1 : bananas.front();\n"
|
||||
" int fruit = std::max(apple, banana);\n"
|
||||
" if (fruit == -1)\n"
|
||||
" return fruit;\n"
|
||||
" if (std::min(apple, banana) != -1)\n"
|
||||
" fruit = preferApples ? apple : banana;\n"
|
||||
" return fruit;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f(const std::string & s, int i) {\n"
|
||||
" const char c = s[i];\n"
|
||||
" if (!std::isalnum(c)) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void alwaysTrueInfer() {
|
||||
|
|
Loading…
Reference in New Issue