[clang-tidy] AllowExplicitObjectParameters suppresses warnings for this auto&
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
`cat foo.cc`
```c++
#include
#include
#include
struct task {
struct promise_type {
task get_return_object() {
return {std::coroutine_handle::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle h;
~task() { h.destroy(); }
};
[[gnu::noinline]]
task make_task() {
auto f = [value = 42](this auto& self) -> task {
std::printf("%d\n", value);
co_return;
};
return f();
}
int main() {
auto t = make_task();
t.h.resume();
}
```
```console
❯ ./LLVM-CI-2cbdbc9ad7ff40457023c8f353161069df8eb57f-Linux-X64/bin/clang++ -std=c++23 -g -fsanitize=address foo.cc
❯ ./a.out
=================================================================
==85242==ERROR: AddressSanitizer: stack-use-after-return on address 0x7b956f6f0060 at pc 0x561f43753d1c bp 0x7fff50ae8350 sp 0x7fff50ae8348
READ of size 4 at 0x7b956f6f0060 thread T0
#0 0x561f43753d1b in _ZZ9make_taskvENH3$_0clIS_EE4taskRT_.resume /tmp/llvm-upstream-2cbdbc9ad7ff4/foo.cc:22:25
#1 0x561f437545b3 in std::__n4861::coroutine_handle::resume() const /usr/lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/coroutine:247:29
#2 0x561f437538cf in main /tmp/llvm-upstream-2cbdbc9ad7ff4/foo.cc:30:7
#3 0x7f95718f3680 in __libc_start_call_main (/lib64/libc.so.6+0x3680) (BuildId: 5bd941be836f538fe5e10eff508f7f5dd94905a6)
#4 0x7f95718f3797 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3797) (BuildId: 5bd941be836f538fe5e10eff508f7f5dd94905a6)
#5 0x561f436616e4 in _start (/tmp/llvm-upstream-2cbdbc9ad7ff4/a.out+0x6e4)
Address 0x7b956f6f0060 is located in stack of thread T0 at offset 32 in frame
#0 0x561f4375329f in make_task() /tmp/llvm-upstream-2cbdbc9ad7ff4/foo.cc:20
This frame has 1 object(s):
[32, 36) 'f' (line 21) <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return /tmp/llvm-upstream-2cbdbc9ad7ff4/foo.cc:22:25 in _ZZ9make_taskvENH3$_0clIS_EE4taskRT_.resume
Shadow bytes around the buggy address:
0x7b956f6efd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6efe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6efe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6eff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6eff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7b956f6f0000: f1 f1 f1 f1 00 f3 f3 f3 f5 f5 f5 f5[f5]f5 f5 f5
0x7b956f6f0080: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7b956f6f0100: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7b956f6f0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6f0200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b956f6f0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==85242==ABORTING
Aborted (core dumped) ./a.out
❯ cat .clang-tidy
Checks: '-*,cppcoreguidelines-avoid-capturing-lambda-coroutines'
CheckOptions:
cppcoreguidelines-avoid-capturing-lambda-coroutines.AllowExplicitObjectParameters: true
❯ ./LLVM-CI-2cbdbc9ad7ff40457023c8f353161069df8eb57f-Linux-X64/bin/clang-tidy foo.cc -- -std=c++23
❯ echo $?
0
❯ ./LLVM-CI-2cbdbc9ad7ff40457023c8f353161069df8eb57f-Linux-X64/bin/clang -v
clang version 24.0.0git (https://github.com/llvm/llvm-project 2cbdbc9ad7ff40457023c8f353161069df8eb57f)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /tmp/llvm-upstream-2cbdbc9ad7ff4/LLVM-CI-2cbdbc9ad7ff40457023c8f353161069df8eb57f-Linux-X64/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/16
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/16
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
```
Expected behavior:
The check should warn for capturing coroutine lambdas with reference explicit object parameters (`this auto&` or `this auto&&`), even when `AllowExplicitObjectParameters` is `true`. Only by-value explicit object parameters (`this auto`) should be exempted, since reference parameters do not copy the closure into the coroutine frame.
Contributor guide
Research direction
Start with the foo.cc reproducer and its .clang-tidy configuration, then run clang-tidy with the cppcoreguidelines-avoid-capturing-lambda-coroutines check. Trace how AllowExplicitObjectParameters handles the explicit object parameter. Done means reference parameters such as this auto& and this auto&& produce warnings, while this auto remains exempt.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100