| 3227 | } |
| 3228 | |
| 3229 | static void valueFlowAfterMove(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) |
| 3230 | { |
| 3231 | if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11) |
| 3232 | return; |
| 3233 | for (const Scope * scope : symboldatabase.functionScopes) { |
| 3234 | if (!scope) |
| 3235 | continue; |
| 3236 | const Token * start = scope->bodyStart; |
| 3237 | if (scope->function) { |
| 3238 | const Token * memberInitializationTok = scope->function->constructorMemberInitialization(); |
| 3239 | if (memberInitializationTok) |
| 3240 | start = memberInitializationTok; |
| 3241 | } |
| 3242 | |
| 3243 | for (auto* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) { |
| 3244 | Token * varTok; |
| 3245 | if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) { |
| 3246 | varTok = tok; |
| 3247 | |
| 3248 | const Variable *var = tok->variable(); |
| 3249 | if (!var || (!var->isLocal() && !var->isArgument())) |
| 3250 | continue; |
| 3251 | |
| 3252 | ValueFlow::Value value; |
| 3253 | value.valueType = ValueFlow::Value::ValueType::MOVED; |
| 3254 | value.moveKind = ValueFlow::Value::MoveKind::NonMovedVariable; |
| 3255 | value.errorPath.emplace_back(tok, "Calling " + tok->next()->expressionString() + " makes " + tok->str() + " 'non-moved'"); |
| 3256 | value.setKnown(); |
| 3257 | |
| 3258 | setTokenValue(tok, value, settings); |
| 3259 | if (var->scope()) { |
| 3260 | const Token* const endOfVarScope = var->scope()->bodyEnd; |
| 3261 | valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, errorLogger, settings); |
| 3262 | } |
| 3263 | continue; |
| 3264 | } |
| 3265 | ValueFlow::Value::MoveKind moveKind; |
| 3266 | if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok)) |
| 3267 | continue; |
| 3268 | const nonneg int varId = varTok->varId(); |
| 3269 | // x is not MOVED after assignment if code is: x = ... std::move(x) .. ; |
| 3270 | const Token *parent = tok->astParent(); |
| 3271 | bool bail = false; |
| 3272 | while (parent && parent->str() != "=" && parent->str() != "return" && |
| 3273 | !(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId))) { |
| 3274 | if (isTryEmplace(parent)) { |
| 3275 | bail = true; |
| 3276 | break; |
| 3277 | } |
| 3278 | parent = parent->astParent(); |
| 3279 | } |
| 3280 | if (bail) |
| 3281 | continue; |
| 3282 | if (parent && |
| 3283 | (parent->str() == "return" || // MOVED in return statement |
| 3284 | parent->str() == "(")) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true |
| 3285 | continue; |
| 3286 | if (parent && parent->astOperand1() && parent->astOperand1()->varId() == varId) |
no test coverage detected