@@ -594,6 +594,14 @@ void CheckOtherImpl::invalidPointerCastError(const Token* tok, const std::string
594594// Detect redundant assignments: x = 0; x = 4;
595595// ---------------------------------------------------------------------------
596596
597+ static bool isAssignment (const Token* tok) {
598+ if (tok->astParent () || !tok->astOperand1 ())
599+ return false ;
600+ if (tok->isAssignmentOp () || tok->tokType () == Token::eIncDecOp)
601+ return true ;
602+ return Token::Match (tok, " [{(]" ) && tok->astOperand1 ()->variable () && tok->astOperand1 () == tok->astOperand1 ()->variable ()->nameToken ();
603+ }
604+
597605void CheckOtherImpl::checkRedundantAssignment ()
598606{
599607 if (!mSettings .severity .isEnabled (Severity::style) &&
@@ -614,122 +622,119 @@ void CheckOtherImpl::checkRedundantAssignment()
614622 if (Token::simpleMatch (tok, " try {" ))
615623 // todo: check try blocks
616624 tok = tok->linkAt (1 );
617- if ((tok->isAssignmentOp () || tok->tokType () == Token::eIncDecOp) && tok->astOperand1 ()) {
618- if (tok->astParent ())
619- continue ;
625+ if (!isAssignment (tok))
626+ continue ;
620627
621- // Do not warn about redundant initialization when rhs is trivial
622- // TODO : do not simplify the variable declarations
623- bool isInitialization = false ;
624- if (Token::Match (tok->tokAt (-2 ), " ; %var% =" ) && tok->tokAt (-2 )->isSplittedVarDeclEq ()) {
625- isInitialization = true ;
626- bool trivial = true ;
627- visitAstNodes (tok->astOperand2 (),
628- [&](const Token *rhs) {
629- if (Token::simpleMatch (rhs, " { 0 }" ))
630- return ChildrenToVisit::none;
631- if (Token::Match (rhs, " %num%|%name%" ) && !rhs->varId ())
632- return ChildrenToVisit::none;
633- if (Token::Match (rhs, " :: %name%" ) && rhs->hasKnownIntValue ())
634- return ChildrenToVisit::none;
635- if (rhs->isCast ())
636- return ChildrenToVisit::op2;
637- trivial = false ;
638- return ChildrenToVisit::done;
639- });
640- if (trivial)
641- continue ;
628+ // Do not warn about redundant initialization when rhs is trivial
629+ // TODO : do not simplify the variable declarations
630+ bool isInitialization = false ;
631+ if (( Token::Match (tok->tokAt (-2 ), " ; %var% =" ) && tok->tokAt (-2 )->isSplittedVarDeclEq ()) || Token::Match (tok, " [{(] " )) {
632+ isInitialization = true ;
633+ bool trivial = true ;
634+ visitAstNodes (tok->astOperand2 (),
635+ [&](const Token *rhs) {
636+ if (Token::simpleMatch (rhs, " { 0 }" ))
637+ return ChildrenToVisit::none;
638+ if (Token::Match (rhs, " %num%|%name%" ) && !rhs->varId ())
639+ return ChildrenToVisit::none;
640+ if (Token::Match (rhs, " :: %name%" ) && rhs->hasKnownIntValue ())
641+ return ChildrenToVisit::none;
642+ if (rhs->isCast ())
643+ return ChildrenToVisit::op2;
644+ trivial = false ;
645+ return ChildrenToVisit::done;
646+ });
647+ if (trivial)
648+ continue ;
642649 }
643650
644- const Token* rhs = tok->astOperand2 ();
645- // Do not warn about assignment with 0 / NULL
646- if ((rhs && MathLib::isNullValue (rhs->str ())) || isNullOperand (rhs))
647- continue ;
651+ const Token* rhs = tok->astOperand2 ();
652+ // Do not warn about assignment with 0 / NULL
653+ if ((rhs && MathLib::isNullValue (rhs->str ())) || isNullOperand (rhs))
654+ continue ;
648655
649- if (tok->astOperand1 ()->variable () && tok->astOperand1 ()->variable ()->isReference ())
650- // todo: check references
651- continue ;
656+ if (tok->astOperand1 ()->variable () && tok->astOperand1 ()->variable ()->isReference ())
657+ // todo: check references
658+ continue ;
652659
653- if (tok->astOperand1 ()->variable () && tok->astOperand1 ()->variable ()->isStatic ())
654- // todo: check static variables
655- continue ;
660+ if (tok->astOperand1 ()->variable () && tok->astOperand1 ()->variable ()->isStatic ())
661+ // todo: check static variables
662+ continue ;
656663
657- bool inconclusive = false ;
658- if (tok->isCpp () && tok->astOperand1 ()->valueType ()) {
659- // If there is a custom assignment operator => this is inconclusive
660- if (tok->astOperand1 ()->valueType ()->typeScope ) {
661- const std::string op = " operator" + tok->str ();
662- const std::list<Function>& fList = tok->astOperand1 ()->valueType ()->typeScope ->functionList ;
663- inconclusive = std::any_of (fList .cbegin (), fList .cend (), [&](const Function& f) {
664- return f.name () == op;
665- });
666- }
667- // assigning a smart pointer has side effects
668- if (tok->astOperand1 ()->valueType ()->type == ValueType::SMART_POINTER )
669- break ;
664+ bool inconclusive = false ;
665+ if (tok->isCpp () && tok->astOperand1 ()->valueType ()) {
666+ // If there is a custom assignment operator => this is inconclusive
667+ if (tok->astOperand1 ()->valueType ()->typeScope ) {
668+ const std::string op = " operator" + tok->str ();
669+ const std::list<Function>& fList = tok->astOperand1 ()->valueType ()->typeScope ->functionList ;
670+ inconclusive = std::any_of (fList .cbegin (), fList .cend (), [&](const Function& f) {
671+ return f.name () == op;
672+ });
670673 }
671- if (inconclusive && !mSettings .certainty .isEnabled (Certainty::inconclusive))
672- continue ;
673-
674- FwdAnalysis fwdAnalysis (mSettings );
675- if (fwdAnalysis.hasOperand (tok->astOperand2 (), tok->astOperand1 ()))
676- continue ;
677-
678- // Is there a redundant assignment?
679- const Token *start;
680- if (tok->isAssignmentOp ())
681- start = tok->astOperand2 ();
682- else
683- start = tok->findExpressionStartEndTokens ().second ->next ();
674+ // assigning a smart pointer has side effects
675+ if (tok->astOperand1 ()->valueType ()->type == ValueType::SMART_POINTER )
676+ break ;
677+ }
678+ if (inconclusive && !mSettings .certainty .isEnabled (Certainty::inconclusive))
679+ continue ;
684680
685- const Token * tokenToCheck = tok->astOperand1 ();
681+ FwdAnalysis fwdAnalysis (mSettings );
682+ if (fwdAnalysis.hasOperand (tok->astOperand2 (), tok->astOperand1 ()))
683+ continue ;
686684
687- // Check if we are working with union
688- for (const Token* tempToken = tokenToCheck; Token::simpleMatch (tempToken, " ." );) {
689- tempToken = tempToken->astOperand1 ();
690- if (tempToken && tempToken->variable () && tempToken->variable ()->type () && tempToken->variable ()->type ()->isUnionType ())
691- tokenToCheck = tempToken;
692- }
685+ // Is there a redundant assignment?
686+ const Token *start;
687+ if (tok->isAssignmentOp ())
688+ start = tok->astOperand2 ();
689+ else
690+ start = tok->findExpressionStartEndTokens ().second ->next ();
691+ const Token * tokenToCheck = tok->astOperand1 ();
692+
693+ // Check if we are working with union
694+ for (const Token* tempToken = tokenToCheck; Token::simpleMatch (tempToken, " ." );) {
695+ tempToken = tempToken->astOperand1 ();
696+ if (tempToken && tempToken->variable () && tempToken->variable ()->type () && tempToken->variable ()->type ()->isUnionType ())
697+ tokenToCheck = tempToken;
698+ }
693699
694- if (start->hasKnownSymbolicValue (tokenToCheck) && Token::simpleMatch (start->astParent (), " =" ) && !diag (tok)) {
695- const ValueFlow::Value* val = start->getKnownValue (ValueFlow::Value::ValueType::SYMBOLIC );
696- if (val->intvalue == 0 ) // no offset
697- redundantAssignmentSameValueError (tokenToCheck, val, tok->astOperand1 ()->expressionString ());
698- }
700+ if (start->hasKnownSymbolicValue (tokenToCheck) && Token::simpleMatch (start->astParent (), " =" ) && !diag (tok)) {
701+ const ValueFlow::Value* val = start->getKnownValue (ValueFlow::Value::ValueType::SYMBOLIC );
702+ if (val->intvalue == 0 ) // no offset
703+ redundantAssignmentSameValueError (tokenToCheck, val, tok->astOperand1 ()->expressionString ());
704+ }
699705
700- // Get next assignment..
701- const Token *nextAssign = fwdAnalysis.reassign (tokenToCheck, start, scope->bodyEnd );
702- // extra check for union
703- if (nextAssign && tokenToCheck != tok->astOperand1 ()) {
704- nextAssign = fwdAnalysis.reassign (tok->astOperand1 (), start, scope->bodyEnd );
705- // reading another member of the same union in the rhs is a use through aliasing
706- if (nextAssign && fwdAnalysis.hasOperand (nextAssign->astOperand2 (), tokenToCheck))
707- nextAssign = nullptr ;
708- }
706+ // Get next assignment..
707+ const Token *nextAssign = fwdAnalysis.reassign (tokenToCheck, start, scope->bodyEnd );
708+ // extra check for union
709+ if (nextAssign && tokenToCheck != tok->astOperand1 ()) {
710+ nextAssign = fwdAnalysis.reassign (tok->astOperand1 (), start, scope->bodyEnd );
711+ // reading another member of the same union in the rhs is a use through aliasing
712+ if (nextAssign && fwdAnalysis.hasOperand (nextAssign->astOperand2 (), tokenToCheck))
713+ nextAssign = nullptr ;
714+ }
709715
710- if (!nextAssign)
711- continue ;
716+ if (!nextAssign)
717+ continue ;
712718
713- // there is redundant assignment. Is there a case between the assignments?
714- bool hasCase = false ;
715- for (const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->next ()) {
716- if (tok2->str () == " break" || tok2->str () == " return" )
717- break ;
718- if (tok2->str () == " case" ) {
719- hasCase = true ;
720- break ;
721- }
719+ // there is redundant assignment. Is there a case between the assignments?
720+ bool hasCase = false ;
721+ for (const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->next ()) {
722+ if (tok2->str () == " break" || tok2->str () == " return" )
723+ break ;
724+ if (tok2->str () == " case" ) {
725+ hasCase = true ;
726+ break ;
722727 }
728+ }
723729
724- // warn
725- if (hasCase)
726- redundantAssignmentInSwitchError (tok, nextAssign, tok->astOperand1 ()->expressionString ());
727- else if (isInitialization)
728- redundantInitializationError (tok, nextAssign, tok->astOperand1 ()->expressionString (), inconclusive);
729- else {
730- diag (nextAssign);
731- redundantAssignmentError (tok, nextAssign, tok->astOperand1 ()->expressionString (), inconclusive);
732- }
730+ // warn
731+ if (hasCase)
732+ redundantAssignmentInSwitchError (tok, nextAssign, tok->astOperand1 ()->expressionString ());
733+ else if (isInitialization)
734+ redundantInitializationError (tok, nextAssign, tok->astOperand1 ()->expressionString (), inconclusive);
735+ else {
736+ diag (nextAssign);
737+ redundantAssignmentError (tok, nextAssign, tok->astOperand1 ()->expressionString (), inconclusive);
733738 }
734739 }
735740 }
0 commit comments