Tokenizer::setVarId: better handling of initializer lists

This commit is contained in:
Daniel Marjamäki 2012-04-23 18:26:27 +02:00
parent 5086ae7c31
commit 6ae135124e
3 changed files with 53 additions and 19 deletions

View File

@ -2885,6 +2885,26 @@ static void setVarIdStructMembers(Token **tok1,
} }
// Update the variable ids..
// Parse each function..
static void setVarIdClassFunction(Token * const startToken,
const Token * const endToken,
const std::map<std::string, unsigned int> &varlist,
std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
unsigned int *_varId)
{
for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
if (tok2->varId() == 0 && tok2->previous()->str() != ".") {
const std::map<std::string,unsigned int>::const_iterator it = varlist.find(tok2->str());
if (it != varlist.end()) {
tok2->varId(it->second);
setVarIdStructMembers(&tok2, structMembers, _varId);
}
}
}
}
void Tokenizer::setVarId() void Tokenizer::setVarId()
{ {
// Clear all variable ids // Clear all variable ids
@ -3084,27 +3104,24 @@ void Tokenizer::setVarId()
// If this is a function implementation.. add it to funclist // If this is a function implementation.. add it to funclist
if (Token::Match(tok2, ") const|volatile| {")) { if (Token::Match(tok2, ") const|volatile| {")) {
if (tok2->next()->str() != "{") while (tok2->str() != "{")
tok2 = tok2->next(); tok2 = tok2->next();
funclist.push_back(tok2->next()); setVarIdClassFunction(tok2, tok2->link(), varlist, &structMembers, &_varId);
}
}
}
} }
// Update the variable ids.. // constructor with initializer list
// Parse each function.. if (Token::Match(tok2, ") : %var% (")) {
for (std::list<Token *>::iterator func = funclist.begin(); func != funclist.end(); ++func) { const Token *tok3 = tok2;
for (Token *tok2 = (*func)->next(); tok2 != (*func)->link(); tok2 = tok2->next()) { while (Token::Match(tok3, ") [:,] %var% (")) {
if (tok2->varId() == 0 && tok3 = tok3->linkAt(3);
tok2->strAt(-1) != "." && }
varlist.find(tok2->str()) != varlist.end()) { if (Token::simpleMatch(tok3, ") {")) {
tok2->varId(varlist[tok2->str()]); setVarIdClassFunction(tok2, tok3->next()->link(), varlist, &structMembers, &_varId);
setVarIdStructMembers(&tok2, &structMembers, &_varId); }
}
} }
} }
} }
} }
} }
} }

View File

@ -1916,9 +1916,8 @@ private:
" Foo();\n" " Foo();\n"
"};\n" "};\n"
"Foo::Foo() : s(0) {}"); "Foo::Foo() : s(0) {}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n" ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n"
"[test.cpp:9]: (error) Null pointer dereference\n", "[test.cpp:9]: (error) Null pointer dereference\n", errout.str());
"[test.cpp:3]: (error) Null pointer dereference\n", errout.str());
check("void f() {\n" check("void f() {\n"
" std::string s = 0 == x ? \"a\" : \"b\";\n" " std::string s = 0 == x ? \"a\" : \"b\";\n"

View File

@ -241,6 +241,7 @@ private:
TEST_CASE(varidclass12); TEST_CASE(varidclass12);
TEST_CASE(varidclass13); TEST_CASE(varidclass13);
TEST_CASE(varidclass14); TEST_CASE(varidclass14);
TEST_CASE(varidclass15); // initializer list
TEST_CASE(file1); TEST_CASE(file1);
TEST_CASE(file2); TEST_CASE(file2);
@ -3942,6 +3943,23 @@ private:
} }
} }
void varidclass15() {
const char code[] = "class A {\n"
" int a;\n"
" int b;\n"
" A();\n"
"};\n"
"A::A() : a(0) { b = 1; }";
const char expected[] = "\n\n##file 0\n"
"1: class A {\n"
"2: int a@1 ;\n"
"3: int b@2 ;\n"
"4: A ( ) ;\n"
"5: } ;\n"
"6: A :: A ( ) : a@1 ( 0 ) { b@2 = 1 ; }\n";
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void file1() { void file1() {
const char code[] = "a1\n" const char code[] = "a1\n"
"#file \"b\"\n" "#file \"b\"\n"