[clang] 8d60e10 - [AST][Coroutine] Fix CoyieldExpr missing end loc

via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 9 17:05:01 PDT 2023


Author: dingfei
Date: 2023-08-10T08:02:32+08:00
New Revision: 8d60e10ce4bd428577ef441eb77b260ec3c14088

URL: https://github.com/llvm/llvm-project/commit/8d60e10ce4bd428577ef441eb77b260ec3c14088
DIFF: https://github.com/llvm/llvm-project/commit/8d60e10ce4bd428577ef441eb77b260ec3c14088.diff

LOG: [AST][Coroutine] Fix CoyieldExpr missing end loc

Coroutine co_yield/co_await/co_return are implemented by a serious of
synthesized CXXMemberExpr which have no lexical right-side parenthesis.

This fix uses the end loc of inner expr as the hypothetical RParenLoc of
CXXMemberExpr. For tools this might be an issue since the RParen token doesn't
exist (but has a valid location).

For future improvement, we might:
1. mark those inner (generated) exprs as implict (tools have chances to skip
   these nodes) (by @aaron.ballman)
2. borrow the idea from InitListExpr, there are two forms, one is for semantic,
   the other one is for syntactic, having these two split can make everything
   easier (by @hokein)

Fixes https://github.com/llvm/llvm-project/issues/64483

Reviewed By: aaron.ballman, hokein

Differential Revision: https://reviews.llvm.org/D157296

Added: 
    clang/test/AST/coroutine-co_yield-source-range.cpp

Modified: 
    clang/lib/Sema/SemaCoroutine.cpp
    clang/test/AST/Inputs/std-coroutine.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index deb67337a2aec0..c7d88f7784c187 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -318,7 +318,8 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
     return ExprError();
   }
 
-  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }
 
 // See if return type is coroutine-handle and if so, invoke builtin coro-resume

diff  --git a/clang/test/AST/Inputs/std-coroutine.h b/clang/test/AST/Inputs/std-coroutine.h
index c3ce6543ea5db3..12b0ad093656f7 100644
--- a/clang/test/AST/Inputs/std-coroutine.h
+++ b/clang/test/AST/Inputs/std-coroutine.h
@@ -55,9 +55,9 @@ template <typename Promise> struct coroutine_handle : coroutine_handle<> {
 };
 
 struct suspend_always {
-  bool await_ready() { return false; }
-  void await_suspend(coroutine_handle<>) {}
-  void await_resume() {}
+  bool await_ready() noexcept { return false; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
 };
 
 struct suspend_never {

diff  --git a/clang/test/AST/coroutine-co_yield-source-range.cpp b/clang/test/AST/coroutine-co_yield-source-range.cpp
new file mode 100644
index 00000000000000..c5766a6d718940
--- /dev/null
+++ b/clang/test/AST/coroutine-co_yield-source-range.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
+// RUN:    -fsyntax-only -ast-dump | FileCheck %s
+
+#include "Inputs/std-coroutine.h"
+
+using namespace std;
+
+struct Chat {
+  struct promise_type {
+    std::suspend_always initial_suspend() { return {}; }
+    Chat get_return_object() {
+      return std::coroutine_handle<promise_type>::from_promise(*this);
+    }
+    std::suspend_always yield_value(int m) { return {}; }
+    std::suspend_always final_suspend() noexcept { return {}; }
+    std::suspend_always return_value(int) { return {}; }
+    void unhandled_exception() {}
+
+    auto await_transform(int s) {
+      struct awaiter {
+        promise_type *promise;
+        bool await_ready() { return true; }
+        int await_resume() { return promise->message; }
+        void await_suspend(std::coroutine_handle<>) {}
+      };
+
+      return awaiter{this};
+    }
+    int message;
+  };
+
+  Chat(std::coroutine_handle<promise_type> promise);
+
+  std::coroutine_handle<promise_type> handle;
+};
+
+Chat f(int s)  {
+  // CHECK:      CoyieldExpr {{.*}} <col:3, col:12>
+  // CHECK-NEXT:   CXXMemberCallExpr {{.*}} <col:3, col:12> {{.*}}
+  // CHECK-NEXT:     MemberExpr {{.*}} <col:3> {{.*}}
+  // CHECK-NEXT:       DeclRefExpr {{.*}} <col:3> {{.*}}
+  // CHECK-NEXT:     ImplicitCastExpr {{.*}} <col:12> {{.*}}
+  // CHECK-NEXT:       DeclRefExpr {{.*}} <col:12> {{.*}}
+  co_yield s;
+  // CHECK:      CoreturnStmt {{.*}} <line:{{.*}}:3, col:13>
+  co_return s;
+  // CHECK:      CoawaitExpr {{.*}} <col:3, col:12> 'int'
+  co_await s;
+}


        


More information about the cfe-commits mailing list