Skip to content

Conversation

@higher-performance
Copy link
Contributor

When you have code like co_await foo(), foo may know for a fact that it is returning an object that is safe to hold a mutex across. There is currently no way to exempt these. This PR adds support for such exemptions.

@llvmbot
Copy link
Member

llvmbot commented Nov 12, 2025

@llvm/pr-subscribers-coroutines
@llvm/pr-subscribers-clang-tools-extra

@llvm/pr-subscribers-clang-tidy

Author: None (higher-performance)

Changes

When you have code like co_await foo(), foo may know for a fact that it is returning an object that is safe to hold a mutex across. There is currently no way to exempt these. This PR adds support for such exemptions.


Full diff: https://github.com/llvm/llvm-project/pull/167778.diff

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp (+8-2)
  • (modified) clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h (+3)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp (+8-1)
diff --git a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp
index a2d3d3ff1512d..a7b74944690b4 100644
--- a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp
@@ -73,7 +73,9 @@ CoroutineHostileRAIICheck::CoroutineHostileRAIICheck(StringRef Name,
       RAIITypesList(utils::options::parseStringList(
           Options.get("RAIITypesList", "std::lock_guard;std::scoped_lock"))),
       AllowedAwaitablesList(utils::options::parseStringList(
-          Options.get("AllowedAwaitablesList", ""))) {}
+          Options.get("AllowedAwaitablesList", ""))),
+      AllowedCallees(
+          utils::options::parseStringList(Options.get("AllowedCallees", ""))) {}
 
 void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) {
   // A suspension happens with co_await or co_yield.
@@ -81,7 +83,9 @@ void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) {
                                     hasAttr(attr::Kind::ScopedLockable)))))
                             .bind("scoped-lockable");
   auto OtherRAII = varDecl(typeWithNameIn(RAIITypesList)).bind("raii");
-  auto AllowedSuspend = awaitable(typeWithNameIn(AllowedAwaitablesList));
+  auto AllowedSuspend = awaitable(
+      anyOf(typeWithNameIn(AllowedAwaitablesList),
+            callExpr(callee(functionDecl(hasAnyName(AllowedCallees))))));
   Finder->addMatcher(
       expr(anyOf(coawaitExpr(unless(AllowedSuspend)), coyieldExpr()),
            forEachPrevStmt(
@@ -111,5 +115,7 @@ void CoroutineHostileRAIICheck::storeOptions(
                 utils::options::serializeStringList(RAIITypesList));
   Options.store(Opts, "SafeAwaitableList",
                 utils::options::serializeStringList(AllowedAwaitablesList));
+  Options.store(Opts, "SafeCallees",
+                utils::options::serializeStringList(AllowedCallees));
 }
 } // namespace clang::tidy::misc
diff --git a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h
index 768b62ef07f90..12ad1b1e0e220 100644
--- a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h
+++ b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h
@@ -46,6 +46,9 @@ class CoroutineHostileRAIICheck : public ClangTidyCheck {
   // List of fully qualified awaitable types which are considered safe to
   // co_await.
   std::vector<StringRef> AllowedAwaitablesList;
+  // List of callees whose return values are considered safe to directly
+  // co_await.
+  std::vector<StringRef> AllowedCallees;
 };
 
 } // namespace clang::tidy::misc
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp
index c23c355dac1b2..ec6ddec56e1f2 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp
@@ -1,7 +1,8 @@
 // RUN: %check_clang_tidy -std=c++20 %s misc-coroutine-hostile-raii %t \
 // RUN:   -config="{CheckOptions: {\
 // RUN:             misc-coroutine-hostile-raii.RAIITypesList: 'my::Mutex; ::my::other::Mutex', \
-// RUN:             misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable' \
+// RUN:             misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable', \
+// RUN:             misc-coroutine-hostile-raii.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod' \
 // RUN:             }}"
 
 namespace std {
@@ -145,12 +146,18 @@ namespace safe {
   void await_suspend(std::coroutine_handle<>) noexcept {}
   void await_resume() noexcept {}
 };
+  std::suspend_always AwaitFunc();
+  struct Obj {
+    std::suspend_always AwaitMethod();
+  };
 } // namespace safe
 ReturnObject RAIISafeSuspendTest() {
   absl::Mutex a;
   co_await safe::awaitable{};
   using other = safe::awaitable;
   co_await other{};
+  co_await safe::AwaitFunc();
+  co_await safe::Obj().AwaitMethod();
 } 
 
 // ================================================================================

