diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d8af0a240..9c16c70d1 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3474,6 +3474,13 @@ void Tokenizer::setVarId() varname = tok2->str(); else if (tok2->str() != "*" && tok2->str() != "&") break; + + // a type can't have varid + if (tok2->previous()->varId() > 0) { + tok2 = 0; + break; + } + tok2 = tok2->next(); } @@ -3498,6 +3505,7 @@ void Tokenizer::setVarId() Token::Match(tok2->next(), "%bool%") || tok2->next()->str()[0] == '"' || tok2->next()->str()[0] == '\'' || + tok2->next()->str() == "*" || tok2->next()->varId() != 0) { // This is not a function } else { @@ -3557,7 +3565,7 @@ void Tokenizer::setVarId() while (NULL != (tok2 = tok2->next())) { const char c = tok2->str()[0]; if (c == varname[0]) { - if (tok2->str() == varname) { + if (tok2->str() == varname && (className.empty() || tok2->varId() == 0)) { const std::string &prev = tok2->previous()->str(); /** @todo better handling when classes in different scopes have the same name */ diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a9a5b93e0..91ea1314a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -184,6 +184,7 @@ private: TEST_CASE(varid34); // ticket #2825 TEST_CASE(varid35); // ticket #2937 TEST_CASE(varid36); // ticket #2980 (segmentation fault) + TEST_CASE(varid37); // ticket #3092 (varid for 'Bar bar(*this);') TEST_CASE(varidFunctionCall1); TEST_CASE(varidFunctionCall2); TEST_CASE(varidFunctionCall3); @@ -193,6 +194,7 @@ private: TEST_CASE(varid_reference_to_containers); TEST_CASE(varid_in_class1); TEST_CASE(varid_in_class2); + TEST_CASE(varid_in_class3); // #3092 - shadow variable in member function TEST_CASE(varid_operator); TEST_CASE(varid_throw); TEST_CASE(varid_unknown_macro); // #2638 - unknown macro is not type @@ -2854,13 +2856,9 @@ private: "}\n"); const std::string expected2("\n\n##file 0\n" "1: void f ( int b@1 , int c@2 ) {\n" - "2: x ( a@3 * b@1 * c@2 , 10 ) ;\n" + "2: x ( a * b@1 * c@2 , 10 ) ;\n" "3: }\n"); - const std::string actual2("\n\n##file 0\n" - "1: void f ( int b@1 , int c@2 ) {\n" - "2: x ( a * b@1 * c@3 , 10 ) ;\n" - "3: }\n"); - TODO_ASSERT_EQUALS(expected2, actual2, tokenizeDebugListing(code2)); + ASSERT_EQUALS(expected2, tokenizeDebugListing(code2)); const std::string code3("class Nullpointer : public ExecutionPath\n" " {\n" @@ -2939,6 +2937,16 @@ private: ASSERT_EQUALS("", errout.str()); } + void varid37() { + const std::string code = "void blah() {" + " Bar bar(*x);" + "}"; + ASSERT_EQUALS("\n\n##file 0\n1: " + "void blah ( ) { Bar bar@1 ( * x ) ; }\n", + tokenizeDebugListing(code)); + } + + void varidFunctionCall1() { const std::string code("void f() {\n" " int x;\n" @@ -3200,6 +3208,23 @@ private: ASSERT_EQUALS(expected, actual); } + void varid_in_class3() { + const std::string code = "class Foo {\n" + " void blah() {\n" + " Bar x(*this);\n" // <- .. + " }\n" + " int x;\n" // <- .. don't assign same varid + "};"; + ASSERT_EQUALS("\n\n##file 0\n" + "1: class Foo {\n" + "2: void blah ( ) {\n" + "3: Bar x@1 ( * this ) ;\n" + "4: }\n" + "5: int x@2 ;\n" + "6: } ;\n", tokenizeDebugListing(code)); + } + + void varid_operator() { { const std::string actual = tokenizeDebugListing(