From 1c399c86cab4cfdee698de8f7d57b5b3b2ce4785 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sat, 3 Nov 2012 21:16:05 +0100 Subject: [PATCH] Improved fix for #4311; Added back support for "this." (fixes again #4291) Added TODO unit test for missing varid. --- lib/checkother.cpp | 2 +- lib/tokenize.cpp | 2 +- test/testother.cpp | 10 +++++++ test/testtokenize.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 6ee7d282c..c06df0e01 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1033,7 +1033,7 @@ void CheckOther::checkSelfAssignment() const char selfAssignmentPattern[] = "%var% = %var% ;|=|)"; const Token *tok = Token::findmatch(_tokenizer->tokens(), selfAssignmentPattern); while (tok) { - if (Token::Match(tok->previous(), "[;{}]") && + if (Token::Match(tok->previous(), "[;{}.]") && tok->varId() && tok->varId() == tok->tokAt(2)->varId() && isTypeWithoutSideEffects(_tokenizer, symbolDatabase->getVariableFromVarId(tok->varId()))) { bool err = true; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 87f43e472..8c8616bf0 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2624,7 +2624,7 @@ static void setVarIdClassFunction(Token * const startToken, unsigned int *_varId) { for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) { - if (tok2->varId() == 0 && tok2->previous()->str() != ".") { + if (tok2->varId() == 0 && (tok2->previous()->str() != "." || tok2->strAt(-2) == "this")) { const std::map::const_iterator it = varlist.find(tok2->str()); if (it != varlist.end()) { tok2->varId(it->second); diff --git a/test/testother.cpp b/test/testother.cpp index 95d2fcbb4..0351450e4 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2791,6 +2791,16 @@ private: " i = i;\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant assignment of 'i' to itself.\n", errout.str()); + + // #4291 - id for variables accessed through 'this' + check("class Foo {\n" + " int var;\n" + " void func();\n" + "};\n" + "void Foo::func() {\n" + " this->var = var;\n" + "}"); + ASSERT_EQUALS("[test.cpp:6]: (warning) Redundant assignment of 'var' to itself.\n", errout.str()); } void trac1132() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3528e9ec7..4927a2494 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -250,6 +250,8 @@ private: TEST_CASE(varid_in_class6); // #3755 TEST_CASE(varid_in_class7); // set variable id for struct members TEST_CASE(varid_in_class8); // unknown macro in class + TEST_CASE(varid_in_class9); // #4291 - id for variables accessed through 'this' + TEST_CASE(varid_in_class10); TEST_CASE(varid_initList); TEST_CASE(varid_operator); TEST_CASE(varid_throw); @@ -3890,6 +3892,72 @@ private: tokenizeDebugListing(code)); } + void varid_in_class9() { // #4291 - id for variables accessed through 'this' + const char code1[] = "class A {\n" + " int var;\n" + "public:\n" + " void setVar();\n" + "};\n" + "void A::setVar() {\n" + " this->var = var;\n" + "}"; + ASSERT_EQUALS("\n\n##file 0\n" + "1: class A {\n" + "2: int var@1 ;\n" + "3: public:\n" + "4: void setVar ( ) ;\n" + "5: } ;\n" + "6: void A :: setVar ( ) {\n" + "7: this . var@1 = var@1 ;\n" + "8: }\n", + tokenizeDebugListing(code1)); + + const char code2[] = "class Foo : public FooBase {\n" + " void Clone(FooBase& g);\n" + " short m_bar;\n" + "};\n" + "void Foo::Clone(FooBase& g) {\n" + " g->m_bar = m_bar;\n" + "}"; + ASSERT_EQUALS("\n\n##file 0\n" + "1: class Foo : public FooBase {\n" + "2: void Clone ( FooBase & g@1 ) ;\n" + "3: short m_bar@2 ;\n" + "4: } ;\n" + "5: void Foo :: Clone ( FooBase & g@3 ) {\n" + "6: g@3 . m_bar@4 = m_bar@2 ;\n" + "7: }\n", + tokenizeDebugListing(code2)); // #4311 + } + + void varid_in_class10() { + const char code[] = "class Foo : public FooBase {\n" + " void Clone(FooBase& g);\n" + " short m_bar;\n" + "};\n" + "void Foo::Clone(FooBase& g) {\n" + " ((FooBase)g)->m_bar = m_bar;\n" + "}"; + TODO_ASSERT_EQUALS("\n\n##file 0\n" + "1: class Foo : public FooBase {\n" + "2: void Clone ( FooBase & g@1 ) ;\n" + "3: short m_bar@2 ;\n" + "4: } ;\n" + "5: void Foo :: Clone ( FooBase & g@3 ) {\n" + "6: ( ( FooBase ) g@3 ) . m_bar@4 = m_bar@2 ;\n" + "7: }\n", + "\n\n##file 0\n" + "1: class Foo : public FooBase {\n" + "2: void Clone ( FooBase & g@1 ) ;\n" + "3: short m_bar@2 ;\n" + "4: } ;\n" + "5: void Foo :: Clone ( FooBase & g@3 ) {\n" + "6: ( ( FooBase ) g@3 ) . m_bar = m_bar@2 ;\n" + "7: }\n", + tokenizeDebugListing(code)); + } + + void varid_initList() { const char code[] = "class A {\n" " A() : x(0) {}\n"