Fixed #6538 (Symboldatabase: improve isFunction)

This commit is contained in:
Robert Reif 2015-02-23 06:49:50 +01:00 committed by Daniel Marjamäki
parent 26c2c4a824
commit d7ef89bbe6
5 changed files with 71 additions and 7 deletions

View File

@ -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| ;|{|=") ||

View File

@ -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() {

View File

@ -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"

View File

@ -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"

View File

@ -418,7 +418,7 @@ private:
"class A\n"
"{\n"
"public:\n"
" A()\n"
" A();\n"
" void a();\n"
"private:\n"
" void b();\n"