From a16d63181302cea9ca5cd7a4ba8c171332852c74 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Fri, 28 Mar 2014 17:43:40 +0100 Subject: [PATCH] Further improvements to setVarId and function/array pointer detection in SymbolDatabase (#2872) --- lib/symboldatabase.cpp | 4 ++-- lib/tokenize.cpp | 8 +++++++- test/testsymboldatabase.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 310f5f727..fb53c9019 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2408,7 +2408,7 @@ static const Token* skipScopeIdentifiers(const Token* tok) static const Token* skipPointers(const Token* tok) { - while (Token::Match(tok, "*|&|&&")) { + while (Token::Match(tok, "*|&|&&") || (tok && tok->str() == "(" && Token::Match(tok->link()->next(), "(|["))) { tok = tok->next(); } @@ -2446,7 +2446,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const if (Token::Match(localVarTok, "%var% ;|=")) { vartok = localVarTok; typetok = localTypeTok; - } else if (Token::Match(localVarTok, "%var% [") && localVarTok->str() != "operator") { + } else if (Token::Match(localVarTok, "%var% )|[") && localVarTok->str() != "operator") { vartok = localVarTok; typetok = localTypeTok; } else if ((isLocal() || type == Scope::eFunction) && diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5fb190f00..6fa9030e6 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2177,6 +2177,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::mapstr() == "struct" || tok2->str() == "union" || (cpp && (tok2->str() == "class" || tok2->str() == "typename"))) { hasstruct = true; typeCount = 0; + singleNameCount = 0; } else if (tok2->str() == "const") { ; // just skip "const" } else if (!hasstruct && variableId.find(tok2->str()) != variableId.end() && tok2->previous()->str() != "::") { @@ -2193,16 +2195,20 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map 0) || Token::simpleMatch(tok2, "< >") /* Ticket #4764 */) { tok2 = tok2->findClosingBracket(); if (!Token::Match(tok2, ">|>>")) break; + singleNameCount = 1; } else if (tok2->str() == "&" || tok2->str() == "&&") { ref = !bracket; - } else if (typeCount == 1 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "(|[")) { + } else if (singleNameCount == 1 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "(|[")) { bracket = true; // Skip: Seems to be valid pointer to array or function pointer + } else if (tok2->str() == "::") { + singleNameCount = 0; } else if (tok2->str() != "*" && tok2->str() != "::") { break; } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 2edfbc580..b20583831 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -135,6 +135,7 @@ private: TEST_CASE(hasInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasClassFunctionReturningFunctionPointer); + TEST_CASE(complexFunctionArrayPtr); TEST_CASE(hasSubClassConstructor); TEST_CASE(testConstructors); TEST_CASE(functionDeclarationTemplate); @@ -835,6 +836,35 @@ private: } } + void complexFunctionArrayPtr() { + GET_SYMBOL_DB("int(*p1)[10]; \n" // pointer to array 10 of int + "void(*p2)(char); \n" // pointer to function (char) returning void + "int(*(*p3)(char))[10];\n" // pointer to function (char) returning pointer to array 10 of int + "float(*(*p4)(char))(long); \n" // pointer to function (char) returning pointer to function (long) returning float + "short(*(*(p5) (char))(long))(double); \n" // pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short + "int(*a1[10])(void); \n" // array 10 of pointer to function (void) returning int + "float(*(*a2[10])(char))(long);\n" // array 10 of pointer to func (char) returning pointer to func (long) returning float + "short(*(*(*a3[10])(char))(long))(double);\n" // array 10 of pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short + "::boost::rational(&r_)[9];\n" // reference to array of ::boost::rational + "::boost::rational(&r_)[9];"); // reference to array of ::boost::rational (template!) + + ASSERT(db != nullptr); + + if (db) { + ASSERT_EQUALS(10, db->getVariableListSize() - 1); + ASSERT_EQUALS(true, db->getVariableFromVarId(1) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(2) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(3) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(4) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(5) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(6) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(7) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(8) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(9) != nullptr); + ASSERT_EQUALS(true, db->getVariableFromVarId(10) != nullptr); + ASSERT_EQUALS("", errout.str()); + } + } void hasSubClassConstructor() { GET_SYMBOL_DB("class Foo { class Sub; }; class Foo::Sub { Sub() {} };"); ASSERT(db != nullptr);