Skip to content

Commit 6642897

Browse files
authored
fix simplifyTypedef removing needed type qualification (danmar#3058)
1 parent 5391880 commit 6642897

2 files changed

Lines changed: 295 additions & 8 deletions

File tree

lib/tokenize.cpp

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)