Fixed #752 (SymbolDatabase: Does not match function if redundant keywords mismatch (C++))
This commit is contained in:
parent
6ca76ff965
commit
55b3f0bf38
|
@ -1777,7 +1777,7 @@ CheckBufferOverrun::ArrayInfo::ArrayInfo(const Variable *var, const SymbolDataba
|
|||
_num.push_back(var->dimension(i));
|
||||
if (var->typeEndToken()->str() == "*")
|
||||
_element_size = symDb->sizeOfType(var->typeEndToken());
|
||||
else if (var->typeStartToken()->str() == "struct")
|
||||
else if (var->typeStartToken()->strAt(-1) == "struct")
|
||||
_element_size = 100;
|
||||
else {
|
||||
_element_size = symDb->sizeOfType(var->typeEndToken());
|
||||
|
|
|
@ -117,12 +117,12 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
|||
if (scope->function) {
|
||||
for (unsigned int i = 0; i < scope->function->argCount(); i++) {
|
||||
const Variable *arg = scope->function->getArgumentVar(i);
|
||||
if (arg && arg->declarationId() && Token::Match(arg->typeStartToken(), "struct| %type% * %name% [,)]")) {
|
||||
if (arg && arg->declarationId() && Token::Match(arg->typeStartToken(), "%type% * %name% [,)]")) {
|
||||
// Treat the pointer as initialized until it is assigned by malloc
|
||||
for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[;{}] %varid% = %name% (", arg->declarationId()) &&
|
||||
_settings->library.returnuninitdata.count(tok->strAt(3)) == 1U) {
|
||||
if (arg->typeStartToken()->str() == "struct")
|
||||
if (arg->typeStartToken()->strAt(-1) == "struct" || (arg->type() && arg->type()->isStructType()))
|
||||
checkStruct(tok, *arg);
|
||||
else if (arg->typeStartToken()->isStandardType() || arg->typeStartToken()->isEnumType()) {
|
||||
Alloc alloc = NO_ALLOC;
|
||||
|
@ -138,8 +138,6 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
|||
void CheckUninitVar::checkStruct(const Token *tok, const Variable &structvar)
|
||||
{
|
||||
const Token *typeToken = structvar.typeStartToken();
|
||||
if (typeToken->str() == "struct")
|
||||
typeToken = typeToken->next();
|
||||
const SymbolDatabase * symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
for (std::size_t j = 0U; j < symbolDatabase->classAndStructScopes.size(); ++j) {
|
||||
const Scope *scope2 = symbolDatabase->classAndStructScopes[j];
|
||||
|
@ -1017,9 +1015,9 @@ int CheckUninitVar::isFunctionParUsage(const Token *vartok, bool pointer, Alloc
|
|||
const Variable *arg = func->getArgumentVar(argumentNumber);
|
||||
if (arg) {
|
||||
const Token *argStart = arg->typeStartToken();
|
||||
if (!address && !array && Token::Match(argStart, "struct| %type% %name%| [,)]"))
|
||||
if (!address && !array && Token::Match(argStart, "%type% %name%| [,)]"))
|
||||
return 1;
|
||||
if (pointer && !address && alloc == NO_ALLOC && Token::Match(argStart, "struct| %type% * %name% [,)]"))
|
||||
if (pointer && !address && alloc == NO_ALLOC && Token::Match(argStart, "%type% * %name% [,)]"))
|
||||
return 1;
|
||||
while (argStart->previous() && argStart->previous()->isName())
|
||||
argStart = argStart->previous();
|
||||
|
|
|
@ -1817,9 +1817,9 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
|
|||
second = second->next();
|
||||
|
||||
// skip "struct"
|
||||
if (first->str() == "struct")
|
||||
if (first->str() == "struct" || first->str() == "enum")
|
||||
first = first->next();
|
||||
if (second->str() == "struct")
|
||||
if (second->str() == "struct" || second->str() == "enum")
|
||||
second = second->next();
|
||||
|
||||
// skip const on type passed by value
|
||||
|
@ -2402,7 +2402,7 @@ void SymbolDatabase::printVariable(const Variable *var, const char *indent) cons
|
|||
std::cout << indent << " isStlType: " << var->isStlType() << std::endl;
|
||||
std::cout << indent << "_type: ";
|
||||
if (var->type()) {
|
||||
std::cout << var->type()->name();
|
||||
std::cout << var->type()->type() << " " << var->type()->name();
|
||||
std::cout << " " << _tokenizer->list.fileLine(var->type()->classDef);
|
||||
std::cout << " " << var->type() << std::endl;
|
||||
} else
|
||||
|
@ -2819,6 +2819,10 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
|||
} while (tok->str() != "," && tok->str() != ")");
|
||||
}
|
||||
|
||||
// skip over stuff before type
|
||||
while (Token::Match(startTok, "enum|struct|const"))
|
||||
startTok = startTok->next();
|
||||
|
||||
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library));
|
||||
|
||||
if (tok->str() == ")") {
|
||||
|
@ -3183,6 +3187,10 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con
|
|||
const_cast<Token *>(typetok)->type(vType);
|
||||
}
|
||||
|
||||
// skip "enum" or "struct"
|
||||
if (Token::Match(typestart, "enum|struct"))
|
||||
typestart = typestart->next();
|
||||
|
||||
addVariable(vartok, typestart, vartok->previous(), varaccess, vType, this, lib);
|
||||
}
|
||||
|
||||
|
@ -3468,10 +3476,17 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
|||
}
|
||||
}
|
||||
|
||||
const Type * type = findVariableTypeInBase(scope, typeTok);
|
||||
if (scope) {
|
||||
const Type * type = scope->findType(typeTok->str());
|
||||
|
||||
if (type)
|
||||
return type;
|
||||
if (type)
|
||||
return type;
|
||||
|
||||
type = findVariableTypeInBase(scope, typeTok);
|
||||
|
||||
if (type)
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Type>::const_iterator type;
|
||||
|
@ -3497,13 +3512,24 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
|||
}
|
||||
|
||||
if (type->enclosingScope == parent) {
|
||||
// check if "enum" specified and type is enum
|
||||
if (typeTok->strAt(-1) == "enum") {
|
||||
if (type->classDef->str() == "enum")
|
||||
if (type->isEnumType())
|
||||
return &(*type);
|
||||
} else if (typeTok->strAt(-1) == "struct") {
|
||||
if (type->classDef->str() == "struct")
|
||||
else // not an enum
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if "struct" specified and type is struct
|
||||
else if (typeTok->strAt(-1) == "struct") {
|
||||
if (type->isStructType())
|
||||
return &(*type);
|
||||
} else
|
||||
else // not a struct
|
||||
continue;
|
||||
}
|
||||
|
||||
// "enum" or "struct" not specified so assume match
|
||||
else
|
||||
return &(*type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,10 +109,22 @@ public:
|
|||
|
||||
const std::string& name() const;
|
||||
|
||||
const std::string& type() const {
|
||||
return classDef ? classDef->str() : emptyString;
|
||||
}
|
||||
|
||||
bool isClassType() const {
|
||||
return classDef && classDef->str() == "class";
|
||||
}
|
||||
|
||||
bool isEnumType() const {
|
||||
return classDef && classDef->str() == "enum";
|
||||
}
|
||||
|
||||
bool isStructType() const {
|
||||
return classDef && classDef->str() == "struct";
|
||||
}
|
||||
|
||||
const Token *initBaseInfo(const Token *tok, const Token *tok1);
|
||||
|
||||
const Function* getFunction(const std::string& funcName) const;
|
||||
|
|
|
@ -183,6 +183,9 @@ private:
|
|||
TEST_CASE(functionArgs3);
|
||||
TEST_CASE(functionArgs4);
|
||||
TEST_CASE(functionArgs5); // #7650
|
||||
TEST_CASE(functionArgs6); // #7651
|
||||
TEST_CASE(functionArgs7); // #7652
|
||||
TEST_CASE(functionArgs8); // #7653
|
||||
|
||||
TEST_CASE(namespaces1);
|
||||
TEST_CASE(namespaces2);
|
||||
|
@ -1591,7 +1594,139 @@ private:
|
|||
ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->classDef->str() == "enum");
|
||||
ASSERT_EQUALS(true, type->isEnumType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void functionArgs6() { // #7651
|
||||
GET_SYMBOL_DB("class ABC {};\n"
|
||||
"class Y {\n"
|
||||
" enum ABC {A,B,C};\n"
|
||||
" void f(ABC abc) {}\n"
|
||||
"};");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "f ( ABC");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->isEnumType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void functionArgs7() { // #7652
|
||||
{
|
||||
GET_SYMBOL_DB("struct AB { int a; int b; };\n"
|
||||
"int foo(struct AB *ab);\n"
|
||||
"void bar() {\n"
|
||||
" struct AB ab;\n"
|
||||
" foo(&ab); \n"
|
||||
"};");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->classDef->linenr() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
GET_SYMBOL_DB("struct AB { int a; int b; };\n"
|
||||
"int foo(AB *ab);\n"
|
||||
"void bar() {\n"
|
||||
" struct AB ab;\n"
|
||||
" foo(&ab); \n"
|
||||
"};");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->classDef->linenr() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
GET_SYMBOL_DB("struct AB { int a; int b; };\n"
|
||||
"int foo(struct AB *ab);\n"
|
||||
"void bar() {\n"
|
||||
" AB ab;\n"
|
||||
" foo(&ab); \n"
|
||||
"};");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->classDef->linenr() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
GET_SYMBOL_DB("struct AB { int a; int b; };\n"
|
||||
"int foo(AB *ab);\n"
|
||||
"void bar() {\n"
|
||||
" AB ab;\n"
|
||||
" foo(&ab); \n"
|
||||
"};");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->classDef->linenr() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void functionArgs8() { // #7653
|
||||
GET_SYMBOL_DB("struct A { int i; };\n"
|
||||
"struct B { double d; };\n"
|
||||
"int foo(struct A a);\n"
|
||||
"double foo(struct B b);\n"
|
||||
"void bar() {\n"
|
||||
" struct B b;\n"
|
||||
" foo(b);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS(true, db != nullptr);
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( b");
|
||||
ASSERT_EQUALS(true, f && f->function());
|
||||
if (f && f->function()) {
|
||||
const Function *func = f->function();
|
||||
ASSERT_EQUALS(true, func->tokenDef->linenr() == 4 && func->argumentList.size() == 1 && func->argumentList.front().type());
|
||||
if (func->argumentList.size() == 1 && func->argumentList.front().type()) {
|
||||
const Type * type = func->argumentList.front().type();
|
||||
ASSERT_EQUALS(true, type->isStructType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue