[clang-tools-extra] aba40fb - [coroutines] Do not check coroutine wrappers for skipped function bodies (#76729)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 3 03:41:14 PST 2024
Author: Utkarsh Saxena
Date: 2024-01-03T12:41:10+01:00
New Revision: aba40fb34a27f1d36b4b541bf04d414dca7d1c4c
URL: https://github.com/llvm/llvm-project/commit/aba40fb34a27f1d36b4b541bf04d414dca7d1c4c
DIFF: https://github.com/llvm/llvm-project/commit/aba40fb34a27f1d36b4b541bf04d414dca7d1c4c.diff
LOG: [coroutines] Do not check coroutine wrappers for skipped function bodies (#76729)
Without function bodies, we cannot tell whether a function is a
coroutine or not.
The analysis of coroutine wrappers is not useful when this information
is not available.
We therefore now skip this analysis for skipped function bodies.
Added:
Modified:
clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
clang/lib/Sema/SemaDecl.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 37643e5afa2304..f302dcf5f09db0 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -420,6 +420,62 @@ TEST(DiagnosticTest, MakeUnique) {
"no matching constructor for initialization of 'S'")));
}
+TEST(DiagnosticTest, CoroutineInHeader) {
+ StringRef CoroutineH = R"cpp(
+namespace std {
+template <class Ret, typename... T>
+struct coroutine_traits { using promise_type = typename Ret::promise_type; };
+
+template <class Promise = void>
+struct coroutine_handle {
+ static coroutine_handle from_address(void *) noexcept;
+ static coroutine_handle from_promise(Promise &promise);
+ constexpr void* address() const noexcept;
+};
+template <>
+struct coroutine_handle<void> {
+ template <class PromiseType>
+ coroutine_handle(coroutine_handle<PromiseType>) noexcept;
+ static coroutine_handle from_address(void *);
+ constexpr void* address() const noexcept;
+};
+
+struct awaitable {
+ bool await_ready() noexcept { return false; }
+ void await_suspend(coroutine_handle<>) noexcept {}
+ void await_resume() noexcept {}
+};
+} // namespace std
+ )cpp";
+
+ StringRef Header = R"cpp(
+#include "coroutine.h"
+template <typename T> struct [[clang::coro_return_type]] Gen {
+ struct promise_type {
+ Gen<T> get_return_object() {
+ return {};
+ }
+ std::awaitable initial_suspend();
+ std::awaitable final_suspend() noexcept;
+ void unhandled_exception();
+ void return_value(T t);
+ };
+};
+
+Gen<int> foo_coro(int b) { co_return b; }
+ )cpp";
+ Annotations Main(R"cpp(
+// error-ok
+#include "header.hpp"
+Gen<int> $[[bar_coro]](int b) { return foo_coro(b); }
+ )cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles["coroutine.h"] = std::string(CoroutineH);
+ TU.AdditionalFiles["header.hpp"] = std::string(Header);
+ TU.ExtraArgs.push_back("--std=c++20");
+ EXPECT_THAT(TU.build().getDiagnostics(), ElementsAre(hasRange(Main.range())));
+}
+
TEST(DiagnosticTest, MakeShared) {
// We usually miss diagnostics from header functions as we don't parse them.
// std::make_shared is only parsed when --parse-forwarding-functions is set
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ffbe317d559995..2de631941325fa 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15845,8 +15845,6 @@ static void diagnoseImplicitlyRetainedSelf(Sema &S) {
}
void Sema::CheckCoroutineWrapper(FunctionDecl *FD) {
- if (!FD)
- return;
RecordDecl *RD = FD->getReturnType()->getAsRecordDecl();
if (!RD || !RD->getUnderlyingDecl()->hasAttr<CoroReturnTypeAttr>())
return;
@@ -15869,7 +15867,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
- if (getLangOpts().Coroutines) {
+ // If we skip function body, we can't tell if a function is a coroutine.
+ if (getLangOpts().Coroutines && FD && !FD->hasSkippedBody()) {
if (FSI->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
else
More information about the cfe-commits
mailing list