diff --git a/cfg/std.cfg b/cfg/std.cfg index d96383c0b..951323811 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -1498,7 +1498,7 @@ - + fabs(arg1) false @@ -1509,7 +1509,7 @@ - + fabs(arg1) false @@ -1520,7 +1520,7 @@ - + fabs(arg1) false @@ -1531,7 +1531,7 @@ - + fdim(arg1, arg2) false @@ -1545,7 +1545,7 @@ - + fdim(arg1, arg2) false @@ -1559,7 +1559,7 @@ - + fdim(arg1, arg2) false @@ -1649,7 +1649,7 @@ - + floor(arg1) false @@ -1660,7 +1660,7 @@ - + floor(arg1) false @@ -1671,7 +1671,7 @@ - + floor(arg1) false @@ -1733,7 +1733,7 @@ - + fmax(arg1,arg2) false @@ -1747,7 +1747,7 @@ - + fmax(arg1,arg2) false @@ -1761,7 +1761,7 @@ - + fmax(arg1,arg2) false @@ -1775,7 +1775,7 @@ - + fmin(arg1,arg2) false @@ -1789,7 +1789,7 @@ - + fmin(arg1,arg2) false @@ -1803,7 +1803,7 @@ - + fmin(arg1,arg2) false @@ -1817,7 +1817,7 @@ - + fmod(arg1,arg2) false @@ -1832,7 +1832,7 @@ - + fmod(arg1,arg2) false @@ -1847,7 +1847,7 @@ - + fmod(arg1,arg2) false diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 66b7c0969..53617c6ce 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -708,6 +708,50 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["fdim"] = [](const std::vector& args) { + if (args.size() != 2) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + 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& args) { + if (args.size() != 2) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + 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& args) { + if (args.size() != 2) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + 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& args) { + if (args.size() != 2) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + 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& args) { if (args.size() != 2) return ValueFlow::Value::unknown(); @@ -741,6 +785,17 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["floor"] = [](const std::vector& args) { + if (args.size() != 1) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + v.floatValue = std::floor(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; functions["sqrt"] = [](const std::vector& args) { if (args.size() != 1) return ValueFlow::Value::unknown(); @@ -803,7 +858,18 @@ static std::unordered_map createBuiltinLibr if (!v.isFloatValue() && !v.isIntValue()) return ValueFlow::Value::unknown(); double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; - v.floatValue = std::exp2(value); + v.floatValue = std::expm1(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["fabs"] = [](const std::vector& args) { + if (args.size() != 1) + return ValueFlow::Value::unknown(); + ValueFlow::Value v = args[0]; + if (!v.isFloatValue() && !v.isIntValue()) + return ValueFlow::Value::unknown(); + double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue; + v.floatValue = std::fabs(value); v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index f7b9fb7ef..0f6a1eef3 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -36,6 +36,48 @@ #include #include +int zerodiv_fmod() +{ + int i = std::fmod(0.0, 42.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_fmin() +{ + int i = std::fmin(0.0, 0.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_fmax() +{ + int i = std::fmax(0.0, 0.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_floor() +{ + int i = std::floor(0.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_fabs() +{ + int i = std::fabs(-0.0) + std::fabs(+0.0) + std::fabs(0.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_fdim() +{ + int i = std::fdim(1.0, 1.0); + // cppcheck-suppress zerodiv + return 42 / i; +} + int zerodiv_ceil() { int i = std::ceil(0); @@ -134,6 +176,13 @@ int zerodiv_sin() return 42 / i; } +int zerodiv_expm1() +{ + int i = std::expm1(0); + // cppcheck-suppress zerodiv + return 42 / i; +} + int moduloofone_cos() { int i = std::cos(0); @@ -141,13 +190,6 @@ int moduloofone_cos() return 42 % i; } -int moduloofone_expm1() -{ - int i = std::expm1(0); - // cppcheck-suppress moduloofone - return 42 % i; -} - int moduloofone_exp() { int i = std::exp(0);