From e163f878ab332c68f872ba4862e57c8a706b31a4 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 20 Jan 2010 21:16:40 +0100 Subject: [PATCH] Handle/simplify function pointer typedefs --- lib/tokenize.cpp | 75 +++++++++++++++++++++++++++++-- test/testsimplifytokens.cpp | 90 +++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 4 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5ca2c6e0c..b26ca62be 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -453,6 +453,7 @@ void Tokenizer::simplifyTypedef() Token *num = 0; Token *typeDef = tok; int offset = 1; + bool functionPtr = false; if (Token::Match(tok->next(), "%type% <") || Token::Match(tok->next(), "%type% %type% <") || @@ -504,11 +505,15 @@ void Tokenizer::simplifyTypedef() { 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++); - if (tok->tokAt(offset) && !Token::Match(tok->tokAt(offset), "*|&") && tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,")) - type3 = tok->strAt(offset++); + if (tok->tokAt(offset) && Token::Match(tok->tokAt(offset), "%type%") && + tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,")) + type3 = tok->strAt(offset++); + } } else { @@ -537,6 +542,19 @@ void Tokenizer::simplifyTypedef() 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 { // unhandled typedef, skip it and continue @@ -602,7 +620,7 @@ void Tokenizer::simplifyTypedef() if (simplifyType) { - if (start && end) + if (start && end && !functionPtr) { tok2->str(start->str()); Token * nextToken; @@ -626,6 +644,10 @@ void Tokenizer::simplifyTypedef() } } } + else if (functionPtr) + { + tok2->str(type1); + } else { tok2->str(type1); @@ -647,6 +669,51 @@ void Tokenizer::simplifyTypedef() pointers.pop_front(); 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 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) { tok2 = tok2->next(); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e0b08ec0f..82d76d075 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -154,6 +154,9 @@ private: TEST_CASE(simplifyTypedef17); TEST_CASE(simplifyTypedef18); // typedef vector a; TEST_CASE(simplifyTypedef19); + TEST_CASE(simplifyTypedef20); + TEST_CASE(simplifyTypedef21); + TEST_CASE(simplifyTypedef22); TEST_CASE(reverseArraySyntax) 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() { ASSERT_EQUALS("a [ 13 ]", tok("13[a]"));