@@ -5220,6 +5220,20 @@ static std::string getScopeName(const std::list<ScopeInfo2> &scopeInfo)
52205220 return ret;
52215221}
52225222
5223+ // If tok is the name in a qualification "name ::" or "name < ... > ::", return the token after the "::"
5224+ static Token * skipQualification (Token *tok)
5225+ {
5226+ if (!Token::Match (tok, " %name% ::|<" ))
5227+ return nullptr ;
5228+ if (tok->strAt (1 ) == " <" ) {
5229+ tok = tok->next ()->findClosingBracket ();
5230+ if (!Token::simpleMatch (tok, " > ::" ))
5231+ return nullptr ;
5232+ }
5233+ return tok->tokAt (2 );
5234+ }
5235+
5236+ // indexMembersByScopeName() relies on how this matches the scope names: keep the two in sync
52235237static Token * matchMemberName (const std::list<std::string> &scope, const Token *nsToken, Token *memberToken, const std::list<ScopeInfo2> &scopeInfo)
52245238{
52255239 auto scopeIt = scopeInfo.cbegin ();
@@ -5252,16 +5266,11 @@ static Token * matchMemberName(const std::list<std::string> &scope, const Token
52525266
52535267 // Parse member tokens..
52545268 while (scopeIt != scopeInfo.end ()) {
5255- if (!Token::Match (memberToken, " %name% ::|< " ) )
5269+ if (!Token::Match (memberToken, " %name%" ) || memberToken-> str () != scopeIt-> name )
52565270 return nullptr ;
5257- if (memberToken->str () != scopeIt->name )
5271+ memberToken = skipQualification (memberToken);
5272+ if (!memberToken)
52585273 return nullptr ;
5259- if (memberToken->strAt (1 ) == " <" ) {
5260- memberToken = memberToken->next ()->findClosingBracket ();
5261- if (!Token::simpleMatch (memberToken, " > ::" ))
5262- return nullptr ;
5263- }
5264- memberToken = memberToken->tokAt (2 );
52655274 ++scopeIt;
52665275 }
52675276
@@ -5288,6 +5297,47 @@ static Token * matchMemberName(const Member &member, const std::list<ScopeInfo2>
52885297 return nullptr ;
52895298}
52905299
5300+ using MembersByScopeName = std::unordered_map<std::string, std::vector<const Member *>>;
5301+
5302+ // matchMemberName() can only match when the last scope name is matched by a name in the
5303+ // member's scope, in one of its "using namespace" or in its qualification. Index the members
5304+ // by these names, keeping their order, so that each scope only tries its candidates.
5305+ static MembersByScopeName indexMembersByScopeName (const std::list<Member> &members)
5306+ {
5307+ MembersByScopeName index;
5308+ for (const Member &member : members) {
5309+ // members are visited in order, so a member that is already a candidate is the last one
5310+ const auto addCandidate = [&](const std::string &name) {
5311+ std::vector<const Member *> &candidates = index[name];
5312+ if (candidates.empty () || candidates.back () != &member)
5313+ candidates.push_back (&member);
5314+ };
5315+ for (const std::string &name : member.scope )
5316+ addCandidate (name);
5317+ for (const Token *ns : member.usingnamespaces ) {
5318+ for (; Token::Match (ns, " %name% ::" ); ns = ns->tokAt (2 ))
5319+ addCandidate (ns->str ());
5320+ if (Token::Match (ns, " %name%" ))
5321+ addCandidate (ns->str ());
5322+ }
5323+ Token *tok = member.tok ;
5324+ while (Token *next = skipQualification (tok)) {
5325+ addCandidate (tok->str ());
5326+ tok = next;
5327+ }
5328+ }
5329+ return index;
5330+ }
5331+
5332+ static const std::vector<const Member *> &membersForScope (const MembersByScopeName &index, const std::list<ScopeInfo2> &scopeInfo)
5333+ {
5334+ static const std::vector<const Member *> none;
5335+ if (scopeInfo.empty ())
5336+ return none;
5337+ const auto it = index.find (scopeInfo.back ().name );
5338+ return it == index.end () ? none : it->second ;
5339+ }
5340+
52915341static Token * matchMemberVarName (const Member &var, const std::list<ScopeInfo2> &scopeInfo)
52925342{
52935343 Token *tok = matchMemberName (var, scopeInfo);
@@ -5399,6 +5449,9 @@ void Tokenizer::setVarIdPass2()
53995449 }
54005450 }
54015451
5452+ const MembersByScopeName memberFunctionsByScopeName = indexMembersByScopeName (allMemberFunctions);
5453+ const MembersByScopeName memberVarsByScopeName = indexMembersByScopeName (allMemberVars);
5454+
54025455 std::list<ScopeInfo2> scopeInfo;
54035456
54045457 // class members..
@@ -5515,8 +5568,8 @@ void Tokenizer::setVarIdPass2()
55155568 continue ;
55165569
55175570 // Member variables
5518- for (const Member & var : allMemberVars ) {
5519- Token *tok2 = matchMemberVarName (var, scopeInfo);
5571+ for (const Member * var : membersForScope (memberVarsByScopeName, scopeInfo) ) {
5572+ Token *tok2 = matchMemberVarName (* var, scopeInfo);
55205573 if (!tok2)
55215574 continue ;
55225575 if (tok2->varId () == 0 )
@@ -5527,8 +5580,8 @@ void Tokenizer::setVarIdPass2()
55275580 continue ;
55285581
55295582 // Set variable ids in member functions for this class..
5530- for (const Member & func : allMemberFunctions ) {
5531- Token *tok2 = matchMemberFunctionName (func, scopeInfo);
5583+ for (const Member * func : membersForScope (memberFunctionsByScopeName, scopeInfo) ) {
5584+ Token *tok2 = matchMemberFunctionName (* func, scopeInfo);
55325585 if (!tok2)
55335586 continue ;
55345587
0 commit comments