diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 891f99b44..ea340dfdc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2801,47 +2801,6 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map= 2 && tok2 && Token::Match(tok2->tokAt(-2), "!!:: %type%")); } -static void setVarIdClassDeclaration(Token * const startToken, const std::map &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::const_iterator it = variableId.find(tok->str()); - if (it != variableId.end()) { - tok->varId(it->second); - } - } - } -} - static void setVarIdStructMembers(Token **tok1, std::map > *structMembers, @@ -2878,6 +2837,54 @@ static void setVarIdStructMembers(Token **tok1, } +static void setVarIdClassDeclaration(Token * const startToken, + const std::map &variableId, + const unsigned int scopeStartVarId, + std::map > *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::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(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3a06a556c..ed2cb3fa6 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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(