@@ -1333,20 +1333,6 @@ void CheckOther::passedByValueError(const Variable* var, bool inconclusive, bool
13331333 reportError (errorPath, Severity::performance, id.c_str (), msg, CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal);
13341334}
13351335
1336- static bool isUnusedVariable (const Variable *var)
1337- {
1338- if (!var)
1339- return false ;
1340- if (!var->scope ())
1341- return false ;
1342- const Token *start = var->declEndToken ();
1343- if (!start)
1344- return false ;
1345- if (Token::Match (start, " ; %varid% =" , var->declarationId ()))
1346- start = start->tokAt (2 );
1347- return !Token::findmatch (start->next (), " %varid%" , var->scope ()->bodyEnd , var->declarationId ());
1348- }
1349-
13501336static bool isVariableMutableInInitializer (const Token* start, const Token * end, nonneg int varid)
13511337{
13521338 if (!start)
@@ -1402,8 +1388,6 @@ void CheckOther::checkConstVariable()
14021388 if (function && var->isArgument ()) {
14031389 if (function->isImplicitlyVirtual () || function->templateDef )
14041390 continue ;
1405- if (isUnusedVariable (var))
1406- continue ;
14071391 if (function->isConstructor () && isVariableMutableInInitializer (function->constructorMemberInitialization (), scope->bodyStart , var->declarationId ()))
14081392 continue ;
14091393 }
@@ -1417,6 +1401,8 @@ void CheckOther::checkConstVariable()
14171401 continue ;
14181402 if (var->isVolatile ())
14191403 continue ;
1404+ if (var->isMaybeUnused ())
1405+ continue ;
14201406 if (var->nameToken ()->isExpandedMacro ())
14211407 continue ;
14221408 if (isStructuredBindingVariable (var)) // TODO: check all bound variables
@@ -1505,6 +1491,24 @@ static const Token* getVariableChangedStart(const Variable* p)
15051491 return start;
15061492}
15071493
1494+ namespace {
1495+ struct CompareVariables {
1496+ bool operator ()(const Variable* a, const Variable* b) const {
1497+ const int fileA = a->nameToken ()->fileIndex ();
1498+ const int fileB = b->nameToken ()->fileIndex ();
1499+ if (fileA != fileB)
1500+ return fileA < fileB;
1501+ const int lineA = a->nameToken ()->linenr ();
1502+ const int lineB = b->nameToken ()->linenr ();
1503+ if (lineA != lineB)
1504+ return lineA < lineB;
1505+ const int columnA = a->nameToken ()->column ();
1506+ const int columnB = b->nameToken ()->column ();
1507+ return columnA < columnB;
1508+ }
1509+ };
1510+ }
1511+
15081512void CheckOther::checkConstPointer ()
15091513{
15101514 if (!mSettings ->severity .isEnabled (Severity::style) &&
@@ -1514,18 +1518,20 @@ void CheckOther::checkConstPointer()
15141518
15151519 logChecker (" CheckOther::checkConstPointer" ); // style
15161520
1517- std::vector <const Variable*> pointers, nonConstPointers;
1521+ std::set <const Variable*, CompareVariables > pointers, nonConstPointers;
15181522 for (const Token *tok = mTokenizer ->tokens (); tok; tok = tok->next ()) {
15191523 const Variable* const var = tok->variable ();
15201524 if (!var)
15211525 continue ;
15221526 if (!var->isLocal () && !var->isArgument ())
15231527 continue ;
15241528 const Token* const nameTok = var->nameToken ();
1525- // declarations of (static) pointers are (not) split up, array declarations are never split up
1526- if (tok == nameTok && (!var->isStatic () || Token::simpleMatch (nameTok->next (), " [" )) &&
1527- !astIsRangeBasedForDecl (nameTok))
1528- continue ;
1529+ if (tok == nameTok) {
1530+ // declarations of (static) pointers are (not) split up, array declarations are never split up
1531+ if (var->isLocal () && (!var->isStatic () || Token::simpleMatch (nameTok->next (), " [" )) &&
1532+ !astIsRangeBasedForDecl (nameTok))
1533+ continue ;
1534+ }
15291535 const ValueType* const vt = tok->valueType ();
15301536 if (!vt)
15311537 continue ;
@@ -1535,7 +1541,7 @@ void CheckOther::checkConstPointer()
15351541 continue ;
15361542 if (std::find (nonConstPointers.cbegin (), nonConstPointers.cend (), var) != nonConstPointers.cend ())
15371543 continue ;
1538- pointers.emplace_back (var);
1544+ pointers.emplace (var);
15391545 const Token* parent = tok->astParent ();
15401546 enum Deref { NONE, DEREF, MEMBER } deref = NONE;
15411547 bool hasIncDec = false ;
@@ -1620,12 +1626,15 @@ void CheckOther::checkConstPointer()
16201626 continue ;
16211627 }
16221628 }
1623- nonConstPointers.emplace_back (var);
1629+ if (tok != nameTok)
1630+ nonConstPointers.emplace (var);
16241631 }
16251632 for (const Variable *p: pointers) {
16261633 if (p->isArgument ()) {
16271634 if (!p->scope () || !p->scope ()->function || p->scope ()->function ->isImplicitlyVirtual (true ) || p->scope ()->function ->hasVirtualSpecifier ())
16281635 continue ;
1636+ if (p->isMaybeUnused ())
1637+ continue ;
16291638 }
16301639 if (std::find (nonConstPointers.cbegin (), nonConstPointers.cend (), p) == nonConstPointers.cend ()) {
16311640 const Token *start = getVariableChangedStart (p);
0 commit comments