Skip to content

Commit fe83217

Browse files
Update checkother.cpp
1 parent 94f84ed commit fe83217

1 file changed

Lines changed: 106 additions & 101 deletions

File tree

‎lib/checkother.cpp‎

Lines changed: 106 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
597605
void 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

Comments
 (0)