Fixed #6073
This commit is contained in:
parent
db929ffd19
commit
8c5013adda
|
@ -2359,6 +2359,37 @@ static void setVarIdStructMembers(Token **tok1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const Token * findInitListEndToken(const Token *tok)
|
||||||
|
{
|
||||||
|
if (!Token::Match(tok, ") :"))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
|
||||||
|
while (tok) {
|
||||||
|
if (tok && tok->str()=="::")
|
||||||
|
tok = tok->next();
|
||||||
|
|
||||||
|
while (tok && Token::Match(tok, "%type% ::"))
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
|
||||||
|
if (Token::Match(tok, "%var% [({]")) {
|
||||||
|
tok = tok->linkAt(1);
|
||||||
|
if (!tok)
|
||||||
|
return nullptr;
|
||||||
|
tok = tok->next();
|
||||||
|
}
|
||||||
|
if (tok && tok->str()==",")
|
||||||
|
tok = tok->next();
|
||||||
|
else if (tok && tok->str()=="{")
|
||||||
|
return tok; // End of init list found
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static void setVarIdClassDeclaration(Token * const startToken,
|
static void setVarIdClassDeclaration(Token * const startToken,
|
||||||
const std::map<std::string, unsigned int> &variableId,
|
const std::map<std::string, unsigned int> &variableId,
|
||||||
const unsigned int scopeStartVarId,
|
const unsigned int scopeStartVarId,
|
||||||
|
@ -2381,14 +2412,15 @@ static void setVarIdClassDeclaration(Token * const startToken,
|
||||||
|
|
||||||
// replace varids..
|
// replace varids..
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
bool initList = false;
|
const Token * initListEndToken = nullptr;
|
||||||
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
|
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
|
||||||
if (tok->str() == "{") {
|
if (tok->str() == "{") {
|
||||||
initList = false;
|
if (tok == initListEndToken)
|
||||||
|
initListEndToken = nullptr;
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
} else if (tok->str() == "}")
|
} else if (tok->str() == "}")
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %var% (")) {
|
else if (initListEndToken && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %var% [({]")) {
|
||||||
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
||||||
if (it != variableId.end()) {
|
if (it != variableId.end()) {
|
||||||
tok->varId(it->second);
|
tok->varId(it->second);
|
||||||
|
@ -2411,7 +2443,7 @@ static void setVarIdClassDeclaration(Token * const startToken,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (indentlevel == 0 && tok->str() == ":")
|
} else if (indentlevel == 0 && tok->str() == ":")
|
||||||
initList = true;
|
initListEndToken = findInitListEndToken(tok->previous());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2444,18 +2476,6 @@ static void setVarIdClassFunction(const std::string &classname,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isInitList(const Token *tok)
|
|
||||||
{
|
|
||||||
if (!Token::Match(tok, ") : %var% ("))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
tok = tok->linkAt(3);
|
|
||||||
while (Token::Match(tok, ") , %var% ("))
|
|
||||||
tok = tok->linkAt(3);
|
|
||||||
|
|
||||||
return Token::simpleMatch(tok, ") {");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tokenizer::setVarId()
|
void Tokenizer::setVarId()
|
||||||
{
|
{
|
||||||
// Clear all variable ids
|
// Clear all variable ids
|
||||||
|
@ -2486,14 +2506,22 @@ void Tokenizer::setVarId()
|
||||||
executableScope.push(false);
|
executableScope.push(false);
|
||||||
std::stack<unsigned int> scopestartvarid; // varid when scope starts
|
std::stack<unsigned int> scopestartvarid; // varid when scope starts
|
||||||
scopestartvarid.push(0);
|
scopestartvarid.push(0);
|
||||||
bool initlist = false;
|
const Token * initListEndToken = nullptr;
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
|
||||||
// scope info to handle shadow variables..
|
// scope info to handle shadow variables..
|
||||||
if (!initlist && tok->str() == "(" &&
|
bool newScope = false;
|
||||||
(Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {") || isInitList(tok->link()))) {
|
if (!initListEndToken && tok->str() == "(") {
|
||||||
|
if (Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {"))
|
||||||
|
newScope = true;
|
||||||
|
else {
|
||||||
|
initListEndToken = findInitListEndToken(tok->link());
|
||||||
|
if (initListEndToken)
|
||||||
|
newScope = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newScope) {
|
||||||
scopeInfo.push(variableId);
|
scopeInfo.push(variableId);
|
||||||
initlist = Token::simpleMatch(tok->link(), ") :");
|
|
||||||
|
|
||||||
// function declarations
|
// function declarations
|
||||||
} else if (!executableScope.top() && tok->str() == "(" && Token::Match(tok->link(), ") const| ;")) {
|
} else if (!executableScope.top() && tok->str() == "(" && Token::Match(tok->link(), ") const| ;")) {
|
||||||
|
@ -2503,22 +2531,24 @@ void Tokenizer::setVarId()
|
||||||
scopeInfo.pop();
|
scopeInfo.pop();
|
||||||
|
|
||||||
} else if (tok->str() == "{") {
|
} else if (tok->str() == "{") {
|
||||||
initlist = false;
|
|
||||||
// parse anonymous unions as part of the current scope
|
// parse anonymous unions as part of the current scope
|
||||||
if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;"))) {
|
if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;"))) {
|
||||||
scopestartvarid.push(_varId);
|
scopestartvarid.push(_varId);
|
||||||
if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%")) {
|
if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%") ||
|
||||||
|
tok == initListEndToken) {
|
||||||
executableScope.push(true);
|
executableScope.push(true);
|
||||||
} else {
|
} else {
|
||||||
executableScope.push(tok->strAt(-1) == "else");
|
executableScope.push(tok->strAt(-1) == "else");
|
||||||
scopeInfo.push(variableId);
|
scopeInfo.push(variableId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tok == initListEndToken)
|
||||||
|
initListEndToken= nullptr;
|
||||||
} else if (tok->str() == "}") {
|
} else if (tok->str() == "}") {
|
||||||
// parse anonymous unions as part of the current scope
|
// parse anonymous unions as part of the current scope
|
||||||
if (!(Token::simpleMatch(tok, "} ;") && tok->link() && Token::simpleMatch(tok->link()->previous(), "union {"))) {
|
if (!(Token::simpleMatch(tok, "} ;") && tok->link() && Token::simpleMatch(tok->link()->previous(), "union {"))) {
|
||||||
// Set variable ids in class declaration..
|
// Set variable ids in class declaration..
|
||||||
if (!isC() && !executableScope.top() && tok->link()) {
|
if (!initListEndToken && !isC() && !executableScope.top() && tok->link()) {
|
||||||
setVarIdClassDeclaration(tok->link(),
|
setVarIdClassDeclaration(tok->link(),
|
||||||
variableId,
|
variableId,
|
||||||
scopestartvarid.top(),
|
scopestartvarid.top(),
|
||||||
|
|
|
@ -5821,6 +5821,27 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
checkSelfInitialization("struct Foo : Bar {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" Foo(int i)\n"
|
||||||
|
" : Bar(""), i(i) {}\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
|
||||||
|
" int i;\n"
|
||||||
|
" Foo(int i)\n"
|
||||||
|
" : std::Bar(""), i(i) {}\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
|
||||||
|
" int i;\n"
|
||||||
|
" Foo(int i)\n"
|
||||||
|
" : std::Bar(""), i{i} {}\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkPureVirtualFunctionCall(const char code[], const Settings *s = 0, bool inconclusive = true) {
|
void checkPureVirtualFunctionCall(const char code[], const Settings *s = 0, bool inconclusive = true) {
|
||||||
|
|
|
@ -337,6 +337,7 @@ private:
|
||||||
TEST_CASE(varidclass14);
|
TEST_CASE(varidclass14);
|
||||||
TEST_CASE(varidclass15); // initializer list
|
TEST_CASE(varidclass15); // initializer list
|
||||||
TEST_CASE(varidclass16); // #4577
|
TEST_CASE(varidclass16); // #4577
|
||||||
|
TEST_CASE(varidclass17); // #6073
|
||||||
TEST_CASE(varid_classnameshaddowsvariablename); // #3990
|
TEST_CASE(varid_classnameshaddowsvariablename); // #3990
|
||||||
|
|
||||||
TEST_CASE(varidnamespace1);
|
TEST_CASE(varidnamespace1);
|
||||||
|
@ -4954,6 +4955,21 @@ private:
|
||||||
ASSERT_EQUALS("\n\n##file 0\n"
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
"1: class CPPCHECKLIB Scope { } ;\n",
|
"1: class CPPCHECKLIB Scope { } ;\n",
|
||||||
tokenizeDebugListing("class CPPCHECKLIB Scope { };"));
|
tokenizeDebugListing("class CPPCHECKLIB Scope { };"));
|
||||||
|
|
||||||
|
// #6073
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: class A : public B , public C :: D {\n"
|
||||||
|
"2: int i@1 ;\n"
|
||||||
|
"3: A ( int i@2 ) : B { i@2 } , C :: D { i@2 } , i@1 { i@2 } {\n"
|
||||||
|
"4: int j@3 { i@2 } ;\n"
|
||||||
|
"5: }\n"
|
||||||
|
"6: } ;\n",
|
||||||
|
tokenizeDebugListing("class A: public B, public C::D {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" A(int i): B{i}, C::D{i}, i{i} {\n"
|
||||||
|
" int j{i};\n"
|
||||||
|
" }\n"
|
||||||
|
"};"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void varid_inheritedMembers() {
|
void varid_inheritedMembers() {
|
||||||
|
@ -5429,6 +5445,23 @@ private:
|
||||||
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void varidclass17() {
|
||||||
|
const char code[] = "class A: public B, public C::D {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" A(int i): B(i), C::D(i), i(i) {\n"
|
||||||
|
" int j(i);\n"
|
||||||
|
" }\n"
|
||||||
|
"};";
|
||||||
|
const char expected[] = "\n\n##file 0\n"
|
||||||
|
"1: class A : public B , public C :: D {\n"
|
||||||
|
"2: int i@1 ;\n"
|
||||||
|
"3: A ( int i@2 ) : B ( i@2 ) , C :: D ( i@2 ) , i@1 ( i@2 ) {\n"
|
||||||
|
"4: int j@3 ; j@3 = i@2 ;\n"
|
||||||
|
"5: }\n"
|
||||||
|
"6: } ;\n";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
||||||
|
}
|
||||||
|
|
||||||
void varid_classnameshaddowsvariablename() {
|
void varid_classnameshaddowsvariablename() {
|
||||||
const char code[] = "class Data;\n"
|
const char code[] = "class Data;\n"
|
||||||
"void strange_declarated(const Data& Data);\n"
|
"void strange_declarated(const Data& Data);\n"
|
||||||
|
|
Loading…
Reference in New Issue