Skip to content

[DRAFT] [clang] is_cpp_lambda should only match the call operator of lambdas - #2186

Draft
VladimirMakaev wants to merge 1 commit into
facebook:mainfrom
VladimirMakaev:procname-cpp-call-operator
Draft

VladimirMakaev wants to merge 1 commit into
facebook:mainfrom
VladimirMakaev:procname-cpp-call-operator

Conversation

@VladimirMakaev

@VladimirMakaev VladimirMakaev commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

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.

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.

@meta-cla meta-cla Bot added the CLA Signed label Oct 2, 2026
@VladimirMakaev
VladimirMakaev force-pushed the procname-cpp-call-operator branch from 734e6bf to b0aa23b Compare October 3, 2026 21:53
`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
VladimirMakaev force-pushed the procname-cpp-call-operator branch from b0aa23b to 7c35afa Compare October 5, 2026 06:53
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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant