Skip to content

Fix #15104 FP functionStatic and constParameterReference: call of overloaded member function template resolved to free function with the same name - #8936

Open
autoantwort wants to merge 1 commit into
cppcheck-opensource:mainfrom
autoantwort:fix-15104-member-overload
Open

autoantwort wants to merge 1 commit into
cppcheck-opensource:mainfrom
autoantwort:fix-15104-member-overload

Conversation

@autoantwort

Copy link
Copy Markdown
Contributor

https://trac.cppcheck.net/ticket/15104

struct DS;
void select(int a, int b);
class Query {
    int m = 0;
public:
    template <typename Callback>
    int select(DS &ds, Callback cb) { cb(m); return 0; }
    template <typename Callback>
    int select(DS *ds, Callback cb) { return select(*ds, cb); }
    int select(DS &ds) { return select(ds, [](int) {}); }   // FP functionStatic, constParameterReference
};

Scope::findFunction() couldn't choose between select(DS &, Callback) and select(DS *, Callback) for select(ds, ...) with DS &ds: the pointer overload stayed a candidate although an object can't be passed for a pointer to its class. As the call was ambiguous in the class scope, the lookup continued in the enclosing scopes and picked the free select(int, int).

A candidate is now removed when a plain variable argument and the parameter have the same class type but only one of them is a pointer:

  • an object for a C* parameter, unless the class (or one of its base classes, or an unknown base class) has a conversion operator
  • a C* for a non-const lvalue reference C& (a temporary from a converting constructor can bind to const C& and C&&, so these are kept)

By-value parameters, arrays and function pointers/references are not affected. Incomplete types are assumed to have no conversion operator. Built-in and library types, and arguments that are not plain variables (*p), are not covered.

When a member overload can't be resolved, the lookup still continues in the enclosing scopes although the member functions hide the free function (C++ name hiding). That is a separate issue and not changed here.

This PR was created by Claude Code (an AI coding agent) on behalf of @autoantwort.

🤖 Generated with Claude Code

…rloaded member function template resolved to free function with the same name

For `select(ds, cb)` with `DS& ds`, the overload `select(DS*, Callback)` was
not removed from the candidates, so Scope::findFunction() couldn't choose
between the member overloads. The lookup then continued in the enclosing
scopes and picked a free function with the same name.

An object of a class can't be passed for a pointer to this class, and a
pointer can't be passed for a non-const reference to it, so these candidates
are removed now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

I found no new problems. The fix does what the description says for the ticket case, and in my own overload tests the PR differed from base only where a candidate really is not callable (an object passed for C* with no conversion operator, a C* passed for a non-const C&).

One gap in my testing: the base-vs-PR comparison on cppcheck's own sources did not finish, so I have no result on real-world code.

Testing

Build: make -j8 cppcheck testrunner in pr/ succeeded; base/ cppcheck was built for comparison.

Unit tests (PR): ./testrunner TestSymbolDatabase, ./testrunner TestClass and ./testrunner TestOther all report Tests failed: 0.

Own tests: I wrote four files in /work/scratch, ran both binaries with cppcheck -q --dump --std=c++17 <file>, and compared which declaration each call token's function attribute points to.

  • Identical between base and PR (about 60 calls):
    • auto p = &c; f(p);, const auto, decltype(...) and range-for variables
    • typedef / using / nested-typedef pointer types, C*&, C* const&, C** dereferenced
    • arrays, pointer-to-array and reference-to-array arguments, function pointers and function references
    • enums, nested classes, forward-declared classes (also when defined later with a conversion operator)
    • forward-declared and uninstantiated templates (Opt<C*>& vs Opt<C>*, Box<U*>& inside a class template), calls inside a class template with X* / X& overloads
    • default arguments, C-style variadics, parameter packs, const and non-const member overloads
    • classes with operator bool, operator int, and a pointer conversion operator in a derived class
  • Different, and correct in the PR:
    • void only(C* p); void g(C c) { only(c); } and void onlyr(C& r); void g(C* p) { onlyr(p); }: base links the call, the PR leaves it unlinked. Both calls are ill-formed.
    • struct Self { Self(Self* parent); }; void s(Self& r); void s(const Self& r, int); void s(Self v, char, char = 0); void s1(Self* p) { s(p); }: base links s(p) to s(Self&), the PR leaves it unlinked. The call is ill-formed.
    • namespace ns { struct C { operator ::C*(); }; void n(C* p); void n(::C* p, int = 0); void n1(C c, ::C g) { n(c); n(g); } }: one of the two calls is unresolved in base and resolved in the PR. I did not check which overload it now points to, because both declarations are on the same line of my test file.

Not completed: running both binaries with --enable=style,performance --inconclusive on lib/symboldatabase.cpp, lib/tokenize.cpp and lib/checkclass.cpp was killed at the 1500 s timeout before producing a comparison. The Python tests in test/cli were not run; the PR does not touch them.


Automated review of 271a5ea by Claude. The pull request was built and tested locally.

@dmcppcheck

Copy link
Copy Markdown

Test results for commit 271a5ea (tools/test-my-pr.py, main compared to this PR):

Test: http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8936/
packages: 100
Differing warnings: 0 (+0 -0)
Timing: -0.3% (http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8936/2026-10-12_15-20-39-271a5ea1104f_timing.html)

Posted automatically by the cppcheck PR test runner. +N: warnings only with this PR, -N: warnings only with main. The AI review is written by Claude and can be wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants