| 1875 | } |
| 1876 | |
| 1877 | ValueFlow::Value evaluateLibraryFunction(const std::unordered_map<nonneg int, ValueFlow::Value>& args, |
| 1878 | const std::string& returnValue, |
| 1879 | const Settings& settings, |
| 1880 | bool cpp) |
| 1881 | { |
| 1882 | thread_local static std::unordered_map<std::string, |
| 1883 | std::function<ValueFlow::Value(const std::unordered_map<nonneg int, ValueFlow::Value>&, const Settings&)>> |
| 1884 | functions = {}; |
| 1885 | if (functions.count(returnValue) == 0) { |
| 1886 | |
| 1887 | std::unordered_map<nonneg int, const Token*> lookupVarId; |
| 1888 | std::shared_ptr<Token> expr = createTokenFromExpression(returnValue, settings, cpp, lookupVarId); |
| 1889 | |
| 1890 | functions[returnValue] = |
| 1891 | [lookupVarId, expr](const std::unordered_map<nonneg int, ValueFlow::Value>& xargs, const Settings& settings) { |
| 1892 | if (!expr) |
| 1893 | return ValueFlow::Value::unknown(); |
| 1894 | ProgramMemory pm{}; |
| 1895 | for (const auto& p : xargs) { |
| 1896 | auto it = lookupVarId.find(p.first); |
| 1897 | if (it != lookupVarId.end()) |
| 1898 | pm.setValue(it->second, p.second); |
| 1899 | } |
| 1900 | return execute(expr.get(), pm, settings); |
| 1901 | }; |
| 1902 | } |
| 1903 | return functions.at(returnValue)(args, settings); |
| 1904 | } |
| 1905 | |
| 1906 | void execute(const Token* expr, |
| 1907 | ProgramMemory& programMemory, |