From 9c921ab657aed896048b6d106ca773315e1af689 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sat, 12 Apr 2014 11:43:10 +0200 Subject: [PATCH] Fixed handling of member function pointers in setVarId and SymbolDatabase (#4577) --- lib/symboldatabase.cpp | 2 ++ lib/tokenize.cpp | 2 +- test/testsymboldatabase.cpp | 16 ++++++++++++++++ test/testtokenize.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 983069467..74c1de092 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2563,6 +2563,8 @@ static const Token* skipPointers(const Token* tok) { while (Token::Match(tok, "*|&|&&") || (tok && tok->str() == "(" && Token::Match(tok->link()->next(), "(|["))) { tok = tok->next(); + if (tok->strAt(-1) == "(" && Token::Match(tok, "%type% ::")) + tok = tok->tokAt(2); } return tok; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 79536b267..e48b2783d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2563,7 +2563,7 @@ void Tokenizer::setVarId() if (tok2->link()) { if (tok2->str() == "{") tok2 = tok2->link(); - else if (tok2->str() == "(") + else if (tok2->str() == "(" && tok2->link()->strAt(1) != "(") tok2 = tok2->link(); } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index dda3b0d21..b7a8a7a29 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -136,6 +136,7 @@ private: TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasClassFunctionReturningFunctionPointer); TEST_CASE(complexFunctionArrayPtr); + TEST_CASE(pointerToMemberFunction); TEST_CASE(hasSubClassConstructor); TEST_CASE(testConstructors); TEST_CASE(functionDeclarationTemplate); @@ -873,6 +874,21 @@ private: ASSERT_EQUALS("", errout.str()); } } + + void pointerToMemberFunction() { + GET_SYMBOL_DB("bool (A::*pFun)();"); // Pointer to member function of A, returning bool and taking no parameters + + ASSERT(db != nullptr); + + if (db) { + ASSERT_EQUALS(1, db->getVariableListSize() - 1); + ASSERT_EQUALS(true, db->getVariableFromVarId(1) != nullptr); + if (db->getVariableFromVarId(1)) + ASSERT_EQUALS("pFun", db->getVariableFromVarId(1)->name()); + ASSERT_EQUALS("", errout.str()); + } + } + void hasSubClassConstructor() { GET_SYMBOL_DB("class Foo { class Sub; }; class Foo::Sub { Sub() {} };"); ASSERT(db != nullptr); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d3a105b55..d36a4fce7 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -324,6 +324,7 @@ private: TEST_CASE(varidclass13); TEST_CASE(varidclass14); TEST_CASE(varidclass15); // initializer list + TEST_CASE(varidclass16); // #4577 TEST_CASE(varid_classnameshaddowsvariablename) // #3990 TEST_CASE(file1); @@ -5163,6 +5164,31 @@ private: ASSERT_EQUALS(expected, tokenizeDebugListing(code)); } + void varidclass16() { + const char code[] = "struct A;\n" + "typedef bool (A::* FuncPtr)();\n" + "struct A {\n" + " FuncPtr pFun;\n" + " void setPFun(int mode);\n" + " bool funcNorm();\n" + "};\n" + "void A::setPFun(int mode) {\n" + " pFun = &A::funcNorm;\n" + "}"; + const char expected[] = "\n\n##file 0\n" + "1: struct A ;\n" + "2:\n" + "3: struct A {\n" + "4: bool ( A :: * pFun@1 ) ( ) ;\n" + "5: void setPFun ( int mode@2 ) ;\n" + "6: bool funcNorm ( ) ;\n" + "7: } ;\n" + "8: void A :: setPFun ( int mode@3 ) {\n" + "9: pFun@1 = & A :: funcNorm ;\n" + "10: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + void varid_classnameshaddowsvariablename() { const char code[] = "class Data;\n" "void strange_declarated(const Data& Data);\n"