diff --git a/cfg/std.cfg b/cfg/std.cfg index 6e01700c5..0d7462aa1 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -733,7 +733,7 @@ - + tgamma(arg1) false @@ -744,7 +744,7 @@ - + tgamma(arg1) false @@ -755,7 +755,7 @@ - + tgamma(arg1) false @@ -766,7 +766,7 @@ - + trunc(arg1) false @@ -777,7 +777,7 @@ - + trunc(arg1) false @@ -788,7 +788,7 @@ - + trunc(arg1) false @@ -3344,7 +3344,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + logb(arg1) false @@ -3355,7 +3355,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + logb(arg1) false @@ -3366,7 +3366,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + logb(arg1) false @@ -3580,7 +3580,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3591,7 +3591,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3602,7 +3602,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3613,7 +3613,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3625,7 +3625,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3637,7 +3637,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3649,7 +3649,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3660,7 +3660,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3671,7 +3671,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3682,7 +3682,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3696,7 +3696,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3710,7 +3710,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3724,7 +3724,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -3738,7 +3738,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -3752,7 +3752,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -4238,7 +4238,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + remainder(arg1,arg2) false @@ -4253,7 +4253,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + remainder(arg1,arg2) false @@ -4268,7 +4268,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + remainder(arg1,arg2) false @@ -4604,7 +4604,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false @@ -4615,7 +4615,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false @@ -4626,7 +4626,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index e81c8af53..55974f635 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -719,6 +719,39 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["remainder"] = [](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::remainder(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["nextafter"] = [](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::nextafter(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["nexttoward"] = [](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::nexttoward(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; functions["hypot"] = [](const std::vector& args) { if (args.size() != 2) return ValueFlow::Value::unknown(); @@ -785,6 +818,17 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["scalbln"] = [](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::scalbln(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; functions["ldexp"] = [](const std::vector& args) { if (args.size() != 2) return ValueFlow::Value::unknown(); @@ -939,6 +983,50 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["log1p"] = [](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::log1p(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["log2"] = [](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::log2(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["logb"] = [](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::logb(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["nearbyint"] = [](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::nearbyint(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; functions["sinh"] = [](const std::vector& args) { if (args.size() != 1) return ValueFlow::Value::unknown(); @@ -1005,6 +1093,39 @@ static std::unordered_map createBuiltinLibr v.valueType = ValueFlow::Value::ValueType::FLOAT; return v; }; + functions["round"] = [](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::round(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["tgamma"] = [](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::tgamma(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; + functions["trunc"] = [](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::trunc(value); + v.valueType = ValueFlow::Value::ValueType::FLOAT; + return v; + }; return functions; } diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index bdac23899..40758c1ea 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -99,6 +99,13 @@ int zerodiv_fdim() return 42 / i; } +int zerodiv_trunc() +{ + int i = std::trunc(0); + // cppcheck-suppress zerodiv + return 42 / i; +} + int zerodiv_ceil() { int i = std::ceil(0); @@ -162,6 +169,27 @@ int zerodiv_acosh() return 42 / i; } +int zerodiv_log1p() +{ + int i = std::log1p(0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_nearbyint() +{ + int i = std::nearbyint(0); + // cppcheck-suppress zerodiv + return 42 / i; +} + +int zerodiv_round() +{ + int i = std::round(0); + // cppcheck-suppress zerodiv + return 42 / i; +} + int zerodiv_sinh() { int i = std::sinh(0);