diff --git a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp index a7b74944690b4..75693a0c563e9 100644 --- a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp @@ -67,6 +67,11 @@ static auto typeWithNameIn(const std::vector &Names) { hasCanonicalType(hasDeclaration(namedDecl(hasAnyName(Names))))); } +static auto functionWithNameIn(const std::vector &Names) { + auto Call = callExpr(callee(functionDecl(hasAnyName(Names)))); + return anyOf(expr(cxxBindTemporaryExpr(has(Call))), expr(Call)); +} + CoroutineHostileRAIICheck::CoroutineHostileRAIICheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), @@ -83,9 +88,8 @@ void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) { hasAttr(attr::Kind::ScopedLockable))))) .bind("scoped-lockable"); auto OtherRAII = varDecl(typeWithNameIn(RAIITypesList)).bind("raii"); - auto AllowedSuspend = awaitable( - anyOf(typeWithNameIn(AllowedAwaitablesList), - callExpr(callee(functionDecl(hasAnyName(AllowedCallees)))))); + auto AllowedSuspend = awaitable(anyOf(typeWithNameIn(AllowedAwaitablesList), + functionWithNameIn(AllowedCallees))); Finder->addMatcher( expr(anyOf(coawaitExpr(unless(AllowedSuspend)), coyieldExpr()), forEachPrevStmt( @@ -113,9 +117,9 @@ void CoroutineHostileRAIICheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "RAIITypesList", utils::options::serializeStringList(RAIITypesList)); - Options.store(Opts, "SafeAwaitableList", + Options.store(Opts, "AllowedAwaitablesList", utils::options::serializeStringList(AllowedAwaitablesList)); - Options.store(Opts, "SafeCallees", + Options.store(Opts, "AllowedCallees", utils::options::serializeStringList(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 ec6ddec56e1f2..dff73aeb7a5ee 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 @@ -2,7 +2,7 @@ // 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.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod' \ +// RUN: misc-coroutine-hostile-raii.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod; retExemptedAwaitable' \ // RUN: }}" namespace std { @@ -163,7 +163,10 @@ ReturnObject RAIISafeSuspendTest() { // ================================================================================ // Safe transformable awaitable // ================================================================================ -struct transformable { struct awaitable{}; }; +struct transformable { + struct awaitable{}; + struct unsafe_awaitable{}; +}; using alias_transformable_awaitable = transformable::awaitable; struct UseTransformAwaitable { struct promise_type { @@ -172,13 +175,18 @@ struct UseTransformAwaitable { std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() {} std::suspend_always await_transform(transformable::awaitable) { return {}; } + std::suspend_always await_transform(transformable::unsafe_awaitable) { + return {}; + } }; }; auto retAwaitable() { return transformable::awaitable{}; } +auto retExemptedAwaitable() { return transformable::unsafe_awaitable{}; } UseTransformAwaitable RAIISafeSuspendTest2() { absl::Mutex a; co_await retAwaitable(); + co_await retExemptedAwaitable(); co_await transformable::awaitable{}; co_await alias_transformable_awaitable{}; }