Handle/simplify function pointer typedefs

This commit is contained in:
Robert Reif 2010-01-20 21:16:40 +01:00 committed by Daniel Marjamäki
parent 863a42797f
commit e163f878ab
2 changed files with 161 additions and 4 deletions

View File

@ -453,6 +453,7 @@ void Tokenizer::simplifyTypedef()
Token *num = 0; Token *num = 0;
Token *typeDef = tok; Token *typeDef = tok;
int offset = 1; int offset = 1;
bool functionPtr = false;
if (Token::Match(tok->next(), "%type% <") || if (Token::Match(tok->next(), "%type% <") ||
Token::Match(tok->next(), "%type% %type% <") || Token::Match(tok->next(), "%type% %type% <") ||
@ -504,11 +505,15 @@ void Tokenizer::simplifyTypedef()
{ {
type1 = tok->strAt(offset++); type1 = tok->strAt(offset++);
if (tok->tokAt(offset) && !Token::Match(tok->tokAt(offset), "*|&") && tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,")) if (tok->tokAt(offset) && Token::Match(tok->tokAt(offset), "%type%") &&
tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,"))
{
type2 = tok->strAt(offset++); type2 = tok->strAt(offset++);
if (tok->tokAt(offset) && !Token::Match(tok->tokAt(offset), "*|&") && tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,")) if (tok->tokAt(offset) && Token::Match(tok->tokAt(offset), "%type%") &&
type3 = tok->strAt(offset++); tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,"))
type3 = tok->strAt(offset++);
}
} }
else else
{ {
@ -537,6 +542,19 @@ void Tokenizer::simplifyTypedef()
continue; continue;
} }
} }
else if (tok->tokAt(offset) && Token::Match(tok->tokAt(offset), "( * %type% ) ("))
{
if (tok->tokAt(offset + 4)->link()->next())
{
functionPtr = true;
typeName = tok->strAt(offset + 2);
start = tok->tokAt(offset + 4);
end = tok->tokAt(offset + 4)->link();
tok = end->next();
}
else
continue;
}
else else
{ {
// unhandled typedef, skip it and continue // unhandled typedef, skip it and continue
@ -602,7 +620,7 @@ void Tokenizer::simplifyTypedef()
if (simplifyType) if (simplifyType)
{ {
if (start && end) if (start && end && !functionPtr)
{ {
tok2->str(start->str()); tok2->str(start->str());
Token * nextToken; Token * nextToken;
@ -626,6 +644,10 @@ void Tokenizer::simplifyTypedef()
} }
} }
} }
else if (functionPtr)
{
tok2->str(type1);
}
else else
{ {
tok2->str(type1); tok2->str(type1);
@ -647,6 +669,51 @@ void Tokenizer::simplifyTypedef()
pointers.pop_front(); pointers.pop_front();
tok2 = tok2->next(); tok2 = tok2->next();
} }
if (functionPtr)
{
tok2->insertToken("(");
tok2 = tok2->next();
Token *tok3 = tok2;
tok2->insertToken("*");
tok2 = tok2->next();
tok2 = tok2->next();
// skip over typedef parameter
while (!Token::Match(tok2->next(), "=|{|;"))
tok2 = tok2->next();
tok2->insertToken(")");
tok2 = tok2->next();
Token::createMutualLinks(tok2, tok3);
tok2->insertToken("(");
tok2 = tok2->next();
tok3 = tok2;
Token * nextToken;
std::stack<Token *> links;
for (nextToken = start->next(); nextToken != end; nextToken = nextToken->next())
{
tok2->insertToken(nextToken->strAt(0));
tok2 = tok2->next();
// Check for links and fix them up
if (tok2->str() == "(" || tok2->str() == "[")
links.push(tok2);
if (tok2->str() == ")" || tok2->str() == "]")
{
Token * link = links.top();
tok2->link(link);
link->link(tok2);
links.pop();
}
}
tok2->insertToken(")");
tok2 = tok2->next();
Token::createMutualLinks(tok2, tok3);
}
if (num) if (num)
{ {
tok2 = tok2->next(); tok2 = tok2->next();

View File

@ -154,6 +154,9 @@ private:
TEST_CASE(simplifyTypedef17); TEST_CASE(simplifyTypedef17);
TEST_CASE(simplifyTypedef18); // typedef vector<int[4]> a; TEST_CASE(simplifyTypedef18); // typedef vector<int[4]> a;
TEST_CASE(simplifyTypedef19); TEST_CASE(simplifyTypedef19);
TEST_CASE(simplifyTypedef20);
TEST_CASE(simplifyTypedef21);
TEST_CASE(simplifyTypedef22);
TEST_CASE(reverseArraySyntax) TEST_CASE(reverseArraySyntax)
TEST_CASE(simplify_numeric_condition) TEST_CASE(simplify_numeric_condition)
@ -2619,6 +2622,93 @@ private:
} }
} }
void simplifyTypedef20()
{
// ticket #1284
const char code[] = "typedef jobject invoke_t (jobject, Proxy *, Method *, JArray< jobject > *);";
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// Clear the error buffer..
errout.str("");
tokenizer.simplifyTokenList();
ASSERT_EQUALS(true, tokenizer.validate());
}
void simplifyTypedef21()
{
const char code[] = "typedef void (* PF)();\n"
"typedef void * (* PFV)(void *);\n"
"PF pf;\n"
"PFV pfv;";
const char expected[] =
"; "
"; "
"void ( * pf ) ( ) ; "
"void * ( * pfv ) ( void * ) ;";
ASSERT_EQUALS(expected, tok(code, false));
}
void simplifyTypedef22()
{
{
const char code[] = "class Fred {\n"
" typedef void (*testfp)();\n"
" testfp get() { return test; }\n"
" static void test() { }\n"
"};";
const char expected[] =
"class Fred { "
"; "
"void ( * get ( ) ) ( ) { return test ; } "
"static void test ( ) { } "
"} ;";
ASSERT_EQUALS(expected, tok(code, false));
}
{
const char code[] = "class Fred {\n"
" typedef void * (*testfp)(void *);\n"
" testfp get() { return test; }\n"
" static void * test(void * p) { return p; }\n"
"};\n";
const char expected[] =
"class Fred { "
"; "
"void * ( * get ( ) ) ( void * ) { return test ; } "
"static void * test ( void * p ) { return p ; } "
"} ;";
ASSERT_EQUALS(expected, tok(code, false));
}
{
const char code[] = "class Fred {\n"
" typedef void * (*testfp)(void *);\n"
" testfp get(int i) { return test; }\n"
" static void * test(void * p) { return p; }\n"
"};\n";
const char expected[] =
"class Fred { "
"; "
"void * ( * get ( int i ) ) ( void * ) { return test ; } "
"static void * test ( void * p ) { return p ; } "
"} ;";
ASSERT_EQUALS(expected, tok(code, false));
}
}
void reverseArraySyntax() void reverseArraySyntax()
{ {
ASSERT_EQUALS("a [ 13 ]", tok("13[a]")); ASSERT_EQUALS("a [ 13 ]", tok("13[a]"));