[all-commits] [llvm/llvm-project] 315128: [clang-tidy] Add check to diagnose coroutine-hosti...

Utkarsh Saxena via All-commits all-commits at lists.llvm.org
Tue Oct 17 11:46:16 PDT 2023


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 31512811b8c0f8fd328fba585640992c39218f1e
      https://github.com/llvm/llvm-project/commit/31512811b8c0f8fd328fba585640992c39218f1e
  Author: Utkarsh Saxena <usaxena95 at gmail.com>
  Date:   2023-10-17 (Tue, 17 Oct 2023)

  Changed paths:
    M clang-tools-extra/clang-tidy/misc/CMakeLists.txt
    A clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp
    A clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h
    M clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
    M clang-tools-extra/docs/ReleaseNotes.rst
    M clang-tools-extra/docs/clang-tidy/checks/list.rst
    A clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst
    A clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp

  Log Message:
  -----------
  [clang-tidy] Add check to diagnose coroutine-hostile RAII objects (#68738)

This check detects **hostile-RAII** objects which should not **persist
across a suspension point in a coroutine**.

Some objects require that they be destroyed on the same thread that
created them. Traditionally this requirement was often phrased as "must
be a local variable", under the assumption that local variables always
work this way. However this is incorrect with **C++20 coroutines**,
since an intervening `co_await` may cause the coroutine to suspend and
later be resumed on another thread.

The lifetime of an object that requires being destroyed on the same
thread must not encompass a `co_await` or `co_yield` point. If you
create/destroy an object, you must do so without allowing the coroutine
to suspend in the meantime.

The check considers the following type as hostile:

- **Scoped-lockable types**: A scoped-lockable object persisting across
a suspension point is problematic as the lock held by this object could
be unlocked by a different thread. This would be undefined behaviour.

 - Types belonging to a configurable **denylist**.

```cpp
  // Call some async API while holding a lock.
const my::MutexLock l(&mu_);

// Oops! The async Bar function may finish on a different
// thread from the one that created the MutexLock object and therefore called
// Mutex::Lock -- now Mutex::Unlock will be called on the wrong thread.
co_await Bar();
```




More information about the All-commits mailing list