Fixed #1588 (typedef struct incorrectly simplified)

This commit is contained in:
Robert Reif 2010-04-14 19:06:51 +02:00 committed by Daniel Marjamäki
parent 3bbb2e1d7f
commit d2bb4964d0
2 changed files with 192 additions and 20 deletions

View File

@ -544,9 +544,9 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name)
else else
{ {
// look backwards // look backwards
if (Token::Match(tok->previous(), "typedef|}|>|struct") || if (Token::Match(tok->previous(), "typedef|}|>") ||
(Token::Match(tok->previous(), "%type%") && (Token::Match(tok->previous(), "%type%") &&
(!Token::Match(tok->previous(), "return|new|const|friend|struct") && (!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected") &&
!Token::Match(tok->tokAt(-2), "friend class")))) !Token::Match(tok->tokAt(-2), "friend class"))))
{ {
// scan backwards for the end of the previous statement // scan backwards for the end of the previous statement
@ -577,6 +577,34 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name)
return false; return false;
} }
} }
else if (tok->previous()->str() == "union")
{
if (tok->next()->str() != ";")
{
duplicateTypedefError(*tokPtr, name, "Union");
return true;
}
else
{
// forward declaration after declaration
duplicateDeclarationError(*tokPtr, name, "Union");
return false;
}
}
else if (tok->previous()->str() == "class")
{
if (tok->next()->str() != ";")
{
duplicateTypedefError(*tokPtr, name, "Class");
return true;
}
else
{
// forward declaration after declaration
duplicateDeclarationError(*tokPtr, name, "Class");
return false;
}
}
else if (tok->previous()->str() == "{") else if (tok->previous()->str() == "{")
level--; level--;
@ -639,10 +667,10 @@ void Tokenizer::simplifyTypedef()
else if (tok->str() != "typedef") else if (tok->str() != "typedef")
continue; continue;
// pull struct, union or enum definition out of typedef // pull struct, union, enum or class definition out of typedef
// use typedef name for unnamed struct, union or enum // use typedef name for unnamed struct, union, enum or class
if (Token::Match(tok->next(), "struct|enum|union %type% {") || if (Token::Match(tok->next(), "struct|enum|union|class %type% {") ||
Token::Match(tok->next(), "struct|enum|union {")) Token::Match(tok->next(), "struct|enum|union|class {"))
{ {
Token *tok1; Token *tok1;
std::string name; std::string name;
@ -935,6 +963,9 @@ void Tokenizer::simplifyTypedef()
if (simplifyType) if (simplifyType)
{ {
bool isDerived = false;
isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,");
bool inCast = false; bool inCast = false;
if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")") || if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")") ||
@ -942,6 +973,10 @@ void Tokenizer::simplifyTypedef()
Token::Match(tok2->next(), "> ("))) Token::Match(tok2->next(), "> (")))
inCast = true; inCast = true;
// skip over class or struct in derived class declaration
if (isDerived && Token::Match(typeStart, "class|struct"))
typeStart = typeStart->next();
tok2->str(typeStart->str()); tok2->str(typeStart->str());
Token * nextToken; Token * nextToken;
std::stack<Token *> links; std::stack<Token *> links;

View File

@ -182,6 +182,7 @@ private:
TEST_CASE(simplifyTypedef41); // ticket #1488 TEST_CASE(simplifyTypedef41); // ticket #1488
TEST_CASE(simplifyTypedef42); // ticket #1506 TEST_CASE(simplifyTypedef42); // ticket #1506
TEST_CASE(simplifyTypedef43); // ticket #1588 TEST_CASE(simplifyTypedef43); // ticket #1588
TEST_CASE(simplifyTypedef44);
TEST_CASE(reverseArraySyntax) TEST_CASE(reverseArraySyntax)
TEST_CASE(simplify_numeric_condition) TEST_CASE(simplify_numeric_condition)
@ -3714,27 +3715,163 @@ private:
checkSimplifyTypedef("typedef struct A { } A;\n" checkSimplifyTypedef("typedef struct A { } A;\n"
"struct A;"); "struct A;");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Struct 'A' forward declaration unnecessary, already declared\n", errout.str()); ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Struct 'A' forward declaration unnecessary, already declared\n", errout.str());
checkSimplifyTypedef("typedef union A { int i; float f; } A;\n"
"union A;");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Union 'A' forward declaration unnecessary, already declared\n", errout.str());
checkSimplifyTypedef("typedef std::map<std::string, int> A;\n"
"class A;");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Class 'A' forward declaration unnecessary, already declared\n", errout.str());
} }
void simplifyTypedef43() void simplifyTypedef43()
{ {
// ticket #1588 // ticket #1588
const char code[] = "typedef struct foo A;\n" {
"struct A\n" const char code[] = "typedef struct foo A;\n"
"{\n" "struct A\n"
" int alloclen;\n" "{\n"
"};\n"; " int alloclen;\n"
"};\n";
// The expected result.. // The expected result..
const std::string expected("; " const std::string expected("; "
"struct A " "struct A "
"{ " "{ "
"int alloclen ; " "int alloclen ; "
"} ;"); "} ;");
ASSERT_EQUALS(expected, sizeof_(code)); ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code); checkSimplifyTypedef(code);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Struct 'A' hides typedef with same name\n", errout.str()); ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Struct 'A' hides typedef with same name\n", errout.str());
}
{
const char code[] = "typedef union foo A;\n"
"union A\n"
"{\n"
" int alloclen;\n"
"};\n";
// The expected result..
const std::string expected("; "
"union A "
"{ "
"int alloclen ; "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Union 'A' hides typedef with same name\n", errout.str());
}
{
const char code[] = "typedef class foo A;\n"
"class A\n"
"{\n"
" int alloclen;\n"
"};\n";
// The expected result..
const std::string expected("; "
"class A "
"{ "
"int alloclen ; "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Class 'A' hides typedef with same name\n", errout.str());
}
}
void simplifyTypedef44()
{
{
const char code[] = "typedef std::map<std::string, int> Map;\n"
"class MyMap : public Map\n"
"{\n"
"};\n";
// The expected result..
const std::string expected("; "
"class MyMap : public std :: map < std :: string , int > "
"{ "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
{
const char code[] = "typedef std::map<std::string, int> Map;\n"
"class MyMap : protected Map\n"
"{\n"
"};\n";
// The expected result..
const std::string expected("; "
"class MyMap : protected std :: map < std :: string , int > "
"{ "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
{
const char code[] = "typedef std::map<std::string, int> Map;\n"
"class MyMap : private Map\n"
"{\n"
"};\n";
// The expected result..
const std::string expected("; "
"class MyMap : private std :: map < std :: string , int > "
"{ "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
{
const char code[] = "typedef struct foo { } A;\n"
"struct MyA : public A\n"
"{\n"
"};\n";
// The expected result..
const std::string expected("struct foo { } ; ; "
"struct MyA : public foo "
"{ "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
{
const char code[] = "typedef class foo { } A;\n"
"class MyA : public A\n"
"{\n"
"};\n";
// The expected result..
const std::string expected("class foo { } ; ; "
"class MyA : public foo "
"{ "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
} }
void reverseArraySyntax() void reverseArraySyntax()