diff --git a/src/tokenize.cpp b/src/tokenize.cpp index a91b3d7ae..e55beae9d 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -730,6 +730,66 @@ void Tokenizer::setVarId() } } } + + // class members.. + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "class %var% {")) + { + const std::string &classname(tok->next()->str()); + + unsigned int indentlevel = 0; + + // What member variables are there in this class? + for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) + { + // Indentation.. + if (tok2->str() == "{") + ++indentlevel; + else if (tok2->str() == "}") + { + if (indentlevel == 0) + break; + --indentlevel; + } + + // If a variable id is found in the class declaration, start + // updating the variable ids in member functions.. + else if (indentlevel == 1 && tok2->varId() > 0) + { + const unsigned int varid(tok2->varId()); + const std::string &varname(tok2->str()); + + for (Token *tok3 = tok; tok3; tok3 = tok3->next()) + { + // Found a class function.. + if (Token::Match(tok3, (classname + " :: %var% (").c_str())) + { + unsigned int indentlevel2 = 0; + while (tok3) + { + if (tok3->str() == "{") + ++indentlevel2; + else if (tok3->str() == "}") + { + if (indentlevel2 <= 1) + break; + --indentlevel2; + } + else if (indentlevel2 == 0 && tok3->str() == ";") + break; + else if (indentlevel2 > 0 && tok3->varId() == 0 && tok3->str() == varname) + tok3->varId(varid); + tok3 = tok3->next(); + } + if (!tok3) + break; + } + } + } + } + } + } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f710879af..fc229bd8b 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -110,6 +110,7 @@ private: TEST_CASE(varid9); TEST_CASE(varidStl); TEST_CASE(varid_delete); + TEST_CASE(varid_class); TEST_CASE(file1); TEST_CASE(file2); @@ -1142,6 +1143,55 @@ private: } + void varid_class() + { + const std::string code("class Fred\n" + "{\n" + "private:\n" + " int i;\n" + "\n" + " void foo1();\n" + " void foo2()\n" + " {\n" + " ++i;\n" + " }\n" + "}\n" + "\n" + "Fred::foo1()\n" + "{\n" + " i = 0;\n" + "}\n"); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.setVarId(); + + // result.. + const std::string actual(tokenizer.tokens()->stringifyList(true)); + const std::string expected("\n\n##file 0\n" + "1: class Fred\n" + "2: {\n" + "3: private:\n" + "4: int i@1 ;\n" + "5:\n" + "6: void foo1@2 ( ) ;\n" + "7: void foo2 ( )\n" + "8: {\n" + "9: ++ i@1 ;\n" + "10: }\n" + "11: }\n" + "12:\n" + "13: Fred :: foo1 ( )\n" + "14: {\n" + "15: i@1 = 0 ;\n" + "16: }\n"); + + ASSERT_EQUALS(expected, actual); + } + + void file1() {