Fixed #6538 (Symboldatabase: improve isFunction)
This commit is contained in:
parent
b9cc5b5c6b
commit
130ffc5752
|
@ -1288,6 +1288,57 @@ 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() == ">") {
|
||||
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%"))
|
||||
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| ;|{|=") ||
|
||||
|
|
|
@ -80,6 +80,7 @@ private:
|
|||
TEST_CASE(testautovar12); // ticket #5024 - crash
|
||||
TEST_CASE(testautovar13); // ticket #5537 - crash
|
||||
TEST_CASE(testautovar14); // ticket #4776 - assignment of function parameter, goto
|
||||
TEST_CASE(testautovar15); // ticket #6538
|
||||
TEST_CASE(testautovar_array1);
|
||||
TEST_CASE(testautovar_array2);
|
||||
TEST_CASE(testautovar_return1);
|
||||
|
@ -390,6 +391,19 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void testautovar15() { // Ticket #6538
|
||||
check("static const float4 darkOutline(0.05f, 0.05f, 0.05f, 0.95f);\n"
|
||||
"static const float darkLuminosity = 0.05 +\n"
|
||||
" 0.0722f * math::powf(darkOutline[2], 2.2);\n"
|
||||
"const float4* ChooseOutlineColor(const float4& textColor) {\n"
|
||||
" const float lumdiff = something;\n"
|
||||
" if (lumdiff > 5.0f)\n"
|
||||
" return &darkOutline;\n"
|
||||
" return 0;\n"
|
||||
"}", false, false);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void testautovar_array1() {
|
||||
check("void func1(int* arr[2])\n"
|
||||
"{\n"
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,24 @@ 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"
|
||||
"static const bool b1 = 2 > foo6(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);
|
||||
ASSERT(findFunctionByName("foo6", &db->scopeList.front()) == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void isImplicitlyVirtual() {
|
||||
{
|
||||
GET_SYMBOL_DB("class Base {\n"
|
||||
|
|
|
@ -418,7 +418,7 @@ private:
|
|||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" A()\n"
|
||||
" A();\n"
|
||||
" void a();\n"
|
||||
"private:\n"
|
||||
" void b();\n"
|
||||
|
|
Loading…
Reference in New Issue