| 2878 | } |
| 2879 | |
| 2880 | static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) |
| 2881 | { |
| 2882 | for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { |
| 2883 | if (!tok->scope()) |
| 2884 | continue; |
| 2885 | if (tok->scope()->type == ScopeType::eGlobal) |
| 2886 | continue; |
| 2887 | Lambda lam(tok); |
| 2888 | // Lambdas |
| 2889 | if (lam.isLambda()) { |
| 2890 | const Scope * bodyScope = lam.bodyTok->scope(); |
| 2891 | |
| 2892 | std::set<const Scope *> scopes; |
| 2893 | // Avoid capturing a variable twice |
| 2894 | std::set<nonneg int> varids; |
| 2895 | bool capturedThis = false; |
| 2896 | |
| 2897 | auto isImplicitCapturingVariable = [&](const Token *varTok) { |
| 2898 | const Variable *var = varTok->variable(); |
| 2899 | if (!var) |
| 2900 | return false; |
| 2901 | if (varids.count(var->declarationId()) > 0) |
| 2902 | return false; |
| 2903 | if (!var->isLocal() && !var->isArgument()) |
| 2904 | return false; |
| 2905 | const Scope *scope = var->scope(); |
| 2906 | if (!scope) |
| 2907 | return false; |
| 2908 | if (scopes.count(scope) > 0) |
| 2909 | return false; |
| 2910 | if (scope->isNestedIn(bodyScope)) |
| 2911 | return false; |
| 2912 | scopes.insert(scope); |
| 2913 | varids.insert(var->declarationId()); |
| 2914 | return true; |
| 2915 | }; |
| 2916 | |
| 2917 | bool update = false; |
| 2918 | auto captureVariable = [&](const Token* tok2, LifetimeCapture c, const std::function<bool(const Token*)> &pred) { |
| 2919 | if (varids.count(tok->varId()) > 0) |
| 2920 | return; |
| 2921 | if (c == LifetimeCapture::ByReference) { |
| 2922 | LifetimeStore ls{ |
| 2923 | tok2, "Lambda captures variable by reference here.", ValueFlow::Value::LifetimeKind::Lambda}; |
| 2924 | ls.forward = false; |
| 2925 | update |= ls.byRef(tok, tokenlist, errorLogger, settings, pred); |
| 2926 | } else if (c == LifetimeCapture::ByValue) { |
| 2927 | LifetimeStore ls{ |
| 2928 | tok2, "Lambda captures variable by value here.", ValueFlow::Value::LifetimeKind::Lambda}; |
| 2929 | ls.forward = false; |
| 2930 | update |= ls.byVal(tok, tokenlist, errorLogger, settings, pred); |
| 2931 | pred(tok2); |
| 2932 | } |
| 2933 | }; |
| 2934 | |
| 2935 | auto captureThisVariable = [&](const Token* tok2, LifetimeCapture c) { |
| 2936 | ValueFlow::Value value; |
| 2937 | value.valueType = ValueFlow::Value::ValueType::LIFETIME; |
no test coverage detected