Copy link
Contributor

@EugeneZelenko EugeneZelenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mention changes in documentation and Release Notes.

@usx95 usx95 added the coroutines C++20 coroutines label Nov 12, 2025 — with Graphite App
@higher-performance
Copy link
Contributor Author

Done, thanks.

@higher-performance higher-performance enabled auto-merge (squash) November 12, 2025 23:34
@higher-performance higher-performance merged commit 18d4da2 into llvm:main Nov 12, 2025
12 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Nov 13, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-5 while building clang-tools-extra at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/30855

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'lit :: verbosity.py' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 3
mkdir -p /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp
# executed command: mkdir -p /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp
# note: command had no output on stdout or stderr
# RUN: at line 7
not env -u FILECHECK_OPTS "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9" /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical Inputs/verbosity 2> /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt > /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 8
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS
# note: command had no output on stdout or stderr
# RUN: at line 9
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 43
not env -u FILECHECK_OPTS "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9" /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --succinct Inputs/verbosity 2> /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt > /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --succinct Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 44
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix SUCCINCT < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix SUCCINCT
# note: command had no output on stdout or stderr
# RUN: at line 45
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 71
not env -u FILECHECK_OPTS "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9" /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --verbose Inputs/verbosity 2> /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt > /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --verbose Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 72
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix VERBOSE < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix VERBOSE
# note: command had no output on stdout or stderr
# RUN: at line 73
FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt
# executed command: FileCheck /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 136
not env -u FILECHECK_OPTS "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9" /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --show-all Inputs/verbosity 2> /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stderr.txt > /Volumes/ExternalSSD/buildbot-root/aarch64-darwin/build/utils/lit/tests/Output/verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/utils/lit/lit.py -j1 --order=lexical --show-all Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 137
...

@higher-performance higher-performance deleted the coro-hostile branch November 13, 2025 00:08
@llvm-ci
Copy link
Collaborator

llvm-ci commented Nov 13, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-sie-win running on sie-win-worker while building clang-tools-extra at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/26284

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'lit :: verbosity.py' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 3
mkdir -p Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp
# executed command: mkdir -p 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp'
# note: command had no output on stdout or stderr
# RUN: at line 7
not env -u FILECHECK_OPTS "C:\Program Files\Python310\python.exe" Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py -j1 --order=lexical Inputs/verbosity 2> Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt > Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS 'C:\Program Files\Python310\python.exe' 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py' -j1 --order=lexical Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 8
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix NO-ARGS < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix NO-ARGS
# note: command had no output on stdout or stderr
# RUN: at line 9
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 43
not env -u FILECHECK_OPTS "C:\Program Files\Python310\python.exe" Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py -j1 --order=lexical --succinct Inputs/verbosity 2> Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt > Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS 'C:\Program Files\Python310\python.exe' 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py' -j1 --order=lexical --succinct Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 44
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix SUCCINCT < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix SUCCINCT
# note: command had no output on stdout or stderr
# RUN: at line 45
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 71
not env -u FILECHECK_OPTS "C:\Program Files\Python310\python.exe" Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py -j1 --order=lexical --verbose Inputs/verbosity 2> Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt > Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS 'C:\Program Files\Python310\python.exe' 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py' -j1 --order=lexical --verbose Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 72
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix VERBOSE < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix VERBOSE
# note: command had no output on stdout or stderr
# RUN: at line 73
FileCheck Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py --check-prefix NO-ARGS-ERR --implicit-check-not lit < Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt
# executed command: FileCheck 'Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\verbosity.py' --check-prefix NO-ARGS-ERR --implicit-check-not lit
# note: command had no output on stdout or stderr
# RUN: at line 136
not env -u FILECHECK_OPTS "C:\Program Files\Python310\python.exe" Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py -j1 --order=lexical --show-all Inputs/verbosity 2> Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stderr.txt > Z:\b\llvm-clang-x86_64-sie-win\build\utils\lit\tests\Output\verbosity.py.tmp/stdout.txt
# executed command: not env -u FILECHECK_OPTS 'C:\Program Files\Python310\python.exe' 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\llvm\utils\lit\lit.py' -j1 --order=lexical --show-all Inputs/verbosity
# note: command had no output on stdout or stderr
# RUN: at line 137
...

git-crd pushed a commit to git-crd/crd-llvm-project that referenced this pull request Nov 13, 2025
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.

5 participants