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
{
// look backwards
if (Token::Match(tok->previous(), "typedef|}|>|struct") ||
if (Token::Match(tok->previous(), "typedef|}|>") ||
(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"))))
{
// scan backwards for the end of the previous statement
@ -577,6 +577,34 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name)
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() == "{")
level--;
@ -639,10 +667,10 @@ void Tokenizer::simplifyTypedef()
else if (tok->str() != "typedef")
continue;
// pull struct, union or enum definition out of typedef
// use typedef name for unnamed struct, union or enum
if (Token::Match(tok->next(), "struct|enum|union %type% {") ||
Token::Match(tok->next(), "struct|enum|union {"))
// pull struct, union, enum or class definition out of typedef
// use typedef name for unnamed struct, union, enum or class
if (Token::Match(tok->next(), "struct|enum|union|class %type% {") ||
Token::Match(tok->next(), "struct|enum|union|class {"))
{
Token *tok1;
std::string name;
@ -935,6 +963,9 @@ void Tokenizer::simplifyTypedef()
if (simplifyType)
{
bool isDerived = false;
isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,");
bool inCast = false;
if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")") ||
@ -942,6 +973,10 @@ void Tokenizer::simplifyTypedef()
Token::Match(tok2->next(), "> (")))
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());
Token * nextToken;
std::stack<Token *> links;

View File

@ -182,6 +182,7 @@ private:
TEST_CASE(simplifyTypedef41); // ticket #1488
TEST_CASE(simplifyTypedef42); // ticket #1506
TEST_CASE(simplifyTypedef43); // ticket #1588
TEST_CASE(simplifyTypedef44);
TEST_CASE(reverseArraySyntax)
TEST_CASE(simplify_numeric_condition)
@ -3714,27 +3715,163 @@ private:
checkSimplifyTypedef("typedef struct A { } A;\n"
"struct A;");
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()
{
// ticket #1588
const char code[] = "typedef struct foo A;\n"
"struct A\n"
"{\n"
" int alloclen;\n"
"};\n";
{
const char code[] = "typedef struct foo A;\n"
"struct A\n"
"{\n"
" int alloclen;\n"
"};\n";
// The expected result..
const std::string expected("; "
"struct A "
"{ "
"int alloclen ; "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
// The expected result..
const std::string expected("; "
"struct A "
"{ "
"int alloclen ; "
"} ;");
ASSERT_EQUALS(expected, sizeof_(code));
checkSimplifyTypedef(code);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Struct 'A' hides typedef with same name\n", errout.str());
checkSimplifyTypedef(code);
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()