Fixed #3755 (Tokenizer::setVarId: improve varid inside class for struct/class variables)

This commit is contained in:
Daniel Marjamäki 2012-04-26 18:38:47 +02:00
parent c3578e88b6
commit df6f88b4fe
2 changed files with 89 additions and 42 deletions

View File

@ -2801,47 +2801,6 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
return bool(typeCount >= 2 && tok2 && Token::Match(tok2->tokAt(-2), "!!:: %type%"));
}
static void setVarIdClassDeclaration(Token * const startToken, const std::map<std::string, unsigned int> &variableId, const unsigned int scopeStartVarId)
{
// end of scope
const Token * const endToken = startToken->link();
// determine class name
std::string className;
for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
if (!tok->isName() && tok->str() != ":")
break;
if (Token::Match(tok, "class|struct %type% [:{]")) {
className = tok->next()->str();
break;
}
}
// replace varids..
unsigned int indentlevel = 0;
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}")
--indentlevel;
else if (indentlevel > 0 && tok->isName() && tok->varId() <= scopeStartVarId) {
if (tok->previous()->str() == "::")
continue;
if (tok->next()->str() == "::") {
if (tok->str() == className)
tok = tok->tokAt(2);
else
continue;
}
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
if (it != variableId.end()) {
tok->varId(it->second);
}
}
}
}
static void setVarIdStructMembers(Token **tok1,
std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
@ -2878,6 +2837,54 @@ static void setVarIdStructMembers(Token **tok1,
}
static void setVarIdClassDeclaration(Token * const startToken,
const std::map<std::string, unsigned int> &variableId,
const unsigned int scopeStartVarId,
std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
unsigned int *_varId)
{
// end of scope
const Token * const endToken = startToken->link();
// determine class name
std::string className;
for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
if (!tok->isName() && tok->str() != ":")
break;
if (Token::Match(tok, "class|struct %type% [:{]")) {
className = tok->next()->str();
break;
}
}
// replace varids..
unsigned int indentlevel = 0;
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}")
--indentlevel;
else if (indentlevel > 0 && tok->isName() && tok->varId() <= scopeStartVarId) {
if (Token::Match(tok->previous(), "::|."))
continue;
if (tok->next()->str() == "::") {
if (tok->str() == className)
tok = tok->tokAt(2);
else
continue;
}
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
if (it != variableId.end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, _varId);
}
}
}
}
// Update the variable ids..
// Parse each function..
static void setVarIdClassFunction(Token * const startToken,
@ -2940,7 +2947,11 @@ void Tokenizer::setVarId()
} else if (tok->str() == "}") {
// Set variable ids in class declaration..
if (!isC() && !executableScope.top() && tok->link()) {
setVarIdClassDeclaration(tok->link(), variableId, scopestartvarid.top());
setVarIdClassDeclaration(tok->link(),
variableId,
scopestartvarid.top(),
&structMembers,
&_varId);
}
scopestartvarid.pop();

View File

@ -223,6 +223,8 @@ private:
TEST_CASE(varid_in_class3); // #3092 - shadow variable in member function
TEST_CASE(varid_in_class4); // #3271 - public: class C;
TEST_CASE(varid_in_class5); // #3584 - std::vector<::FOO::B> b;
TEST_CASE(varid_in_class6); // #3755
TEST_CASE(varid_in_class7); // set variable id for struct members
TEST_CASE(varid_operator);
TEST_CASE(varid_throw);
TEST_CASE(varid_unknown_macro); // #2638 - unknown macro is not type
@ -3532,6 +3534,40 @@ private:
tokenizeDebugListing(code));
}
void varid_in_class6() {
const char code[] = "class A {\n"
" void f(const char *str) const {\n"
" std::stringstream sst;\n"
" sst.str();\n"
" }\n"
"};";
ASSERT_EQUALS("\n\n##file 0\n"
"1: class A {\n"
"2: void f ( const char * str@1 ) const {\n"
"3: std :: stringstream sst@2 ;\n"
"4: sst@2 . str ( ) ;\n"
"5: }\n"
"6: } ;\n",
tokenizeDebugListing(code));
}
void varid_in_class7() {
const char code[] = "class A {\n"
" void f() {\n"
" abc.a = 0;\n"
" }\n"
" struct ABC abc;\n"
"};";
ASSERT_EQUALS("\n\n##file 0\n"
"1: class A {\n"
"2: void f ( ) {\n"
"3: abc@1 . a@2 = 0 ;\n"
"4: }\n"
"5: struct ABC abc@1 ;\n"
"6: } ;\n",
tokenizeDebugListing(code));
}
void varid_operator() {
{
const std::string actual = tokenizeDebugListing(