llvm / llvm/llvm-project

Clang Analyzer reports initialized coroutine promise members as garbage in `await_transform`

Open
#208,531 2 comments 0 reactions 0 assignees View on GitHub
clang:static analyzer false-positive regression:15
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Clang Static Analyzer **incorrectly** reports `core.UndefinedBinaryOperatorResult` when `promise_type::await_transform` reads coroutine promise members initialized with in-class member initializers.

The expected behavior is "no warning", since the `storage_` promise member is always initialized to `0`.

This report is based on real warnings showing up in [folly/coro](https://github.com/facebook/folly/tree/main/folly/coro).

# Repro

Analyzing the following code ([on Godbolt](https://godbolt.org/z/TKrTaaGhK)) emits warnings:

```
clang++ --analyze -std=c++20 -Xanalyzer -analyzer-output=text repro.cpp
```

```cpp
#include
#include

struct Ready {
bool await_ready() noexcept { return true; }
void await_suspend(std::coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
};

struct PointerTask {
struct promise_type {
std::uintptr_t storage_ = 0;

PointerTask get_return_object() noexcept { return {}; }
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() noexcept {}
void unhandled_exception() noexcept {}

Ready await_transform(Ready a) noexcept {
(void)(storage_ & ~std::uintptr_t{3});
return a;
}
};
};

PointerTask pointer_repro() { co_await Ready{}; }
```

This warning appears from Clang 15 through trunk:

```
:21:29: warning: The left operand of '&' is a garbage value [core.UndefinedBinaryOperatorResult]
21 | (void)(storage_ & ~std::uintptr_t{3});
| ^
:27:31: note: Calling 'promise_type::await_transform'
27 | PointerTask pointer_repro() { co_await Ready{}; }
| ^~~~~~~~~~~~~~~~
:21:29: note: The left operand of '&' is a garbage value
21 | (void)(storage_ & ~std::uintptr_t{3});
| ~~~~~~~~ ^
```

Contributor guide

Open the contributing guide

Research direction

Use the reduced coroutine example in repro.cpp as the starting point and run clang++ --analyze -std=c++20 -Xanalyzer -analyzer-output=text to confirm the false warning. Trace how the analyzer models promise members and await_transform during coroutine analysis; done means the repro produces no core.UndefinedBinaryOperatorResult warning while preserving correct uninitialized-value diagnostics.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.