parent
898ad314ab
commit
c340b6ae6c
|
@ -709,133 +709,145 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["atan2"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["atan2"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::atan2(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["remainder"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["remainder"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::remainder(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["nextafter"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["nextafter"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::nextafter(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["nexttoward"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["nexttoward"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::nexttoward(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["hypot"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["hypot"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::hypot(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["fdim"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["fdim"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::fdim(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["fmax"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["fmax"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::fmax(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["fmin"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["fmin"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::fmin(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["fmod"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["fmod"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::fmod(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["pow"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["pow"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::pow(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["scalbln"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["scalbln"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::scalbln(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
functions["ldexp"] = [](const std::vector<ValueFlow::Value>& args) {
|
functions["ldexp"] = [](const std::vector<ValueFlow::Value>& args) {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2 || !std::all_of(args.begin(), args.end(), [](const ValueFlow::Value& v) {
|
||||||
return ValueFlow::Value::unknown();
|
return v.isFloatValue() || v.isIntValue();
|
||||||
ValueFlow::Value v = args[0];
|
}))
|
||||||
if (!v.isFloatValue() && !v.isIntValue())
|
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
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.floatValue = std::ldexp(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -500,7 +500,7 @@ static bool isNumeric(const ValueFlow::Value& value) {
|
||||||
return value.isIntValue() || value.isFloatValue();
|
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())
|
if (value1.isKnown() && value2.isKnown())
|
||||||
result->setKnown();
|
result->setKnown();
|
||||||
|
|
|
@ -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);
|
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
|
#endif // valueflowH
|
||||||
|
|
|
@ -10347,6 +10347,12 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void sameExpressionPointers() {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue