Support inherited member variables in setVarId (#4101)
This commit is contained in:
parent
5a96413220
commit
8c24553229
|
@ -2661,22 +2661,29 @@ void Tokenizer::setVarId()
|
||||||
}
|
}
|
||||||
|
|
||||||
// class members..
|
// class members..
|
||||||
|
std::map<std::string, std::map<std::string, unsigned int>> varlist;
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "namespace|class|struct %var% {|:")) {
|
if (Token::Match(tok, "namespace|class|struct %var% {|:")) {
|
||||||
const std::string &classname(tok->next()->str());
|
const std::string &classname(tok->next()->str());
|
||||||
|
|
||||||
bool namesp = tok->str() == "namespace";
|
bool namesp = tok->str() == "namespace";
|
||||||
|
|
||||||
|
const Token* tokStart = tok->tokAt(2);
|
||||||
|
while (tokStart && tokStart->str() != "{") {
|
||||||
|
if (Token::Match(tokStart, "public|private|protected"))
|
||||||
|
tokStart = tokStart->next();
|
||||||
|
if (tokStart->strAt(1) == "," || tokStart->strAt(1) == "{")
|
||||||
|
varlist[classname].insert(varlist[tokStart->str()].begin(), varlist[tokStart->str()].end());
|
||||||
|
tokStart = tokStart->next();
|
||||||
|
}
|
||||||
// What member variables are there in this class?
|
// What member variables are there in this class?
|
||||||
std::map<std::string, unsigned int> varlist;
|
|
||||||
const Token* tokStart = Token::findsimplematch(tok, "{");
|
|
||||||
if (tokStart) {
|
if (tokStart) {
|
||||||
for (Token *tok2 = tokStart->next(); tok2 && tok2 != tokStart->link(); tok2 = tok2->next()) {
|
for (Token *tok2 = tokStart->next(); tok2 && tok2 != tokStart->link(); tok2 = tok2->next()) {
|
||||||
// skip parentheses..
|
// skip parentheses..
|
||||||
if (tok2->link()) {
|
if (tok2->link()) {
|
||||||
if (tok2->str() == "{") {
|
if (tok2->str() == "{") {
|
||||||
if (tok2->strAt(-1) == ")" || tok2->strAt(-2) == ")")
|
if (tok2->strAt(-1) == ")" || tok2->strAt(-2) == ")")
|
||||||
setVarIdClassFunction(classname, tok2, tok2->link(), varlist, &structMembers, &_varId);
|
setVarIdClassFunction(classname, tok2, tok2->link(), varlist[classname], &structMembers, &_varId);
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
} else if (tok2->str() == "(" && tok2->link()->strAt(1) != "(")
|
} else if (tok2->str() == "(" && tok2->link()->strAt(1) != "(")
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
|
@ -2684,12 +2691,12 @@ void Tokenizer::setVarId()
|
||||||
|
|
||||||
// Found a member variable..
|
// Found a member variable..
|
||||||
else if (tok2->varId() > 0)
|
else if (tok2->varId() > 0)
|
||||||
varlist[tok2->str()] = tok2->varId();
|
varlist[classname][tok2->str()] = tok2->varId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are there any member variables in this class?
|
// Are there any member variables in this class?
|
||||||
if (varlist.empty())
|
if (varlist[classname].empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Member variables
|
// Member variables
|
||||||
|
@ -2699,7 +2706,7 @@ void Tokenizer::setVarId()
|
||||||
|
|
||||||
Token *tok2 = *func;
|
Token *tok2 = *func;
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
tok2->varId(varlist[tok2->str()]);
|
tok2->varId(varlist[classname][tok2->str()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namesp)
|
if (namesp)
|
||||||
|
@ -2720,7 +2727,7 @@ void Tokenizer::setVarId()
|
||||||
// If this is a function implementation.. add it to funclist
|
// If this is a function implementation.. add it to funclist
|
||||||
Token * start = startOfFunction(tok2);
|
Token * start = startOfFunction(tok2);
|
||||||
if (start) {
|
if (start) {
|
||||||
setVarIdClassFunction(classname, start, start->link(), varlist, &structMembers, &_varId);
|
setVarIdClassFunction(classname, start, start->link(), varlist[classname], &structMembers, &_varId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor with initializer list
|
// constructor with initializer list
|
||||||
|
@ -2728,12 +2735,12 @@ void Tokenizer::setVarId()
|
||||||
Token *tok3 = tok2;
|
Token *tok3 = tok2;
|
||||||
while (Token::Match(tok3, ") [:,] %var% (")) {
|
while (Token::Match(tok3, ") [:,] %var% (")) {
|
||||||
Token *vartok = tok3->tokAt(2);
|
Token *vartok = tok3->tokAt(2);
|
||||||
if (varlist.find(vartok->str()) != varlist.end())
|
if (varlist[classname].find(vartok->str()) != varlist[classname].end())
|
||||||
vartok->varId(varlist[vartok->str()]);
|
vartok->varId(varlist[classname][vartok->str()]);
|
||||||
tok3 = tok3->linkAt(3);
|
tok3 = tok3->linkAt(3);
|
||||||
}
|
}
|
||||||
if (Token::simpleMatch(tok3, ") {")) {
|
if (Token::simpleMatch(tok3, ") {")) {
|
||||||
setVarIdClassFunction(classname, tok2, tok3->next()->link(), varlist, &structMembers, &_varId);
|
setVarIdClassFunction(classname, tok2, tok3->next()->link(), varlist[classname], &structMembers, &_varId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,6 +319,7 @@ private:
|
||||||
TEST_CASE(varid_classInFunction); // #5293
|
TEST_CASE(varid_classInFunction); // #5293
|
||||||
TEST_CASE(varid_pointerToArray); // #2645
|
TEST_CASE(varid_pointerToArray); // #2645
|
||||||
TEST_CASE(varid_cpp11initialization); // #4344
|
TEST_CASE(varid_cpp11initialization); // #4344
|
||||||
|
TEST_CASE(varid_inheritedMembers); // #4101
|
||||||
|
|
||||||
TEST_CASE(varidclass1);
|
TEST_CASE(varidclass1);
|
||||||
TEST_CASE(varidclass2);
|
TEST_CASE(varidclass2);
|
||||||
|
@ -4954,6 +4955,86 @@ private:
|
||||||
tokenizeDebugListing("class CPPCHECKLIB Scope { };"));
|
tokenizeDebugListing("class CPPCHECKLIB Scope { };"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void varid_inheritedMembers() {
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: class A {\n"
|
||||||
|
"2: int a@1 ;\n"
|
||||||
|
"3: } ;\n"
|
||||||
|
"4: class B : public A {\n"
|
||||||
|
"5: void f ( ) ;\n"
|
||||||
|
"6: } ;\n"
|
||||||
|
"7: void B :: f ( ) {\n"
|
||||||
|
"8: a@1 = 0 ;\n"
|
||||||
|
"9: }\n",
|
||||||
|
tokenizeDebugListing("class A {\n"
|
||||||
|
" int a;\n"
|
||||||
|
"};\n"
|
||||||
|
"class B : public A {\n"
|
||||||
|
" void f();\n"
|
||||||
|
"};\n"
|
||||||
|
"void B::f() {\n"
|
||||||
|
" a = 0;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: class A {\n"
|
||||||
|
"2: int a@1 ;\n"
|
||||||
|
"3: } ;\n"
|
||||||
|
"4: class B : A {\n"
|
||||||
|
"5: void f ( ) ;\n"
|
||||||
|
"6: } ;\n"
|
||||||
|
"7: void B :: f ( ) {\n"
|
||||||
|
"8: a@1 = 0 ;\n"
|
||||||
|
"9: }\n",
|
||||||
|
tokenizeDebugListing("class A {\n"
|
||||||
|
" int a;\n"
|
||||||
|
"};\n"
|
||||||
|
"class B : A {\n"
|
||||||
|
" void f();\n"
|
||||||
|
"};\n"
|
||||||
|
"void B::f() {\n"
|
||||||
|
" a = 0;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: class A {\n"
|
||||||
|
"2: int a@1 ;\n"
|
||||||
|
"3: } ;\n"
|
||||||
|
"4: class B : protected B , public A {\n"
|
||||||
|
"5: void f ( ) ;\n"
|
||||||
|
"6: } ;\n"
|
||||||
|
"7: void B :: f ( ) {\n"
|
||||||
|
"8: a@1 = 0 ;\n"
|
||||||
|
"9: }\n",
|
||||||
|
tokenizeDebugListing("class A {\n"
|
||||||
|
" int a;\n"
|
||||||
|
"};\n"
|
||||||
|
"class B : protected B, public A {\n"
|
||||||
|
" void f();\n"
|
||||||
|
"};\n"
|
||||||
|
"void B::f() {\n"
|
||||||
|
" a = 0;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: class A {\n"
|
||||||
|
"2: int a@1 ;\n"
|
||||||
|
"3: } ;\n"
|
||||||
|
"4: class B : public A {\n"
|
||||||
|
"5: void f ( ) {\n"
|
||||||
|
"6: a@1 = 0 ;\n"
|
||||||
|
"7: }\n"
|
||||||
|
"8: } ;\n",
|
||||||
|
tokenizeDebugListing("class A {\n"
|
||||||
|
" int a;\n"
|
||||||
|
"};\n"
|
||||||
|
"class B : public A {\n"
|
||||||
|
" void f() {\n"
|
||||||
|
" a = 0;\n"
|
||||||
|
" }\n"
|
||||||
|
"};"));
|
||||||
|
}
|
||||||
|
|
||||||
void varidclass1() {
|
void varidclass1() {
|
||||||
const std::string actual = tokenizeDebugListing(
|
const std::string actual = tokenizeDebugListing(
|
||||||
"class Fred\n"
|
"class Fred\n"
|
||||||
|
|
Loading…
Reference in New Issue