From d7ef89bbe6fa9c8e8cd21f0ad53f4cbfa704644e Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 23 Feb 2015 06:49:50 +0100 Subject: [PATCH] Fixed #6538 (Symboldatabase: improve isFunction) --- lib/symboldatabase.cpp | 47 +++++++++++++++++++++++++++++++++++++ test/testgarbage.cpp | 10 ++++---- test/testother.cpp | 2 +- test/testsymboldatabase.cpp | 17 ++++++++++++++ test/testunusedprivfunc.cpp | 2 +- 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 027749875..26d0e0613 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1288,6 +1288,53 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const (tok->previous()->isName() || tok->strAt(-1) == ">" || tok->strAt(-1) == "&" || tok->strAt(-1) == "*" || // Either a return type in front of tok tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok outerScope->isClassOrStruct())) { // or a ctor/dtor + + const Token* tok1 = tok->previous(); + + // skip over destructor "~" + if (tok1->str() == "~") + tok1 = tok1->previous(); + + // skip over qualification + while (Token::simpleMatch(tok1, "::")) { + if (Token::Match(tok1->tokAt(-1), "%name%")) + tok1 = tok1->tokAt(-2); + else + tok1 = tok1->tokAt(-1); + } + + // skip over pointers and references + while (Token::Match(tok1, "[*&]")) + tok1 = tok1->tokAt(-1); + + // skip over template + if (tok1 && tok1->str() == ">") + tok1 = tok1->link()->previous(); + + // function can't have number or variable as return type + if (tok1 && (tok1->isNumber() || tok1->varId())) + return false; + + // skip over return type + if (Token::Match(tok1, "%name%")) + tok1 = tok1->previous(); + + // skip over qualification + while (Token::simpleMatch(tok1, "::")) { + if (Token::Match(tok1->tokAt(-1), "%name%")) + tok1 = tok1->tokAt(-2); + else + tok1 = tok1->tokAt(-1); + } + + // skip over modifiers and other stuff + while (Token::Match(tok1, "const|static|extern|template|virtual|struct|class")) + tok1 = tok1->previous(); + + // should be at a sequence point if this is a function + if (!Token::Match(tok1, ">|{|}|;|public:|protected:|private:") && tok1) + return false; + const Token* tok2 = tok->next()->link()->next(); if (tok2 && (Token::Match(tok2, "const| ;|{|=") || diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 30a7368e4..2ce2688c3 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -420,11 +420,11 @@ private: ASSERT_THROW(checkCode("class Foo {}; class Bar : public Foo"), InternalError); - ASSERT_THROW(checkCode("YY_DECL { switch (yy_act) {\n" - " case 65: YY_BREAK\n" - " case YY_STATE_EOF(block):\n" - " yyterminate(); \n" - "} }"), InternalError); // #5663 + checkCode("YY_DECL { switch (yy_act) {\n" + " case 65: YY_BREAK\n" + " case YY_STATE_EOF(block):\n" + " yyterminate(); \n" + "} }"); // #5663 } void garbageAST() { diff --git a/test/testother.cpp b/test/testother.cpp index 109d77a32..9349d8629 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3020,7 +3020,7 @@ private: ASSERT_EQUALS("[test.cpp:4]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout.str()); // #5707 - check("extern int i,j\n" + check("extern int i,j;\n" "int foo() {\n" " switch(i) {\n" " default: j=1; break;\n" diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index a5b798eb5..9954710da 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -228,6 +228,7 @@ private: TEST_CASE(symboldatabase48); // #6417 TEST_CASE(symboldatabase49); // #6424 TEST_CASE(symboldatabase50); // #6432 + TEST_CASE(symboldatabase51); // #6538 TEST_CASE(isImplicitlyVirtual); @@ -2128,6 +2129,22 @@ private: ASSERT_EQUALS(true, db && f && f->function() && f->function()->isConstructor()); } + void symboldatabase51() { // #6538 + GET_SYMBOL_DB("static const float f1 = 2 * foo1(a, b);\n" + "static const float f2 = 2 * ::foo2(a, b);\n" + "static const float f3 = 2 * std::foo3(a, b);\n" + "static const float f4 = c * foo4(a, b);\n" + "static const int i1 = 2 & foo5(a, b);\n"); + ASSERT(db != nullptr); + if (db) { + ASSERT(findFunctionByName("foo1", &db->scopeList.front()) == nullptr); + ASSERT(findFunctionByName("foo2", &db->scopeList.front()) == nullptr); + ASSERT(findFunctionByName("foo3", &db->scopeList.front()) == nullptr); + ASSERT(findFunctionByName("foo4", &db->scopeList.front()) == nullptr); + ASSERT(findFunctionByName("foo5", &db->scopeList.front()) == nullptr); + } + } + void isImplicitlyVirtual() { { GET_SYMBOL_DB("class Base {\n" diff --git a/test/testunusedprivfunc.cpp b/test/testunusedprivfunc.cpp index 38ebeb664..b683627de 100644 --- a/test/testunusedprivfunc.cpp +++ b/test/testunusedprivfunc.cpp @@ -418,7 +418,7 @@ private: "class A\n" "{\n" "public:\n" - " A()\n" + " A();\n" " void a();\n" "private:\n" " void b();\n"