Fixed #6614 (false positive: (style) The class 'A' does not have a constructor.)
This commit is contained in:
parent
77e22da7fe
commit
c02acea5bf
|
@ -1303,45 +1303,48 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
tok1 = tok1->tokAt(-1);
|
tok1 = tok1->tokAt(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip over pointers and references
|
// done if constructor or destructor
|
||||||
while (Token::Match(tok1, "[*&]"))
|
if (!Token::Match(tok1, "{|}|;|public:|protected:|private:") && tok1) {
|
||||||
tok1 = tok1->tokAt(-1);
|
// skip over pointers and references
|
||||||
|
while (Token::Match(tok1, "[*&]"))
|
||||||
// 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);
|
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();
|
const Token* tok2 = tok->next()->link()->next();
|
||||||
if (tok2 &&
|
if (tok2 &&
|
||||||
(Token::Match(tok2, "const| ;|{|=") ||
|
(Token::Match(tok2, "const| ;|{|=") ||
|
||||||
|
|
|
@ -73,6 +73,7 @@ private:
|
||||||
TEST_CASE(noConstructor7); // ticket #4391
|
TEST_CASE(noConstructor7); // ticket #4391
|
||||||
TEST_CASE(noConstructor8); // ticket #4404
|
TEST_CASE(noConstructor8); // ticket #4404
|
||||||
TEST_CASE(noConstructor9); // ticket #4419
|
TEST_CASE(noConstructor9); // ticket #4419
|
||||||
|
TEST_CASE(noConstructor10); // ticket #6614
|
||||||
|
|
||||||
TEST_CASE(forwardDeclaration); // ticket #4290/#3190
|
TEST_CASE(forwardDeclaration); // ticket #4290/#3190
|
||||||
|
|
||||||
|
@ -509,6 +510,26 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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 #4290 "False Positive: style (noConstructor): The class 'foo' does not have a constructor."
|
||||||
// ticket #3190 "SymbolDatabase: Parse of sub class constructor fails"
|
// ticket #3190 "SymbolDatabase: Parse of sub class constructor fails"
|
||||||
void forwardDeclaration() {
|
void forwardDeclaration() {
|
||||||
|
|
Loading…
Reference in New Issue