Skip to content

[coroutines] Do not check coroutine wrappers for skipped function bodies #76729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 3, 2024

Conversation

usx95
Copy link
Contributor

@usx95 usx95 commented Jan 2, 2024

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clangd clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 2, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clangd

Author: Utkarsh Saxena (usx95)

Changes

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.


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

2 Files Affected:

  • (modified) clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp (+54)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+1-1)
diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 37643e5afa2304..a5744cdd4cbe6f 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -420,6 +420,60 @@ 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(
+    #include "header.hpp"
+  )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(), IsEmpty());
+}
+
 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..8329c00f1d16c1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15845,7 +15845,7 @@ static void diagnoseImplicitlyRetainedSelf(Sema &S) {
 }
 
 void Sema::CheckCoroutineWrapper(FunctionDecl *FD) {
-  if (!FD)
+  if (!FD || FD->hasSkippedBody())
     return;
   RecordDecl *RD = FD->getReturnType()->getAsRecordDecl();
   if (!RD || !RD->getUnderlyingDecl()->hasAttr<CoroReturnTypeAttr>())

@usx95 usx95 requested a review from ilya-biryukov January 3, 2024 10:28
@usx95 usx95 merged commit aba40fb into llvm:main Jan 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category clangd
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants