diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 055adc2b8..a47740974 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1303,45 +1303,48 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const tok1 = tok1->tokAt(-1); } - // skip over pointers and references - while (Token::Match(tok1, "[*&]")) - tok1 = tok1->tokAt(-1); - - // skip over template - if (tok1 && tok1->str() == ">") { - if (tok1->link()) - tok1 = tok1->link()->previous(); - else - return false; - } - - // 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%")) { - if (tok1->str() == "return") - return false; - tok1 = tok1->previous(); - } - - // skip over qualification - while (Token::simpleMatch(tok1, "::")) { - if (Token::Match(tok1->tokAt(-1), "%name%")) - tok1 = tok1->tokAt(-2); - else + // done if constructor or destructor + if (!Token::Match(tok1, "{|}|;|public:|protected:|private:") && tok1) { + // skip over pointers and references + while (Token::Match(tok1, "[*&]")) tok1 = tok1->tokAt(-1); + + // skip over template + if (tok1 && tok1->str() == ">") { + if (tok1->link()) + tok1 = tok1->link()->previous(); + else + return false; + } + + // 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%")) { + if (tok1->str() == "return") + return false; + 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; } - // 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/testconstructors.cpp b/test/testconstructors.cpp index c96cd63e4..fc08d77af 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -73,6 +73,7 @@ private: TEST_CASE(noConstructor7); // ticket #4391 TEST_CASE(noConstructor8); // ticket #4404 TEST_CASE(noConstructor9); // ticket #4419 + TEST_CASE(noConstructor10); // ticket #6614 TEST_CASE(forwardDeclaration); // ticket #4290/#3190 @@ -509,6 +510,26 @@ private: ASSERT_EQUALS("", errout.str()); } + void noConstructor10() { + // ticket #6614 + check("class A : public wxDialog\n" + "{\n" + "private:\n" + " DECLARE_EVENT_TABLE()\n" + "public:\n" + " A(wxWindow *parent,\n" + " wxWindowID id = 1,\n" + " const wxString &title = wxT(""),\n" + " const wxPoint& pos = wxDefaultPosition,\n" + " const wxSize& size = wxDefaultSize,\n" + " long style = wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX);\n" + " virtual ~A();\n" + "private:\n" + " wxTimer *WxTimer1;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + } + // ticket #4290 "False Positive: style (noConstructor): The class 'foo' does not have a constructor." // ticket #3190 "SymbolDatabase: Parse of sub class constructor fails" void forwardDeclaration() {