@@ -412,132 +412,6 @@ void CheckOther::checkPipeParameterSizeError(const Token *tok, const std::string
412412// Detect redundant assignments: x = 0; x = 4;
413413// ---------------------------------------------------------------------------
414414
415- static bool nonLocal (const Variable* var)
416- {
417- return !var || (!var->isLocal () && !var->isArgument ()) || var->isStatic () || var->isReference ();
418- }
419-
420- static void eraseMemberAssignments (const unsigned int varId, const std::map<unsigned int , std::set<unsigned int > > &membervars, std::map<unsigned int , const Token*> &varAssignments)
421- {
422- const std::map<unsigned int , std::set<unsigned int > >::const_iterator it = membervars.find (varId);
423- if (it != membervars.end ()) {
424- const std::set<unsigned int >& vars = it->second ;
425- for (unsigned int var : vars) {
426- varAssignments.erase (var);
427- if (var != varId)
428- eraseMemberAssignments (var, membervars, varAssignments);
429- }
430- }
431- }
432-
433- static bool hasFunctionCall (const Token *tok)
434- {
435- if (!tok)
436- return false ;
437- if (Token::Match (tok, " %name% (" ))
438- // todo, const/pure function?
439- return true ;
440- return hasFunctionCall (tok->astOperand1 ()) || hasFunctionCall (tok->astOperand2 ());
441- }
442-
443- static bool hasOperand (const Token *tok, const Token *lhs, bool cpp, const Library &library)
444- {
445- if (!tok)
446- return false ;
447- if (isSameExpression (cpp, false , tok, lhs, library, false , false , nullptr ))
448- return true ;
449- return hasOperand (tok->astOperand1 (), lhs, cpp, library) || hasOperand (tok->astOperand2 (), lhs, cpp, library);
450- }
451-
452- struct CheckOther ::ScopeResult CheckOther::checkRedundantAssignmentRecursive (const Token *assign1, const Token *startToken, const Token *endToken) const {
453- // all variable ids in assign1 LHS.
454- std::set<unsigned int > assign1LhsVarIds;
455- bool local = true ;
456- visitAstNodes (assign1->astOperand1 (),
457- [&](const Token *tok) {
458- if (tok->varId () > 0 ) {
459- assign1LhsVarIds.insert (tok->varId ());
460- if (!Token::simpleMatch (tok->previous (), " ." ))
461- local &= !nonLocal (tok->variable ());
462- }
463- return ChildrenToVisit::op1_and_op2;
464- });
465-
466- // Parse the given tokens
467- for (const Token *tok = startToken; tok != endToken; tok = tok->next ()) {
468- if (Token::simpleMatch (tok, " try {" )) {
469- // TODO: handle try
470- return ScopeResult (ScopeResult::BAILOUT);
471- }
472-
473- if (tok->str () == " }" && (tok->scope ()->type == Scope::eFor || tok->scope ()->type == Scope::eWhile)) {
474- // TODO: handle loops better
475- return ScopeResult (ScopeResult::BAILOUT);
476- }
477-
478- if (Token::simpleMatch (tok, " break ;" )) {
479- return ScopeResult (ScopeResult::BREAK, tok);
480- }
481-
482- if (Token::Match (tok, " continue|return|throw|goto" )) {
483- // TODO: Handle these better
484- return ScopeResult (ScopeResult::RETURN);
485- }
486-
487- if (Token::simpleMatch (tok, " else {" ))
488- tok = tok->linkAt (1 );
489-
490- if (Token::simpleMatch (tok, " asm (" )) {
491- return ScopeResult (ScopeResult::BAILOUT);
492- }
493-
494- if (!local && Token::Match (tok, " %name% (" ) && !Token::simpleMatch (tok->linkAt (1 ), " ) {" )) {
495- // TODO: this is a quick bailout
496- return ScopeResult (ScopeResult::BAILOUT);
497- }
498-
499- if (assign1LhsVarIds.find (tok->varId ()) != assign1LhsVarIds.end ()) {
500- const Token *parent = tok;
501- while (Token::Match (parent->astParent (), " .|::|[" ))
502- parent = parent->astParent ();
503- if (Token::simpleMatch (parent->astParent (), " =" ) && parent == parent->astParent ()->astOperand1 ()) {
504- if (!local && hasFunctionCall (parent->astParent ()->astOperand2 ())) {
505- // TODO: this is a quick bailout
506- return ScopeResult (ScopeResult::BAILOUT);
507- }
508- if (hasOperand (parent->astParent ()->astOperand2 (), assign1->astOperand1 (), mTokenizer ->isCPP (), mSettings ->library )) {
509- return ScopeResult (ScopeResult::READ);
510- }
511- const bool reassign = isSameExpression (mTokenizer ->isCPP (), false , assign1->astOperand1 (), parent, mSettings ->library , false , false , nullptr );
512- if (reassign)
513- return ScopeResult (ScopeResult::WRITE, parent->astParent ());
514- return ScopeResult (ScopeResult::READ);
515- } else {
516- // TODO: this is a quick bailout
517- return ScopeResult (ScopeResult::BAILOUT);
518- }
519- }
520-
521- if (Token::Match (tok, " ) {" )) {
522- const ScopeResult &result1 = checkRedundantAssignmentRecursive (assign1, tok->tokAt (2 ), tok->linkAt (1 ));
523- if (result1.type == ScopeResult::READ || result1.type == ScopeResult::BAILOUT)
524- return result1;
525- if (Token::simpleMatch (tok->linkAt (1 ), " } else {" )) {
526- const Token *elseStart = tok->linkAt (1 )->tokAt (2 );
527- const ScopeResult &result2 = checkRedundantAssignmentRecursive (assign1, elseStart, elseStart->link ());
528- if (result2.type == ScopeResult::READ || result2.type == ScopeResult::BAILOUT)
529- return result2;
530- if (result1.type == ScopeResult::WRITE && result2.type == ScopeResult::WRITE)
531- return result1;
532- tok = elseStart->link ();
533- } else {
534- tok = tok->linkAt (1 );
535- }
536- }
537- }
538- return ScopeResult (ScopeResult::NONE);
539- }
540-
541415void CheckOther::checkRedundantAssignment ()
542416{
543417 if (!mSettings ->isEnabled (Settings::STYLE))
@@ -586,9 +460,6 @@ void CheckOther::checkRedundantAssignment()
586460 // todo: check static variables
587461 continue ;
588462
589- if (hasOperand (tok->astOperand2 (), tok->astOperand1 (), mTokenizer ->isCPP (), mSettings ->library ))
590- continue ;
591-
592463 // If there is a custom assignment operator => this is inconclusive
593464 bool inconclusive = false ;
594465 if (mTokenizer ->isCPP () && tok->astOperand1 ()->valueType () && tok->astOperand1 ()->valueType ()->typeScope ) {
@@ -603,6 +474,10 @@ void CheckOther::checkRedundantAssignment()
603474 if (inconclusive && !mSettings ->inconclusive )
604475 continue ;
605476
477+ FwdAnalysis fwdAnalysis (mTokenizer ->isCPP (), mSettings ->library );
478+ if (fwdAnalysis.hasOperand (tok->astOperand2 (), tok->astOperand1 ()))
479+ continue ;
480+
606481 // Is there a redundant assignment?
607482 const Token *start;
608483 if (tok->isAssignmentOp ())
@@ -611,25 +486,9 @@ void CheckOther::checkRedundantAssignment()
611486 start = tok->findExpressionStartEndTokens ().second ->next ();
612487
613488 // Get next assignment..
614- ScopeResult nextAssign (ScopeResult::NONE);
615- while (true ) {
616- nextAssign = checkRedundantAssignmentRecursive (tok, start, scope->bodyEnd );
617-
618- // Break => continue checking in outer scope
619- if (nextAssign.type == ScopeResult::BREAK) {
620- const Scope *s = nextAssign.token ->scope ();
621- while (s->type == Scope::eIf)
622- s = s->nestedIn ;
623- if (s->type == Scope::eSwitch) {
624- start = s->bodyEnd ->next ();
625- continue ;
626- }
627- }
628-
629- break ;
630- }
489+ FwdAnalysis::Result nextAssign = fwdAnalysis.check (tok, start, scope->bodyEnd );
631490
632- if (nextAssign.type != ScopeResult ::WRITE || !nextAssign.token )
491+ if (nextAssign.type != FwdAnalysis::Result::Type ::WRITE || !nextAssign.token )
633492 continue ;
634493
635494 // there is redundant assignment. Is there a case between the assignments?
0 commit comments