This commit is contained in:
Frank Zingsheim 2014-09-07 21:41:52 +02:00 committed by PKEuS
parent db929ffd19
commit 8c5013adda
3 changed files with 107 additions and 23 deletions

View File

@ -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,
const std::map<std::string, unsigned int> &variableId,
const unsigned int scopeStartVarId,
@ -2381,14 +2412,15 @@ static void setVarIdClassDeclaration(Token * const startToken,
// replace varids..
unsigned int indentlevel = 0;
bool initList = false;
const Token * initListEndToken = nullptr;
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
if (tok->str() == "{") {
initList = false;
if (tok == initListEndToken)
initListEndToken = nullptr;
++indentlevel;
} else if (tok->str() == "}")
--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());
if (it != variableId.end()) {
tok->varId(it->second);
@ -2411,7 +2443,7 @@ static void setVarIdClassDeclaration(Token * const startToken,
}
}
} 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()
{
// Clear all variable ids
@ -2486,14 +2506,22 @@ void Tokenizer::setVarId()
executableScope.push(false);
std::stack<unsigned int> scopestartvarid; // varid when scope starts
scopestartvarid.push(0);
bool initlist = false;
const Token * initListEndToken = nullptr;
for (Token *tok = list.front(); tok; tok = tok->next()) {
// scope info to handle shadow variables..
if (!initlist && tok->str() == "(" &&
(Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {") || isInitList(tok->link()))) {
bool newScope = false;
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);
initlist = Token::simpleMatch(tok->link(), ") :");
// function declarations
} else if (!executableScope.top() && tok->str() == "(" && Token::Match(tok->link(), ") const| ;")) {
@ -2503,22 +2531,24 @@ void Tokenizer::setVarId()
scopeInfo.pop();
} else if (tok->str() == "{") {
initlist = false;
// parse anonymous unions as part of the current scope
if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;"))) {
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);
} else {
executableScope.push(tok->strAt(-1) == "else");
scopeInfo.push(variableId);
}
}
if (tok == initListEndToken)
initListEndToken= nullptr;
} else if (tok->str() == "}") {
// parse anonymous unions as part of the current scope
if (!(Token::simpleMatch(tok, "} ;") && tok->link() && Token::simpleMatch(tok->link()->previous(), "union {"))) {
// Set variable ids in class declaration..
if (!isC() && !executableScope.top() && tok->link()) {
if (!initListEndToken && !isC() && !executableScope.top() && tok->link()) {
setVarIdClassDeclaration(tok->link(),
variableId,
scopestartvarid.top(),

View File

@ -5821,6 +5821,27 @@ private:
" }\n"
"};");
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) {

View File

@ -337,6 +337,7 @@ private:
TEST_CASE(varidclass14);
TEST_CASE(varidclass15); // initializer list
TEST_CASE(varidclass16); // #4577
TEST_CASE(varidclass17); // #6073
TEST_CASE(varid_classnameshaddowsvariablename); // #3990
TEST_CASE(varidnamespace1);
@ -4954,6 +4955,21 @@ private:
ASSERT_EQUALS("\n\n##file 0\n"
"1: class CPPCHECKLIB Scope { } ;\n",
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() {
@ -5429,6 +5445,23 @@ private:
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() {
const char code[] = "class Data;\n"
"void strange_declarated(const Data& Data);\n"