Skip to content

Commit 8c5013a

Browse files
zingsheimPKEuS
authored andcommitted
1 parent db929ff commit 8c5013a

3 files changed

Lines changed: 107 additions & 23 deletions

File tree

lib/tokenize.cpp

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,6 +2359,37 @@ static void setVarIdStructMembers(Token **tok1,
23592359
}
23602360

23612361

2362+
static const Token * findInitListEndToken(const Token *tok)
2363+
{
2364+
if (!Token::Match(tok, ") :"))
2365+
return nullptr;
2366+
2367+
tok = tok->tokAt(2);
2368+
2369+
while (tok) {
2370+
if (tok && tok->str()=="::")
2371+
tok = tok->next();
2372+
2373+
while (tok && Token::Match(tok, "%type% ::"))
2374+
tok = tok->tokAt(2);
2375+
2376+
if (Token::Match(tok, "%var% [({]")) {
2377+
tok = tok->linkAt(1);
2378+
if (!tok)
2379+
return nullptr;
2380+
tok = tok->next();
2381+
}
2382+
if (tok && tok->str()==",")
2383+
tok = tok->next();
2384+
else if (tok && tok->str()=="{")
2385+
return tok; // End of init list found
2386+
else
2387+
return nullptr;
2388+
}
2389+
2390+
return nullptr;
2391+
}
2392+
23622393
static void setVarIdClassDeclaration(Token * const startToken,
23632394
const std::map<std::string, unsigned int> &variableId,
23642395
const unsigned int scopeStartVarId,
@@ -2381,14 +2412,15 @@ static void setVarIdClassDeclaration(Token * const startToken,
23812412

23822413
// replace varids..
23832414
unsigned int indentlevel = 0;
2384-
bool initList = false;
2415+
const Token * initListEndToken = nullptr;
23852416
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
23862417
if (tok->str() == "{") {
2387-
initList = false;
2418+
if (tok == initListEndToken)
2419+
initListEndToken = nullptr;
23882420
++indentlevel;
23892421
} else if (tok->str() == "}")
23902422
--indentlevel;
2391-
else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %var% (")) {
2423+
else if (initListEndToken && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %var% [({]")) {
23922424
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
23932425
if (it != variableId.end()) {
23942426
tok->varId(it->second);
@@ -2411,7 +2443,7 @@ static void setVarIdClassDeclaration(Token * const startToken,
24112443
}
24122444
}
24132445
} else if (indentlevel == 0 && tok->str() == ":")
2414-
initList = true;
2446+
initListEndToken = findInitListEndToken(tok->previous());
24152447
}
24162448
}
24172449

@@ -2444,18 +2476,6 @@ static void setVarIdClassFunction(const std::string &classname,
24442476
}
24452477
}
24462478

2447-
static bool isInitList(const Token *tok)
2448-
{
2449-
if (!Token::Match(tok, ") : %var% ("))
2450-
return false;
2451-
2452-
tok = tok->linkAt(3);
2453-
while (Token::Match(tok, ") , %var% ("))
2454-
tok = tok->linkAt(3);
2455-
2456-
return Token::simpleMatch(tok, ") {");
2457-
}
2458-
24592479
void Tokenizer::setVarId()
24602480
{
24612481
// Clear all variable ids
@@ -2486,14 +2506,22 @@ void Tokenizer::setVarId()
24862506
executableScope.push(false);
24872507
std::stack<unsigned int> scopestartvarid; // varid when scope starts
24882508
scopestartvarid.push(0);
2489-
bool initlist = false;
2509+
const Token * initListEndToken = nullptr;
24902510
for (Token *tok = list.front(); tok; tok = tok->next()) {
24912511

24922512
// scope info to handle shadow variables..
2493-
if (!initlist && tok->str() == "(" &&
2494-
(Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {") || isInitList(tok->link()))) {
2513+
bool newScope = false;
2514+
if (!initListEndToken && tok->str() == "(") {
2515+
if (Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {"))
2516+
newScope = true;
2517+
else {
2518+
initListEndToken = findInitListEndToken(tok->link());
2519+
if (initListEndToken)
2520+
newScope = true;
2521+
}
2522+
}
2523+
if (newScope) {
24952524
scopeInfo.push(variableId);
2496-
initlist = Token::simpleMatch(tok->link(), ") :");
24972525

24982526
// function declarations
24992527
} else if (!executableScope.top() && tok->str() == "(" && Token::Match(tok->link(), ") const| ;")) {
@@ -2503,22 +2531,24 @@ void Tokenizer::setVarId()
25032531
scopeInfo.pop();
25042532

25052533
} else if (tok->str() == "{") {
2506-
initlist = false;
25072534
// parse anonymous unions as part of the current scope
25082535
if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;"))) {
25092536
scopestartvarid.push(_varId);
2510-
if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%")) {
2537+
if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%") ||
2538+
tok == initListEndToken) {
25112539
executableScope.push(true);
25122540
} else {
25132541
executableScope.push(tok->strAt(-1) == "else");
25142542
scopeInfo.push(variableId);
25152543
}
25162544
}
2545+
if (tok == initListEndToken)
2546+
initListEndToken= nullptr;
25172547
} else if (tok->str() == "}") {
25182548
// parse anonymous unions as part of the current scope
25192549
if (!(Token::simpleMatch(tok, "} ;") && tok->link() && Token::simpleMatch(tok->link()->previous(), "union {"))) {
25202550
// Set variable ids in class declaration..
2521-
if (!isC() && !executableScope.top() && tok->link()) {
2551+
if (!initListEndToken && !isC() && !executableScope.top() && tok->link()) {
25222552
setVarIdClassDeclaration(tok->link(),
25232553
variableId,
25242554
scopestartvarid.top(),

test/testclass.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5821,6 +5821,27 @@ class TestClass : public TestFixture {
58215821
" }\n"
58225822
"};");
58235823
ASSERT_EQUALS("", errout.str());
5824+
5825+
checkSelfInitialization("struct Foo : Bar {\n"
5826+
" int i;\n"
5827+
" Foo(int i)\n"
5828+
" : Bar(""), i(i) {}\n"
5829+
"};");
5830+
ASSERT_EQUALS("", errout.str());
5831+
5832+
checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
5833+
" int i;\n"
5834+
" Foo(int i)\n"
5835+
" : std::Bar(""), i(i) {}\n"
5836+
"};");
5837+
ASSERT_EQUALS("", errout.str());
5838+
5839+
checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
5840+
" int i;\n"
5841+
" Foo(int i)\n"
5842+
" : std::Bar(""), i{i} {}\n"
5843+
"};");
5844+
ASSERT_EQUALS("", errout.str());
58245845
}
58255846

58265847
void checkPureVirtualFunctionCall(const char code[], const Settings *s = 0, bool inconclusive = true) {

test/testtokenize.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ class TestTokenizer : public TestFixture {
337337
TEST_CASE(varidclass14);
338338
TEST_CASE(varidclass15); // initializer list
339339
TEST_CASE(varidclass16); // #4577
340+
TEST_CASE(varidclass17); // #6073
340341
TEST_CASE(varid_classnameshaddowsvariablename); // #3990
341342

342343
TEST_CASE(varidnamespace1);
@@ -4954,6 +4955,21 @@ class TestTokenizer : public TestFixture {
49544955
ASSERT_EQUALS("\n\n##file 0\n"
49554956
"1: class CPPCHECKLIB Scope { } ;\n",
49564957
tokenizeDebugListing("class CPPCHECKLIB Scope { };"));
4958+
4959+
// #6073
4960+
ASSERT_EQUALS("\n\n##file 0\n"
4961+
"1: class A : public B , public C :: D {\n"
4962+
"2: int i@1 ;\n"
4963+
"3: A ( int i@2 ) : B { i@2 } , C :: D { i@2 } , i@1 { i@2 } {\n"
4964+
"4: int j@3 { i@2 } ;\n"
4965+
"5: }\n"
4966+
"6: } ;\n",
4967+
tokenizeDebugListing("class A: public B, public C::D {\n"
4968+
" int i;\n"
4969+
" A(int i): B{i}, C::D{i}, i{i} {\n"
4970+
" int j{i};\n"
4971+
" }\n"
4972+
"};"));
49574973
}
49584974

49594975
void varid_inheritedMembers() {
@@ -5429,6 +5445,23 @@ class TestTokenizer : public TestFixture {
54295445
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
54305446
}
54315447

5448+
void varidclass17() {
5449+
const char code[] = "class A: public B, public C::D {\n"
5450+
" int i;\n"
5451+
" A(int i): B(i), C::D(i), i(i) {\n"
5452+
" int j(i);\n"
5453+
" }\n"
5454+
"};";
5455+
const char expected[] = "\n\n##file 0\n"
5456+
"1: class A : public B , public C :: D {\n"
5457+
"2: int i@1 ;\n"
5458+
"3: A ( int i@2 ) : B ( i@2 ) , C :: D ( i@2 ) , i@1 ( i@2 ) {\n"
5459+
"4: int j@3 ; j@3 = i@2 ;\n"
5460+
"5: }\n"
5461+
"6: } ;\n";
5462+
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
5463+
}
5464+
54325465
void varid_classnameshaddowsvariablename() {
54335466
const char code[] = "class Data;\n"
54345467
"void strange_declarated(const Data& Data);\n"

0 commit comments

Comments
 (0)