SymbolDatabase: Match function overloads by using ValueType information by running a second pass of the function pointer assignment routine.
This commit is contained in:
parent
abba762d42
commit
f4c0ab5dd5
|
@ -55,7 +55,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
createSymbolDatabaseNeedInitialization();
|
createSymbolDatabaseNeedInitialization();
|
||||||
createSymbolDatabaseVariableSymbolTable();
|
createSymbolDatabaseVariableSymbolTable();
|
||||||
createSymbolDatabaseSetScopePointers();
|
createSymbolDatabaseSetScopePointers();
|
||||||
createSymbolDatabaseSetFunctionPointers();
|
createSymbolDatabaseSetFunctionPointers(true);
|
||||||
createSymbolDatabaseSetVariablePointers();
|
createSymbolDatabaseSetVariablePointers();
|
||||||
createSymbolDatabaseSetTypePointers();
|
createSymbolDatabaseSetTypePointers();
|
||||||
createSymbolDatabaseEnums();
|
createSymbolDatabaseEnums();
|
||||||
|
@ -1148,27 +1148,27 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDatabase::createSymbolDatabaseSetFunctionPointers()
|
void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass)
|
||||||
{
|
{
|
||||||
// Set function definition and declaration pointers
|
if (firstPass) {
|
||||||
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
// Set function definition and declaration pointers
|
||||||
for (std::list<Function>::const_iterator func = it->functionList.begin(); func != it->functionList.end(); ++func) {
|
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||||
if (func->tokenDef)
|
for (std::list<Function>::const_iterator func = it->functionList.begin(); func != it->functionList.end(); ++func) {
|
||||||
const_cast<Token *>(func->tokenDef)->function(&*func);
|
if (func->tokenDef)
|
||||||
|
const_cast<Token *>(func->tokenDef)->function(&*func);
|
||||||
|
|
||||||
if (func->token)
|
if (func->token)
|
||||||
const_cast<Token *>(func->token)->function(&*func);
|
const_cast<Token *>(func->token)->function(&*func);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set function call pointers
|
// Set function call pointers
|
||||||
for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) {
|
for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) {
|
||||||
if (Token::Match(tok, "%name% (")) {
|
if (!tok->function() && tok->varId() == 0 && Token::Match(tok, "%name% (") && !isReservedName(tok->str())) {
|
||||||
if (!tok->function() && tok->varId() == 0 && !isReservedName(tok->str())) {
|
const Function *function = findFunction(tok);
|
||||||
const Function *function = findFunction(tok);
|
if (function)
|
||||||
if (function)
|
const_cast<Token *>(tok)->function(function);
|
||||||
const_cast<Token *>(tok)->function(function);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4010,12 +4010,31 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
while (argtok->astParent() && argtok->astParent() != tok->next() && argtok->astParent()->str() != ",") {
|
while (argtok->astParent() && argtok->astParent() != tok->next() && argtok->astParent()->str() != ",") {
|
||||||
argtok = argtok->astParent();
|
argtok = argtok->astParent();
|
||||||
}
|
}
|
||||||
while (Token::Match(argtok, ".|::"))
|
if (argtok && argtok->valueType() && !funcarg->isArrayOrPointer()) { // TODO: Pointers
|
||||||
argtok = argtok->astOperand2();
|
if (argtok->valueType()->type == ValueType::BOOL) {
|
||||||
|
if (funcarg->typeStartToken()->str() == "bool")
|
||||||
|
same++;
|
||||||
|
else if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long"))
|
||||||
|
fallback1++;
|
||||||
|
} else if (argtok->valueType()->isIntegral()) {
|
||||||
|
if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long"))
|
||||||
|
same++;
|
||||||
|
else if (Token::Match(funcarg->typeStartToken(), "float|double"))
|
||||||
|
fallback1++;
|
||||||
|
} else if (argtok->valueType()->isFloat()) {
|
||||||
|
if (Token::Match(funcarg->typeStartToken(), "float|double"))
|
||||||
|
same++;
|
||||||
|
else if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long"))
|
||||||
|
fallback1++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (Token::Match(argtok, ".|::"))
|
||||||
|
argtok = argtok->astOperand2();
|
||||||
|
|
||||||
if (argtok) {
|
if (argtok) {
|
||||||
const Variable * callarg = check->getVariableFromVarId(argtok->varId());
|
const Variable * callarg = check->getVariableFromVarId(argtok->varId());
|
||||||
checkVariableCallMatch(callarg, funcarg, same, fallback1, fallback2);
|
checkVariableCallMatch(callarg, funcarg, same, fallback1, fallback2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4998,6 +5017,9 @@ void SymbolDatabase::setValueTypeInTokenList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update functions with new type information.
|
||||||
|
createSymbolDatabaseSetFunctionPointers(false);
|
||||||
|
|
||||||
// Update auto variables with new type information.
|
// Update auto variables with new type information.
|
||||||
createSymbolDatabaseSetVariablePointers();
|
createSymbolDatabaseSetVariablePointers();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1159,7 +1159,7 @@ private:
|
||||||
void createSymbolDatabaseNeedInitialization();
|
void createSymbolDatabaseNeedInitialization();
|
||||||
void createSymbolDatabaseVariableSymbolTable();
|
void createSymbolDatabaseVariableSymbolTable();
|
||||||
void createSymbolDatabaseSetScopePointers();
|
void createSymbolDatabaseSetScopePointers();
|
||||||
void createSymbolDatabaseSetFunctionPointers();
|
void createSymbolDatabaseSetFunctionPointers(bool firstPass);
|
||||||
void createSymbolDatabaseSetVariablePointers();
|
void createSymbolDatabaseSetVariablePointers();
|
||||||
void createSymbolDatabaseSetTypePointers();
|
void createSymbolDatabaseSetTypePointers();
|
||||||
void createSymbolDatabaseEnums();
|
void createSymbolDatabaseEnums();
|
||||||
|
|
|
@ -286,6 +286,7 @@ private:
|
||||||
TEST_CASE(findFunction14);
|
TEST_CASE(findFunction14);
|
||||||
TEST_CASE(findFunction15);
|
TEST_CASE(findFunction15);
|
||||||
TEST_CASE(findFunction16);
|
TEST_CASE(findFunction16);
|
||||||
|
TEST_CASE(findFunction17);
|
||||||
|
|
||||||
TEST_CASE(noexceptFunction1);
|
TEST_CASE(noexceptFunction1);
|
||||||
TEST_CASE(noexceptFunction2);
|
TEST_CASE(noexceptFunction2);
|
||||||
|
@ -3753,6 +3754,37 @@ private:
|
||||||
ASSERT_EQUALS(true, f && f->function() == nullptr);
|
ASSERT_EQUALS(true, f && f->function() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void findFunction17() {
|
||||||
|
GET_SYMBOL_DB("void foo(int a) { }\n"
|
||||||
|
"void foo(float a) { }\n"
|
||||||
|
"void foo(void* a) { }\n"
|
||||||
|
"void foo(bool a) { }\n"
|
||||||
|
"void func(int i, float f, bool b) {\n"
|
||||||
|
" foo(i + i);\n"
|
||||||
|
" foo(f + f);\n"
|
||||||
|
" foo(!b);\n"
|
||||||
|
" foo(i > 0);\n"
|
||||||
|
" foo(f + i);\n"
|
||||||
|
"}");
|
||||||
|
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( i + i ) ;");
|
||||||
|
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
|
||||||
|
|
||||||
|
f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + f ) ;");
|
||||||
|
ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
|
||||||
|
|
||||||
|
f = Token::findsimplematch(tokenizer.tokens(), "foo ( ! b ) ;");
|
||||||
|
ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
|
||||||
|
|
||||||
|
f = Token::findsimplematch(tokenizer.tokens(), "foo ( i > 0 ) ;");
|
||||||
|
ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
|
||||||
|
|
||||||
|
f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + i ) ;");
|
||||||
|
ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
|
#define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
|
||||||
ASSERT_EQUALS(true, x != nullptr); \
|
ASSERT_EQUALS(true, x != nullptr); \
|
||||||
|
|
Loading…
Reference in New Issue