Fix #11191 FP moduloofone with pow() (#4312)

This commit is contained in:
chrchr-github 2022-07-28 22:11:23 +02:00 committed by GitHub
parent 898ad314ab
commit c340b6ae6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 1393 deletions

View File

@ -709,133 +709,145 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
return v;
};
functions["atan2"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::atan2(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["remainder"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::remainder(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["nextafter"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::nextafter(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["nexttoward"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::nexttoward(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["hypot"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::hypot(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["fdim"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::fdim(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["fmax"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::fmax(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["fmin"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::fmin(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["fmod"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::fmod(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["pow"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::pow(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["scalbln"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::scalbln(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;
};
functions["ldexp"] = [](const std::vector<ValueFlow::Value>& args) {
if (args.size() != 2)
return ValueFlow::Value::unknown();
ValueFlow::Value v = args[0];
if (!v.isFloatValue() && !v.isIntValue())
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
return v.isFloatValue() || v.isIntValue();
}))
return ValueFlow::Value::unknown();
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
ValueFlow::Value v;
combineValueProperties(args[0], args[1], &v);
v.floatValue = std::ldexp(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
v.valueType = ValueFlow::Value::ValueType::FLOAT;
return v;

View File

@ -500,7 +500,7 @@ static bool isNumeric(const ValueFlow::Value& value) {
return value.isIntValue() || value.isFloatValue();
}
static void combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
void combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
{
if (value1.isKnown() && value2.isKnown())
result->setKnown();

View File

@ -535,4 +535,6 @@ CPPCHECKLIB std::vector<ValueFlow::Value> getLifetimeObjValues(const Token* tok,
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true);
void combineValueProperties(const ValueFlow::Value& value1, const ValueFlow::Value& value2, ValueFlow::Value* result);
#endif // valueflowH

View File

@ -10347,6 +10347,12 @@ private:
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(int i, int j) {\n" // #11191
" const int c = pow(2, i);\n"
" if (j % c) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void sameExpressionPointers() {

File diff suppressed because it is too large Load Diff