Fixed #6538 (Symboldatabase: improve isFunction)
This commit is contained in:
parent
26c2c4a824
commit
d7ef89bbe6
|
@ -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->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
|
tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok
|
||||||
outerScope->isClassOrStruct())) { // or a ctor/dtor
|
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();
|
const Token* tok2 = tok->next()->link()->next();
|
||||||
if (tok2 &&
|
if (tok2 &&
|
||||||
(Token::Match(tok2, "const| ;|{|=") ||
|
(Token::Match(tok2, "const| ;|{|=") ||
|
||||||
|
|
|
@ -420,11 +420,11 @@ private:
|
||||||
|
|
||||||
ASSERT_THROW(checkCode("class Foo {}; class Bar : public Foo"), InternalError);
|
ASSERT_THROW(checkCode("class Foo {}; class Bar : public Foo"), InternalError);
|
||||||
|
|
||||||
ASSERT_THROW(checkCode("YY_DECL { switch (yy_act) {\n"
|
checkCode("YY_DECL { switch (yy_act) {\n"
|
||||||
" case 65: YY_BREAK\n"
|
" case 65: YY_BREAK\n"
|
||||||
" case YY_STATE_EOF(block):\n"
|
" case YY_STATE_EOF(block):\n"
|
||||||
" yyterminate(); \n"
|
" yyterminate(); \n"
|
||||||
"} }"), InternalError); // #5663
|
"} }"); // #5663
|
||||||
}
|
}
|
||||||
|
|
||||||
void garbageAST() {
|
void garbageAST() {
|
||||||
|
|
|
@ -3020,7 +3020,7 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout.str());
|
||||||
|
|
||||||
// #5707
|
// #5707
|
||||||
check("extern int i,j\n"
|
check("extern int i,j;\n"
|
||||||
"int foo() {\n"
|
"int foo() {\n"
|
||||||
" switch(i) {\n"
|
" switch(i) {\n"
|
||||||
" default: j=1; break;\n"
|
" default: j=1; break;\n"
|
||||||
|
|
|
@ -228,6 +228,7 @@ private:
|
||||||
TEST_CASE(symboldatabase48); // #6417
|
TEST_CASE(symboldatabase48); // #6417
|
||||||
TEST_CASE(symboldatabase49); // #6424
|
TEST_CASE(symboldatabase49); // #6424
|
||||||
TEST_CASE(symboldatabase50); // #6432
|
TEST_CASE(symboldatabase50); // #6432
|
||||||
|
TEST_CASE(symboldatabase51); // #6538
|
||||||
|
|
||||||
TEST_CASE(isImplicitlyVirtual);
|
TEST_CASE(isImplicitlyVirtual);
|
||||||
|
|
||||||
|
@ -2128,6 +2129,22 @@ private:
|
||||||
ASSERT_EQUALS(true, db && f && f->function() && f->function()->isConstructor());
|
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() {
|
void isImplicitlyVirtual() {
|
||||||
{
|
{
|
||||||
GET_SYMBOL_DB("class Base {\n"
|
GET_SYMBOL_DB("class Base {\n"
|
||||||
|
|
|
@ -418,7 +418,7 @@ private:
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" A()\n"
|
" A();\n"
|
||||||
" void a();\n"
|
" void a();\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" void b();\n"
|
" void b();\n"
|
||||||
|
|
Loading…
Reference in New Issue