@@ -416,6 +416,7 @@ namespace {
416416 const Token * bodyEnd; // for body contains typedef define
417417 const Token * bodyEnd2; // for body contains typedef using
418418 bool isNamespace;
419+ std::set<std::string> recordTypes;
419420 };
420421}
421422
@@ -578,9 +579,13 @@ void Tokenizer::simplifyTypedef()
578579 std::vector<Space> spaceInfo;
579580 bool isNamespace = false ;
580581 std::string className;
582+ std::string fullClassName;
581583 bool hasClass = false ;
582584 bool goback = false ;
583585
586+ // add global namespace
587+ spaceInfo.emplace_back (Space{});
588+
584589 // Convert "using a::b;" to corresponding typedef statements
585590 simplifyUsingToTypedef ();
586591
@@ -609,9 +614,18 @@ void Tokenizer::simplifyTypedef()
609614 isNamespace = (tok->str () == " namespace" );
610615 hasClass = true ;
611616 className = tok->next ()->str ();
617+ const Token *tok1 = tok->next ();
618+ fullClassName = className;
619+ while (Token::Match (tok1, " %name% :: %name%" )) {
620+ tok1 = tok1->tokAt (2 );
621+ fullClassName += " :: " + tok1->str ();
622+ }
612623 } else if (hasClass && tok->str () == " ;" ) {
613624 hasClass = false ;
614625 } else if (hasClass && tok->str () == " {" ) {
626+ if (!isNamespace)
627+ spaceInfo.back ().recordTypes .insert (fullClassName);
628+
615629 Space info;
616630 info.isNamespace = isNamespace;
617631 info.className = className;
@@ -620,7 +634,7 @@ void Tokenizer::simplifyTypedef()
620634 spaceInfo.push_back (info);
621635
622636 hasClass = false ;
623- } else if (! spaceInfo.empty () && tok->str () == " }" && spaceInfo.back ().bodyEnd == tok) {
637+ } else if (spaceInfo.size () > 1 && tok->str () == " }" && spaceInfo.back ().bodyEnd == tok) {
624638 spaceInfo.pop_back ();
625639 }
626640 continue ;
@@ -1033,11 +1047,20 @@ void Tokenizer::simplifyTypedef()
10331047 int memberScope = 0 ;
10341048 bool globalScope = false ;
10351049 int classLevel = spaceInfo.size ();
1050+ std::string removed;
1051+ std::string classPath;
1052+ for (size_t i = 1 ; i < spaceInfo.size (); ++i) {
1053+ if (!classPath.empty ())
1054+ classPath += " :: " ;
1055+ classPath += spaceInfo[i].className ;
1056+ }
10361057
10371058 for (Token *tok2 = tok; tok2; tok2 = tok2->next ()) {
10381059 if (Settings::terminated ())
10391060 return ;
10401061
1062+ removed.clear ();
1063+
10411064 if (tok2->link ()) { // Pre-check for performance
10421065 // check for end of scope
10431066 if (tok2->str () == " }" ) {
@@ -1048,7 +1071,7 @@ void Tokenizer::simplifyTypedef()
10481071 inMemberFunc = false ;
10491072 }
10501073
1051- if (classLevel > 0 && tok2 == spaceInfo[classLevel - 1 ].bodyEnd2 ) {
1074+ if (classLevel > 1 && tok2 == spaceInfo[classLevel - 1 ].bodyEnd2 ) {
10521075 --classLevel;
10531076 pattern.clear ();
10541077
@@ -1080,7 +1103,7 @@ void Tokenizer::simplifyTypedef()
10801103 while (Token::Match (func->tokAt (offset - 2 ), " %name% ::" ))
10811104 offset -= 2 ;
10821105 // check for available and matching class name
1083- if (! spaceInfo.empty () && classLevel < spaceInfo.size () &&
1106+ if (spaceInfo.size () > 1 && classLevel < spaceInfo.size () &&
10841107 func->strAt (offset) == spaceInfo[classLevel].className ) {
10851108 memberScope = 0 ;
10861109 inMemberFunc = true ;
@@ -1126,7 +1149,7 @@ void Tokenizer::simplifyTypedef()
11261149 // check for qualifier
11271150 if (tok2->previous ()->str () == " ::" ) {
11281151 // check for available and matching class name
1129- if (! spaceInfo.empty () && classLevel < spaceInfo.size () &&
1152+ if (spaceInfo.size () > 1 && classLevel < spaceInfo.size () &&
11301153 tok2->strAt (-2 ) == spaceInfo[classLevel].className ) {
11311154 tok2 = tok2->next ();
11321155 simplifyType = true ;
@@ -1145,7 +1168,7 @@ void Tokenizer::simplifyTypedef()
11451168 int back = classLevel - 1 ;
11461169 bool good = true ;
11471170 // check for extra qualification
1148- while (back >= 0 ) {
1171+ while (back >= 1 ) {
11491172 Token *qualificationTok = start->tokAt (-2 );
11501173 if (!Token::Match (qualificationTok, " %type% ::" ))
11511174 break ;
@@ -1159,33 +1182,41 @@ void Tokenizer::simplifyTypedef()
11591182 }
11601183 }
11611184 // check global namespace
1162- if (good && back == 0 && start->strAt (-1 ) == " ::" )
1185+ if (good && back == 1 && start->strAt (-1 ) == " ::" )
11631186 good = false ;
11641187
11651188 if (good) {
11661189 // remove any extra qualification if present
11671190 while (count) {
1191+ if (!removed.empty ())
1192+ removed.insert (0 , " " );
1193+ removed.insert (0 , tok2->strAt (-2 ) + " " + tok2->strAt (-1 ));
11681194 tok2->tokAt (-3 )->deleteNext (2 );
11691195 --count;
11701196 }
11711197
11721198 // remove global namespace if present
11731199 if (tok2->strAt (-1 ) == " ::" ) {
1200+ removed.insert (0 , " :: " );
11741201 tok2->tokAt (-2 )->deleteNext ();
11751202 globalScope = true ;
11761203 }
11771204
11781205 // remove qualification if present
11791206 for (int i = classLevel; i < spaceInfo.size (); ++i) {
1180- tok2->deleteNext (2 );
1207+ if (!removed.empty ())
1208+ removed += " " ;
1209+ removed += (tok2->str () + " " + tok2->strAt (1 ));
1210+ tok2->deleteThis ();
1211+ tok2->deleteThis ();
11811212 }
11821213 simplifyType = true ;
11831214 }
11841215 } else {
11851216 if (tok2->strAt (-1 ) == " ::" ) {
11861217 int relativeSpaceInfoSize = spaceInfo.size ();
11871218 Token * tokBeforeType = tok2->previous ();
1188- while (relativeSpaceInfoSize != 0 &&
1219+ while (relativeSpaceInfoSize > 1 &&
11891220 tokBeforeType && tokBeforeType->str () == " ::" &&
11901221 tokBeforeType->strAt (-1 ) == spaceInfo[relativeSpaceInfoSize-1 ].className ) {
11911222 tokBeforeType = tokBeforeType->tokAt (-2 );
@@ -1302,6 +1333,33 @@ void Tokenizer::simplifyTypedef()
13021333 }
13031334 }
13041335
1336+ // add some qualification back if needed
1337+ Token *start = tok2;
1338+ std::string removed1 = removed;
1339+ std::string::size_type idx = removed1.rfind (" ::" );
1340+
1341+ if (idx != std::string::npos)
1342+ removed1.resize (idx);
1343+ if (removed1 == classPath && !removed1.empty ()) {
1344+ for (std::vector<Space>::const_reverse_iterator it = spaceInfo.crbegin (); it != spaceInfo.crend (); ++it) {
1345+ if (it->recordTypes .find (start->str ()) != it->recordTypes .end ()) {
1346+ std::string::size_type spaceIdx = 0 ;
1347+ std::string::size_type startIdx = 0 ;
1348+ while ((spaceIdx = removed1.find (" " , startIdx)) != std::string::npos) {
1349+ tok2->previous ()->insertToken (removed1.substr (startIdx, spaceIdx - startIdx));
1350+ startIdx = spaceIdx + 1 ;
1351+ }
1352+ tok2->previous ()->insertToken (removed1.substr (startIdx));
1353+ tok2->previous ()->insertToken (" ::" );
1354+ break ;
1355+ }
1356+ idx = removed1.rfind (" ::" );
1357+ if (idx == std::string::npos)
1358+ break ;
1359+
1360+ removed1.resize (idx);
1361+ }
1362+ }
13051363 // add remainder of type
13061364 tok2 = TokenList::copyTokens (tok2, typeStart->next (), typeEnd);
13071365
0 commit comments