Repository navigation
Fix #15104 FP functionStatic and constParameterReference: call of overloaded member function template resolved to free function with the same name - #8936
Conversation
…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
left a comment
There was a problem hiding this comment.
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*>&vsOpt<C>*,Box<U*>&inside a class template), calls inside a class template withX*/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); }andvoid 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 linkss(p)tos(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.
|
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/ 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. |
https://trac.cppcheck.net/ticket/15104
Scope::findFunction()couldn't choose betweenselect(DS &, Callback)andselect(DS *, Callback)forselect(ds, ...)withDS &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 freeselect(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:
C*parameter, unless the class (or one of its base classes, or an unknown base class) has a conversion operatorC*for a non-const lvalue referenceC&(a temporary from a converting constructor can bind toconst C&andC&&, 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