Fixed #7788 (Varid missing for member variable in ctor of template class)

This commit is contained in:
Daniel Marjamäki 2017-11-10 21:03:15 +01:00
parent 7ec0e41196
commit 6b1a2dcc5d
2 changed files with 54 additions and 27 deletions

View File

@ -2970,47 +2970,51 @@ void Tokenizer::setVarIdPass2()
std::map<const Token *, std::string> endOfScope; std::map<const Token *, std::string> endOfScope;
std::list<std::string> scope; std::list<std::string> scope;
std::list<const Token *> usingnamespaces; std::list<const Token *> usingnamespaces;
for (Token *tok2 = list.front(); tok2; tok2 = tok2->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (!tok2->previous() || Token::Match(tok2->previous(), "[;{}]")) { if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) {
if (Token::Match(tok2, "using namespace %name% ::|;")) { if (Token::Match(tok, "using namespace %name% ::|;")) {
const Token *endtok = tok2->tokAt(2); const Token *endtok = tok->tokAt(2);
while (Token::Match(endtok, "%name% ::")) while (Token::Match(endtok, "%name% ::"))
endtok = endtok->tokAt(2); endtok = endtok->tokAt(2);
if (Token::Match(endtok, "%name% ;")) if (Token::Match(endtok, "%name% ;"))
usingnamespaces.push_back(tok2->tokAt(2)); usingnamespaces.push_back(tok->tokAt(2));
} else if (Token::Match(tok2, "namespace %name% {")) { } else if (Token::Match(tok, "namespace %name% {")) {
scope.push_back(tok2->strAt(1)); scope.push_back(tok->strAt(1));
endOfScope[tok2->linkAt(2)] = tok2->strAt(1); endOfScope[tok->linkAt(2)] = tok->strAt(1);
} }
} }
if (tok2->str() == "}") { if (tok->str() == "}") {
std::map<const Token *, std::string>::iterator it = endOfScope.find(tok2); std::map<const Token *, std::string>::iterator it = endOfScope.find(tok);
if (it != endOfScope.end()) if (it != endOfScope.end())
scope.remove(it->second); scope.remove(it->second);
} }
const Token* tok3 = nullptr; Token* const tok1 = tok;
if (Token::Match(tok2, "%name% :: ~| %name%")) if (Token::Match(tok->previous(), "!!:: %name% :: ~| %name%"))
tok3 = tok2->next(); tok = tok->next();
else if (Token::Match(tok2, "%name% <") && Token::Match(tok2->next()->findClosingBracket(),"> :: ~| %name%")) else if (Token::Match(tok->previous(), "!!:: %name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
tok3 = tok2->next()->findClosingBracket()->next(); tok = tok->next()->findClosingBracket()->next();
else else
continue; continue;
while (Token::Match(tok3, ":: ~| %name%")) { while (Token::Match(tok, ":: ~| %name%")) {
tok3 = tok3->next(); tok = tok->next();
if (tok3->str() == "~") if (tok->str() == "~")
tok3 = tok3->next(); tok = tok->next();
tok3 = tok3->next(); else if (Token::Match(tok, "%name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
tok = tok->next()->findClosingBracket()->next();
else if (Token::Match(tok, "%name% ::"))
tok = tok->next();
else
break;
} }
if (!tok3) if (!tok)
syntaxError(tok2); syntaxError(tok1);
const std::string& str3 = tok3->str(); if (Token::Match(tok, "%name% ("))
if (str3 == "(") allMemberFunctions.push_back(Member(scope, usingnamespaces, tok1));
allMemberFunctions.push_back(Member(scope, usingnamespaces, tok2)); else
else if (str3 != "::" && tok2->strAt(-1) != "::") // Support only one depth allMemberVars.push_back(Member(scope, usingnamespaces, tok1));
allMemberVars.push_back(Member(scope, usingnamespaces, tok2));
} }
} }

View File

@ -126,6 +126,7 @@ private:
TEST_CASE(varid_in_class18); // #7127 TEST_CASE(varid_in_class18); // #7127
TEST_CASE(varid_in_class19); TEST_CASE(varid_in_class19);
TEST_CASE(varid_in_class20); // #7267 TEST_CASE(varid_in_class20); // #7267
TEST_CASE(varid_in_class21); // #7788
TEST_CASE(varid_namespace_1); // #7272 TEST_CASE(varid_namespace_1); // #7272
TEST_CASE(varid_namespace_2); // #7000 TEST_CASE(varid_namespace_2); // #7000
TEST_CASE(varid_initList); TEST_CASE(varid_initList);
@ -1769,6 +1770,28 @@ private:
"8: template < class C > cacheEntry < C > :: cacheEntry ( ) : m_key@1 ( ) { }\n", tokenize(code, false, "test.cpp")); "8: template < class C > cacheEntry < C > :: cacheEntry ( ) : m_key@1 ( ) { }\n", tokenize(code, false, "test.cpp"));
} }
void varid_in_class21() {
const char code[] = "template <typename t1,typename t2>\n"
"class A::B {\n"
" B();\n"
" int x;\n"
"};\n"
"\n"
"template <typename t1,typename t2>\n"
"A::B<t1,t2>::B() : x(9) {}";
const char expected[] = "1: template < typename t1 , typename t2 >\n"
"2: class A :: B {\n"
"3: B ( ) ;\n"
"4: int x@1 ;\n"
"5: } ;\n"
"6:\n"
"7: template < typename t1 , typename t2 >\n"
"8: A :: B < t1 , t2 > :: B ( ) : x@1 ( 9 ) { }\n";
ASSERT_EQUALS(expected, tokenize(code, false, "test.cpp"));
}
void varid_namespace_1() { // #7272 void varid_namespace_1() { // #7272
const char code[] = "namespace Blah {\n" const char code[] = "namespace Blah {\n"
" struct foo { int x;};\n" " struct foo { int x;};\n"