Fixed #3755 (Tokenizer::setVarId: improve varid inside class for struct/class variables)
This commit is contained in:
parent
c3578e88b6
commit
df6f88b4fe
|
@ -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();
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue