Skip to content

Commit

Permalink
Fixed #13127 (SymbolDatabase: findFunction does not handle ref-qualif…
Browse files Browse the repository at this point in the history
…iers properly) (#6819)
  • Loading branch information
danmar authored Sep 26, 2024
1 parent e34b23b commit 776f6fd
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
6 changes: 4 additions & 2 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5698,7 +5698,7 @@ static bool hasMatchingConstructor(const Scope* classScope, const ValueType* arg
});
}

const Function* Scope::findFunction(const Token *tok, bool requireConst) const
const Function* Scope::findFunction(const Token *tok, bool requireConst, Reference ref) const
{
const bool isCall = Token::Match(tok->next(), "(|{");

Expand All @@ -5713,6 +5713,8 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
auto range = scope->functionMap.equal_range(tok->str());
for (std::multimap<std::string, const Function *>::const_iterator it = range.first; it != range.second; ++it) {
const Function *func = it->second;
if (ref == Reference::LValue && func->hasRvalRefQualifier())
continue;
if (!isCall || args == func->argCount() ||
(func->isVariadic() && args >= (func->minArgCount() - 1)) ||
(args < func->argCount() && args >= func->minArgCount())) {
Expand Down Expand Up @@ -6066,7 +6068,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
else if (Token::Match(tok->tokAt(-2), "!!this .")) {
const Token* tok1 = tok->previous()->astOperand1();
if (tok1 && tok1->valueType() && tok1->valueType()->typeScope)
return tok1->valueType()->typeScope->findFunction(tok, tok1->valueType()->constness == 1);
return tok1->valueType()->typeScope->findFunction(tok, tok1->valueType()->constness == 1, tok1->valueType()->reference);
if (tok1 && Token::Match(tok1->previous(), "%name% (") && tok1->previous()->function() &&
tok1->previous()->function()->retDef) {
ValueType vt = ValueType::parseDecl(tok1->previous()->function()->retDef, mSettings);
Expand Down
14 changes: 7 additions & 7 deletions lib/symboldatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class SymbolDatabase;
class Tokenizer;
class ValueType;

enum class Reference : std::uint8_t {
None,
LValue,
RValue
};

/**
* @brief Access control enumerations.
*/
Expand Down Expand Up @@ -1128,7 +1134,7 @@ class CPPCHECKLIB Scope {
* @param requireConst if const refers to a const variable only const methods should be matched
* @return pointer to function if found or NULL if not found
*/
const Function *findFunction(const Token *tok, bool requireConst=false) const;
const Function *findFunction(const Token *tok, bool requireConst=false, Reference ref=Reference::None) const;

const Scope *findRecordInNestedList(const std::string & name, bool isC = false) const;
Scope *findRecordInNestedList(const std::string & name, bool isC = false);
Expand Down Expand Up @@ -1199,12 +1205,6 @@ class CPPCHECKLIB Scope {
void getVariableList(const Settings& settings, const Token *start, const Token *end);
};

enum class Reference : std::uint8_t {
None,
LValue,
RValue
};

/** Value type */
class CPPCHECKLIB ValueType {
public:
Expand Down
20 changes: 20 additions & 0 deletions test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(findFunction53);
TEST_CASE(findFunction54);
TEST_CASE(findFunction55); // #31004
TEST_CASE(findFunctionRef1);
TEST_CASE(findFunctionContainer);
TEST_CASE(findFunctionExternC);
TEST_CASE(findFunctionGlobalScope); // ::foo
Expand Down Expand Up @@ -8329,6 +8330,25 @@ class TestSymbolDatabase : public TestFixture {
ASSERT(Token::simpleMatch(f->function()->tokenDef, "f ( const Token * ptr ) ;"));
}

void findFunctionRef1() {
GET_SYMBOL_DB("struct X {\n"
" const std::vector<int> getInts() const & { return mInts; }\n"
" std::vector<int> getInts() && { return mInts; }\n"
" std::vector<int> mInts;\n"
"}\n"
"\n"
"void foo(X &x) {\n"
" x.getInts();\n"
"}\n");
const Token* x = Token::findsimplematch(tokenizer.tokens(), "x . getInts ( ) ;");
ASSERT(x);
const Token* f = x->tokAt(2);
ASSERT(f);
ASSERT(f->function());
ASSERT(f->function()->tokenDef);
ASSERT_EQUALS(2, f->function()->tokenDef->linenr());
}

void findFunctionContainer() {
{
GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"
Expand Down

0 comments on commit 776f6fd

Please sign in to comment.