[DRAFT] [clang] is_cpp_lambda should only match the call operator of lambdas - #2186
Draft
VladimirMakaev wants to merge 1 commit into
Draft
VladimirMakaev wants to merge 1 commit into
VladimirMakaev wants to merge 1 commit into
Conversation
VladimirMakaev
force-pushed
the
procname-cpp-call-operator
branch
from
October 3, 2026 21:53
734e6bf to
b0aa23b
Compare
`Procname.is_cpp_lambda` matched every method whose name contains `operator()`, so all function
objects were taken for lambdas: RacerD did not report on them, Pulse suppressed
OPTIONAL_EMPTY_ACCESS in them, and closures passed by value to them lost their captures. Closures
passed to generic lambdas lost them too: the callee got the loaded closure, not its address.
```cpp
struct CallLambda {
template <typename F>
int operator()(F lambda) { return lambda(100); }
};
int capturing_null_through_functor_bad() {
int* p = nullptr;
// Infer missed: null dereference
return CallLambda{}([p](int a) { return a + *p; });
}
```
`is_cpp_lambda` now also requires a lambda's closure class, and matches `operator()` as a prefix
instead of a substring; the new `is_cpp_call_operator` still matches any `operator()` for the
`std::function` model. Closure arguments are now passed by address to every callee, including the
`operator()` of lambdas.
## Test plan
New tests in cpp/pulse, cpp/pulse-17 and cpp/racerd: closures passed to a functor and to a generic
lambda, a closure next to a materialized temporary, optional accesses in a functor and in a struct
declared inside a lambda, and RacerD functors (a `lambda_`-named class, a template `operator()`, a
class template). All codetoanalyze cases pass.
VladimirMakaev
force-pushed
the
procname-cpp-call-operator
branch
from
October 5, 2026 06:53
b0aa23b to
7c35afa
Compare
VladimirMakaev
added a commit
to VladimirMakaev/infer
that referenced
this pull request
Oct 5, 2026
`Procname.is_cpp_lambda` matched every method whose name contains `operator()`, so all function objects were taken for lambdas: RacerD did not report on them, Pulse suppressed OPTIONAL_EMPTY_ACCESS in them, and closures passed by value to them lost their captures. Closures passed to generic lambdas lost them too: the callee got the loaded closure, not its address. Expectation conflicts with earlier frontier commits were resolved automatically in: infer/tests/codetoanalyze/cpp/pulse-17/issues.exp, infer/tests/codetoanalyze/cpp/racerd/issues.exp Expected test output regenerated for the combination with earlier frontier commits (no new or lost report): infer/tests/codetoanalyze/cpp/pulse-17/issues.exp (order only), infer/tests/codetoanalyze/cpp/racerd/issues.exp (order only) Upstream-PR: facebook#2186 PR-Head: 7c35afa PR-Base: 9cc2641
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Procname.is_cpp_lambdamatched every method whose name containsoperator(), so all functionobjects were taken for lambdas: RacerD did not report on them, Pulse suppressed
OPTIONAL_EMPTY_ACCESS in them, and closures passed by value to them lost their captures. Closures
passed to generic lambdas lost them too: the callee got the loaded closure, not its address.
is_cpp_lambdanow also requires a lambda's closure class, and matchesoperator()as a prefixinstead of a substring; the new
is_cpp_call_operatorstill matches anyoperator()for thestd::functionmodel. Closure arguments are now passed by address to every callee, including theoperator()of lambdas.Test plan
New tests in cpp/pulse, cpp/pulse-17 and cpp/racerd: closures passed to a functor and to a generic
lambda, a closure next to a materialized temporary, optional accesses in a functor and in a struct
declared inside a lambda, and RacerD functors (a
lambda_-named class, a templateoperator(), aclass template). All codetoanalyze cases pass.