Skip to content

Commit cc526e3

Browse files
committed
[C++20] [Coroutines] Disable to take the address of labels in coroutines
Closing llvm/llvm-project#56436 We can't support the GNU address of label extension in coroutines well in current architecture. Since the coroutines are going to split into pieces in the middle end so the address of labels are ambiguous that time. To avoid any further misunderstanding, we try to emit an error here. Differential Revision: https://reviews.llvm.org/D131938
1 parent ae53c7f commit cc526e3

File tree

7 files changed

+92
-2
lines changed

7 files changed

+92
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ Improvements to Clang's diagnostics
452452
- Add ``-Wreturn-local-addr``, a GCC alias for ``-Wreturn-stack-address``.
453453
- Clang now suppresses ``-Wlogical-op-parentheses`` on ``(x && a || b)`` and ``(a || b && x)``
454454
only when ``x`` is a string literal.
455+
- Clang will now reject the GNU extension address of label in coroutines explicitly.
456+
This fixes `Issue 56436 <https://github.com/llvm/llvm-project/issues/56436>`_.
455457

456458
Non-comprehensive list of changes in this release
457459
-------------------------------------------------

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11360,6 +11360,9 @@ def warn_non_aligned_allocation_function : Warning <
1136011360
def err_conflicting_aligned_options : Error <
1136111361
"conflicting option '-fcoro-aligned-allocation' and '-fno-aligned-allocation'"
1136211362
>;
11363+
def err_coro_invalid_addr_of_label : Error<
11364+
"the GNU address of label extension is not allowed in coroutines."
11365+
>;
1136311366
} // end of coroutines issue category
1136411367

1136511368
let CategoryName = "Documentation Issue" in {

clang/include/clang/Sema/ScopeInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ class FunctionScopeInfo {
233233
/// modified in the function.
234234
llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
235235

236+
/// The set of GNU address of label extension "&&label".
237+
llvm::SmallVector<AddrLabelExpr *, 4> AddrLabels;
238+
236239
public:
237240
/// Represents a simple identification of a weak object.
238241
///

clang/lib/Sema/ScopeInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ void FunctionScopeInfo::Clear() {
5656
ModifiedNonNullParams.clear();
5757
Blocks.clear();
5858
ByrefBlockVars.clear();
59+
AddrLabels.clear();
5960
}
6061

6162
static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,12 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
11251125
Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
11261126
<< Fn->getFirstCoroutineStmtKeyword();
11271127
}
1128+
1129+
// Coroutines will get splitted into pieces. The GNU address of label
1130+
// extension wouldn't be meaningful in coroutines.
1131+
for (AddrLabelExpr *ALE : Fn->AddrLabels)
1132+
Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
1133+
11281134
CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
11291135
if (Builder.isInvalid() || !Builder.buildStatements())
11301136
return FD->setInvalidDecl();

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16105,8 +16105,13 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
1610516105
LabelDecl *TheDecl) {
1610616106
TheDecl->markUsed(Context);
1610716107
// Create the AST node. The address of a label always has type 'void*'.
16108-
return new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
16109-
Context.getPointerType(Context.VoidTy));
16108+
auto *Res = new (Context) AddrLabelExpr(
16109+
OpLoc, LabLoc, TheDecl, Context.getPointerType(Context.VoidTy));
16110+
16111+
if (getCurFunction())
16112+
getCurFunction()->AddrLabels.push_back(Res);
16113+
16114+
return Res;
1611016115
}
1611116116

1611216117
void Sema::ActOnStartStmtExpr() {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2+
3+
#include "Inputs/std-coroutine.h"
4+
5+
struct resumable {
6+
struct promise_type {
7+
resumable get_return_object() { return {}; }
8+
auto initial_suspend() { return std::suspend_always(); }
9+
auto final_suspend() noexcept { return std::suspend_always(); }
10+
void unhandled_exception() {}
11+
void return_void(){};
12+
};
13+
};
14+
15+
resumable f1(int &out, int *inst) {
16+
static void* dispatch_table[] = {&&inc, // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
17+
&&suspend, // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
18+
&&stop}; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
19+
#define DISPATCH() goto *dispatch_table[*inst++]
20+
inc:
21+
out++;
22+
DISPATCH();
23+
24+
suspend:
25+
co_await std::suspend_always{};
26+
DISPATCH();
27+
28+
stop:
29+
co_return;
30+
}
31+
32+
resumable f2(int &out, int *inst) {
33+
void* dispatch_table[] = {nullptr, nullptr, nullptr};
34+
dispatch_table[0] = &&inc; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
35+
dispatch_table[1] = &&suspend; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
36+
dispatch_table[2] = &&stop; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
37+
#define DISPATCH() goto *dispatch_table[*inst++]
38+
inc:
39+
out++;
40+
DISPATCH();
41+
42+
suspend:
43+
co_await std::suspend_always{};
44+
DISPATCH();
45+
46+
stop:
47+
co_return;
48+
}
49+
50+
resumable f3(int &out, int *inst) {
51+
void* dispatch_table[] = {nullptr, nullptr, nullptr};
52+
[&]() -> resumable {
53+
dispatch_table[0] = &&inc; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
54+
dispatch_table[1] = &&suspend; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
55+
dispatch_table[2] = &&stop; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
56+
#define DISPATCH() goto *dispatch_table[*inst++]
57+
inc:
58+
out++;
59+
DISPATCH();
60+
61+
suspend:
62+
co_await std::suspend_always{};
63+
DISPATCH();
64+
65+
stop:
66+
co_return;
67+
}();
68+
69+
co_return;
70+
}

0 commit comments

Comments
 (0)