diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6214518ac..df433483e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -397,7 +397,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) { // check for an end of definition const Token * tok = *tokPtr; - if (tok && tok->next() && Token::Match(tok->next(), ";|,|[|=|)|>")) + if (tok && tok->next() && Token::Match(tok->next(), ";|,|[|=|)|>|(")) { const Token * end = tok->next(); @@ -423,6 +423,39 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) end = end->next(); } + end = end->next(); + } + else if (end->str() == "(") + { + if (tok->previous()->str() == "operator") + { + // conversion operator + return false; + } + else if (tok->previous()->str() == "typedef") + { + // typedef of function returning this type + return false; + } + else if (Token::Match(tok->previous(), "public:|private:|protected:")) + { + return false; + } + else if (tok->previous()->str() == ">") + { + duplicateTypedefError(*tokPtr, name, "Template instantiation"); + *tokPtr = end->link(); + return true; + } + else if (Token::Match(tok->previous(), "%type%")) + { + if (end->link()->next()->str() == "{") + { + duplicateTypedefError(*tokPtr, name, "Function"); + *tokPtr = end->link()->next()->link(); + return true; + } + } } if (end) @@ -461,7 +494,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) // look backwards if (Token::Match(tok->previous(), "typedef|}|>") || (Token::Match(tok->previous(), "%type%") && - !Token::Match(tok->previous(), "return|new|const"))) + !Token::Match(tok->previous(), "return|new|const|friend"))) { // scan backwards for the end of the previous statement int level = (tok->previous()->str() == "}") ? 1 : 0; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 7a73b593b..3117b5cc5 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -176,6 +176,8 @@ private: TEST_CASE(simplifyTypedef37); // ticket #1449 TEST_CASE(simplifyTypedef38); TEST_CASE(simplifyTypedef39); + TEST_CASE(simplifyTypedef40); + TEST_CASE(reverseArraySyntax) TEST_CASE(simplify_numeric_condition) @@ -3420,6 +3422,62 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyTypedef40() + { + const char code[] = "typedef int A;\n" + "typedef int B;\n" + "template class C { };"; + const char expected[] = "; ; ; ;"; + ASSERT_EQUALS(expected, tok(code, false)); + + checkSimplifyTypedef(code); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (style) Template parameter 'A' hides typedef with same name\n" + "[test.cpp:3] -> [test.cpp:2]: (style) Template parameter 'B' hides typedef with same name\n", errout.str()); + + checkSimplifyTypedef("typedef tuple t2;\n" + "void ordering_test()\n" + "{\n" + " tuple t2(5, 3.3f);\n" + " BOOST_CHECK(t3 > t2);\n" + "}"); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (style) Template instantiation 't2' hides typedef with same name\n", errout.str()); + + checkSimplifyTypedef("class MyOverflowingUnsigned\n" + "{\n" + "public:\n" + " typedef unsigned self_type::* bool_type;\n" + " operator bool_type() const { return this->v_ ? &self_type::v_ : 0; }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkSimplifyTypedef("typedef int (*fptr_type)(int, int);\n" + "struct which_one {\n" + " typedef fptr_type (*result_type)(bool x);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkSimplifyTypedef("class my_configuration\n" + "{\n" + "public:\n" + " template < typename T >\n" + " class hook\n" + " {\n" + " public:\n" + " typedef ::boost::rational rational_type;\n" + " public:\n" + " rational_type ( &r_ )[ 9 ];\n" + " };\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkSimplifyTypedef("class A\n" + "{\n" + " typedef B b;\n" + " friend b;\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } + void reverseArraySyntax() { ASSERT_EQUALS("a [ 13 ]", tok("13[a]"));