Skip to content

Commit 8d60e10

Browse files
committed
[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 #64483 Reviewed By: aaron.ballman, hokein Differential Revision: https://reviews.llvm.org/D157296
1 parent ec129c2 commit 8d60e10

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
318318
return ExprError();
319319
}
320320

321-
return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
321+
auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
322+
return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
322323
}
323324

324325
// See if return type is coroutine-handle and if so, invoke builtin coro-resume

clang/test/AST/Inputs/std-coroutine.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ template <typename Promise> struct coroutine_handle : coroutine_handle<> {
5555
};
5656

5757
struct suspend_always {
58-
bool await_ready() { return false; }
59-
void await_suspend(coroutine_handle<>) {}
60-
void await_resume() {}
58+
bool await_ready() noexcept { return false; }
59+
void await_suspend(coroutine_handle<>) noexcept {}
60+
void await_resume() noexcept {}
6161
};
6262

6363
struct suspend_never {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
2+
// RUN: -fsyntax-only -ast-dump | FileCheck %s
3+
4+
#include "Inputs/std-coroutine.h"
5+
6+
using namespace std;
7+
8+
struct Chat {
9+
struct promise_type {
10+
std::suspend_always initial_suspend() { return {}; }
11+
Chat get_return_object() {
12+
return std::coroutine_handle<promise_type>::from_promise(*this);
13+
}
14+
std::suspend_always yield_value(int m) { return {}; }
15+
std::suspend_always final_suspend() noexcept { return {}; }
16+
std::suspend_always return_value(int) { return {}; }
17+
void unhandled_exception() {}
18+
19+
auto await_transform(int s) {
20+
struct awaiter {
21+
promise_type *promise;
22+
bool await_ready() { return true; }
23+
int await_resume() { return promise->message; }
24+
void await_suspend(std::coroutine_handle<>) {}
25+
};
26+
27+
return awaiter{this};
28+
}
29+
int message;
30+
};
31+
32+
Chat(std::coroutine_handle<promise_type> promise);
33+
34+
std::coroutine_handle<promise_type> handle;
35+
};
36+
37+
Chat f(int s) {
38+
// CHECK: CoyieldExpr {{.*}} <col:3, col:12>
39+
// CHECK-NEXT: CXXMemberCallExpr {{.*}} <col:3, col:12> {{.*}}
40+
// CHECK-NEXT: MemberExpr {{.*}} <col:3> {{.*}}
41+
// CHECK-NEXT: DeclRefExpr {{.*}} <col:3> {{.*}}
42+
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:12> {{.*}}
43+
// CHECK-NEXT: DeclRefExpr {{.*}} <col:12> {{.*}}
44+
co_yield s;
45+
// CHECK: CoreturnStmt {{.*}} <line:{{.*}}:3, col:13>
46+
co_return s;
47+
// CHECK: CoawaitExpr {{.*}} <col:3, col:12> 'int'
48+
co_await s;
49+
}

0 commit comments

Comments
 (0)