Further improvements to setVarId and function/array pointer detection in SymbolDatabase (#2872)

This commit is contained in:
PKEuS 2014-03-28 17:43:40 +01:00
parent 1c58628223
commit a16d631813
3 changed files with 39 additions and 3 deletions

View File

@ -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) &&

View File

@ -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;
} }

View File

@ -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);