| 3001 | } // namespace |
| 3002 | |
| 3003 | void CheckStlImpl::useStlAlgorithm() |
| 3004 | { |
| 3005 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("useStlAlgorithm")) |
| 3006 | return; |
| 3007 | |
| 3008 | logChecker("CheckStl::useStlAlgorithm"); // style |
| 3009 | |
| 3010 | auto checkAssignee = [](const Token* tok) { |
| 3011 | if (astIsBool(tok)) // std::accumulate is not a good fit for bool values, std::all/any/none_of return early |
| 3012 | return false; |
| 3013 | return !astIsContainer(tok); // don't warn for containers, where overloaded operators can be costly |
| 3014 | }; |
| 3015 | |
| 3016 | enum class ConditionOpType : std::uint8_t { OTHER, MIN, MAX }; |
| 3017 | auto isConditionWithoutSideEffects = [this](const Token* tok, ConditionOpType& type) -> bool { |
| 3018 | if (!Token::simpleMatch(tok, "{") || !Token::simpleMatch(tok->previous(), ")")) |
| 3019 | return false; |
| 3020 | const Token* condTok = tok->linkAt(-1)->astOperand2(); |
| 3021 | if (isConstExpression(condTok, mSettings.library)) { |
| 3022 | if (condTok->str() == "<") |
| 3023 | type = ConditionOpType::MIN; |
| 3024 | else if (condTok->str() == ">") |
| 3025 | type = ConditionOpType::MAX; |
| 3026 | else |
| 3027 | type = ConditionOpType::OTHER; |
| 3028 | return true; |
| 3029 | } |
| 3030 | return false; |
| 3031 | }; |
| 3032 | |
| 3033 | auto isAccumulation = [](const Token* tok, int varId) { |
| 3034 | if (tok->str() != "=") |
| 3035 | return true; |
| 3036 | const Token* end = Token::findmatch(tok, "%varid%|;", varId); // TODO: lambdas? |
| 3037 | return end && end->varId() != 0; |
| 3038 | }; |
| 3039 | |
| 3040 | for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { |
| 3041 | for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { |
| 3042 | // Parse range-based for loop |
| 3043 | if (!Token::simpleMatch(tok, "for (")) |
| 3044 | continue; |
| 3045 | if (!Token::simpleMatch(tok->linkAt(1), ") {")) |
| 3046 | continue; |
| 3047 | LoopAnalyzer a{tok, &mSettings}; |
| 3048 | std::string algoName = a.findAlgo(); |
| 3049 | if (!algoName.empty()) { |
| 3050 | useStlAlgorithmError(tok, algoName); |
| 3051 | continue; |
| 3052 | } |
| 3053 | |
| 3054 | const Token *bodyTok = tok->linkAt(1)->next(); |
| 3055 | const Token *splitTok = tok->next()->astOperand2(); |
| 3056 | const Token* loopVar{}; |
| 3057 | LoopType loopType{}; |
| 3058 | if (Token::simpleMatch(splitTok, ":")) { |
| 3059 | loopVar = splitTok->previous(); |
| 3060 | if (loopVar->varId() == 0) |
no test coverage detected