Further improvements to setVarId and function/array pointer detection in SymbolDatabase (#2872)
This commit is contained in:
parent
1c58628223
commit
a16d631813
|
@ -2408,7 +2408,7 @@ static const Token* skipScopeIdentifiers(const Token* tok)
|
||||||
|
|
||||||
static const Token* skipPointers(const Token* tok)
|
static const Token* skipPointers(const Token* tok)
|
||||||
{
|
{
|
||||||
while (Token::Match(tok, "*|&|&&")) {
|
while (Token::Match(tok, "*|&|&&") || (tok && tok->str() == "(" && Token::Match(tok->link()->next(), "(|["))) {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2446,7 +2446,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
if (Token::Match(localVarTok, "%var% ;|=")) {
|
if (Token::Match(localVarTok, "%var% ;|=")) {
|
||||||
vartok = localVarTok;
|
vartok = localVarTok;
|
||||||
typetok = localTypeTok;
|
typetok = localTypeTok;
|
||||||
} else if (Token::Match(localVarTok, "%var% [") && localVarTok->str() != "operator") {
|
} else if (Token::Match(localVarTok, "%var% )|[") && localVarTok->str() != "operator") {
|
||||||
vartok = localVarTok;
|
vartok = localVarTok;
|
||||||
typetok = localTypeTok;
|
typetok = localTypeTok;
|
||||||
} else if ((isLocal() || type == Scope::eFunction) &&
|
} else if ((isLocal() || type == Scope::eFunction) &&
|
||||||
|
|
|
@ -2177,6 +2177,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned int typeCount = 0;
|
unsigned int typeCount = 0;
|
||||||
|
unsigned int singleNameCount = 0;
|
||||||
bool hasstruct = false; // Is there a "struct" or "class"?
|
bool hasstruct = false; // Is there a "struct" or "class"?
|
||||||
bool bracket = false;
|
bool bracket = false;
|
||||||
while (tok2) {
|
while (tok2) {
|
||||||
|
@ -2184,6 +2185,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
||||||
if (tok2->str() == "struct" || tok2->str() == "union" || (cpp && (tok2->str() == "class" || tok2->str() == "typename"))) {
|
if (tok2->str() == "struct" || tok2->str() == "union" || (cpp && (tok2->str() == "class" || tok2->str() == "typename"))) {
|
||||||
hasstruct = true;
|
hasstruct = true;
|
||||||
typeCount = 0;
|
typeCount = 0;
|
||||||
|
singleNameCount = 0;
|
||||||
} else if (tok2->str() == "const") {
|
} else if (tok2->str() == "const") {
|
||||||
; // just skip "const"
|
; // just skip "const"
|
||||||
} else if (!hasstruct && variableId.find(tok2->str()) != variableId.end() && tok2->previous()->str() != "::") {
|
} else if (!hasstruct && variableId.find(tok2->str()) != variableId.end() && tok2->previous()->str() != "::") {
|
||||||
|
@ -2193,16 +2195,20 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
++typeCount;
|
++typeCount;
|
||||||
|
++singleNameCount;
|
||||||
}
|
}
|
||||||
} else if ((TemplateSimplifier::templateParameters(tok2) > 0) ||
|
} else if ((TemplateSimplifier::templateParameters(tok2) > 0) ||
|
||||||
Token::simpleMatch(tok2, "< >") /* Ticket #4764 */) {
|
Token::simpleMatch(tok2, "< >") /* Ticket #4764 */) {
|
||||||
tok2 = tok2->findClosingBracket();
|
tok2 = tok2->findClosingBracket();
|
||||||
if (!Token::Match(tok2, ">|>>"))
|
if (!Token::Match(tok2, ">|>>"))
|
||||||
break;
|
break;
|
||||||
|
singleNameCount = 1;
|
||||||
} else if (tok2->str() == "&" || tok2->str() == "&&") {
|
} else if (tok2->str() == "&" || tok2->str() == "&&") {
|
||||||
ref = !bracket;
|
ref = !bracket;
|
||||||
} else if (typeCount == 1 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "(|[")) {
|
} else if (singleNameCount == 1 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "(|[")) {
|
||||||
bracket = true; // Skip: Seems to be valid pointer to array or function pointer
|
bracket = true; // Skip: Seems to be valid pointer to array or function pointer
|
||||||
|
} else if (tok2->str() == "::") {
|
||||||
|
singleNameCount = 0;
|
||||||
} else if (tok2->str() != "*" && tok2->str() != "::") {
|
} else if (tok2->str() != "*" && tok2->str() != "::") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,7 @@ private:
|
||||||
TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
|
TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
|
||||||
TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer);
|
TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer);
|
||||||
TEST_CASE(hasClassFunctionReturningFunctionPointer);
|
TEST_CASE(hasClassFunctionReturningFunctionPointer);
|
||||||
|
TEST_CASE(complexFunctionArrayPtr);
|
||||||
TEST_CASE(hasSubClassConstructor);
|
TEST_CASE(hasSubClassConstructor);
|
||||||
TEST_CASE(testConstructors);
|
TEST_CASE(testConstructors);
|
||||||
TEST_CASE(functionDeclarationTemplate);
|
TEST_CASE(functionDeclarationTemplate);
|
||||||
|
@ -835,6 +836,35 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void complexFunctionArrayPtr() {
|
||||||
|
GET_SYMBOL_DB("int(*p1)[10]; \n" // pointer to array 10 of int
|
||||||
|
"void(*p2)(char); \n" // pointer to function (char) returning void
|
||||||
|
"int(*(*p3)(char))[10];\n" // pointer to function (char) returning pointer to array 10 of int
|
||||||
|
"float(*(*p4)(char))(long); \n" // pointer to function (char) returning pointer to function (long) returning float
|
||||||
|
"short(*(*(p5) (char))(long))(double); \n" // pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short
|
||||||
|
"int(*a1[10])(void); \n" // array 10 of pointer to function (void) returning int
|
||||||
|
"float(*(*a2[10])(char))(long);\n" // array 10 of pointer to func (char) returning pointer to func (long) returning float
|
||||||
|
"short(*(*(*a3[10])(char))(long))(double);\n" // array 10 of pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short
|
||||||
|
"::boost::rational(&r_)[9];\n" // reference to array of ::boost::rational
|
||||||
|
"::boost::rational<T>(&r_)[9];"); // reference to array of ::boost::rational<T> (template!)
|
||||||
|
|
||||||
|
ASSERT(db != nullptr);
|
||||||
|
|
||||||
|
if (db) {
|
||||||
|
ASSERT_EQUALS(10, db->getVariableListSize() - 1);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(1) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(2) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(3) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(4) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(5) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(6) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(7) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(8) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(9) != nullptr);
|
||||||
|
ASSERT_EQUALS(true, db->getVariableFromVarId(10) != nullptr);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
void hasSubClassConstructor() {
|
void hasSubClassConstructor() {
|
||||||
GET_SYMBOL_DB("class Foo { class Sub; }; class Foo::Sub { Sub() {} };");
|
GET_SYMBOL_DB("class Foo { class Sub; }; class Foo::Sub { Sub() {} };");
|
||||||
ASSERT(db != nullptr);
|
ASSERT(db != nullptr);
|
||||||
|
|
Loading…
Reference in New Issue