| 5958 | } |
| 5959 | |
| 5960 | static Token* findStartToken(const Variable* var, Token* start, const Library& library) |
| 5961 | { |
| 5962 | std::vector<Token*> uses = findAllUsages(var, start, library); |
| 5963 | if (uses.empty()) |
| 5964 | return start; |
| 5965 | Token* first = uses.front(); |
| 5966 | if (Token::findmatch(start, "goto|asm|setjmp|longjmp", first)) |
| 5967 | return start; |
| 5968 | if (first != var->nameToken()) { |
| 5969 | // if this is lhs in assignment then set first to the first token in LHS expression |
| 5970 | Token* temp = first; |
| 5971 | while (Token::Match(temp->astParent(), "[&*(]") && precedes(temp->astParent(), temp)) |
| 5972 | temp = temp->astParent(); |
| 5973 | if (Token::simpleMatch(temp->astParent(), "=") && precedes(temp, temp->astParent())) |
| 5974 | first = temp; |
| 5975 | } |
| 5976 | // If there is only one usage |
| 5977 | if (uses.size() == 1) |
| 5978 | return first->previous(); |
| 5979 | const Scope* scope = first->scope(); |
| 5980 | // If first usage is in variable scope |
| 5981 | if (scope == var->scope()) { |
| 5982 | bool isLoopExpression = false; |
| 5983 | for (const Token* parent = first; parent; parent = parent->astParent()) { |
| 5984 | if (Token::simpleMatch(parent->astParent(), ";") && |
| 5985 | Token::simpleMatch(parent->astParent()->astParent(), ";") && |
| 5986 | Token::simpleMatch(parent->astParent()->astParent()->astParent(), "(") && |
| 5987 | Token::simpleMatch(parent->astParent()->astParent()->astParent()->astOperand1(), "for (") && |
| 5988 | parent == parent->astParent()->astParent()->astParent()->astOperand2()->astOperand2()->astOperand2()) { |
| 5989 | isLoopExpression = true; |
| 5990 | } |
| 5991 | } |
| 5992 | return isLoopExpression ? start : first->previous(); |
| 5993 | } |
| 5994 | // If all uses are in the same scope |
| 5995 | if (std::all_of(uses.begin() + 1, uses.end(), [&](const Token* tok) { |
| 5996 | return tok->scope() == scope; |
| 5997 | })) |
| 5998 | return first->previous(); |
| 5999 | // Compute the outer scope |
| 6000 | while (scope && scope->nestedIn != var->scope()) { |
| 6001 | if (scope->type == ScopeType::eLambda && !Token::simpleMatch(scope->bodyEnd, "} (")) |
| 6002 | return start; |
| 6003 | scope = scope->nestedIn; |
| 6004 | } |
| 6005 | if (!scope || (scope->type == ScopeType::eLambda && !Token::simpleMatch(scope->bodyEnd, "} ("))) |
| 6006 | return start; |
| 6007 | auto* tok = const_cast<Token*>(scope->bodyStart); |
| 6008 | if (!tok) |
| 6009 | return start; |
| 6010 | if (Token::simpleMatch(tok->tokAt(-2), "} else {")) |
| 6011 | tok = tok->linkAt(-2); |
| 6012 | if (Token::simpleMatch(tok->previous(), ") {")) |
| 6013 | return tok->linkAt(-1)->previous(); |
| 6014 | return tok; |
| 6015 | } |
| 6016 | |
| 6017 | static void valueFlowUninit(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) |
no test coverage detected