mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
[C++20] [Coroutines] Disable to take the address of labels in coroutines
Closing https://github.com/llvm/llvm-project/issues/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
This commit is contained in:
parent
ae53c7f4a2
commit
cc526e346d
@ -452,6 +452,8 @@ Improvements to Clang's diagnostics
|
||||
- Add ``-Wreturn-local-addr``, a GCC alias for ``-Wreturn-stack-address``.
|
||||
- Clang now suppresses ``-Wlogical-op-parentheses`` on ``(x && a || b)`` and ``(a || b && x)``
|
||||
only when ``x`` is a string literal.
|
||||
- Clang will now reject the GNU extension address of label in coroutines explicitly.
|
||||
This fixes `Issue 56436 <https://github.com/llvm/llvm-project/issues/56436>`_.
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
-------------------------------------------------
|
||||
|
@ -11360,6 +11360,9 @@ def warn_non_aligned_allocation_function : Warning <
|
||||
def err_conflicting_aligned_options : Error <
|
||||
"conflicting option '-fcoro-aligned-allocation' and '-fno-aligned-allocation'"
|
||||
>;
|
||||
def err_coro_invalid_addr_of_label : Error<
|
||||
"the GNU address of label extension is not allowed in coroutines."
|
||||
>;
|
||||
} // end of coroutines issue category
|
||||
|
||||
let CategoryName = "Documentation Issue" in {
|
||||
|
@ -233,6 +233,9 @@ public:
|
||||
/// modified in the function.
|
||||
llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
|
||||
|
||||
/// The set of GNU address of label extension "&&label".
|
||||
llvm::SmallVector<AddrLabelExpr *, 4> AddrLabels;
|
||||
|
||||
public:
|
||||
/// Represents a simple identification of a weak object.
|
||||
///
|
||||
|
@ -56,6 +56,7 @@ void FunctionScopeInfo::Clear() {
|
||||
ModifiedNonNullParams.clear();
|
||||
Blocks.clear();
|
||||
ByrefBlockVars.clear();
|
||||
AddrLabels.clear();
|
||||
}
|
||||
|
||||
static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
|
||||
|
@ -1125,6 +1125,12 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
|
||||
Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
|
||||
<< Fn->getFirstCoroutineStmtKeyword();
|
||||
}
|
||||
|
||||
// Coroutines will get splitted into pieces. The GNU address of label
|
||||
// extension wouldn't be meaningful in coroutines.
|
||||
for (AddrLabelExpr *ALE : Fn->AddrLabels)
|
||||
Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
|
||||
|
||||
CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
|
||||
if (Builder.isInvalid() || !Builder.buildStatements())
|
||||
return FD->setInvalidDecl();
|
||||
|
@ -16105,8 +16105,13 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
|
||||
LabelDecl *TheDecl) {
|
||||
TheDecl->markUsed(Context);
|
||||
// Create the AST node. The address of a label always has type 'void*'.
|
||||
return new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
|
||||
Context.getPointerType(Context.VoidTy));
|
||||
auto *Res = new (Context) AddrLabelExpr(
|
||||
OpLoc, LabLoc, TheDecl, Context.getPointerType(Context.VoidTy));
|
||||
|
||||
if (getCurFunction())
|
||||
getCurFunction()->AddrLabels.push_back(Res);
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
void Sema::ActOnStartStmtExpr() {
|
||||
|
70
clang/test/SemaCXX/addr-label-in-coroutines.cpp
Normal file
70
clang/test/SemaCXX/addr-label-in-coroutines.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
|
||||
#include "Inputs/std-coroutine.h"
|
||||
|
||||
struct resumable {
|
||||
struct promise_type {
|
||||
resumable get_return_object() { return {}; }
|
||||
auto initial_suspend() { return std::suspend_always(); }
|
||||
auto final_suspend() noexcept { return std::suspend_always(); }
|
||||
void unhandled_exception() {}
|
||||
void return_void(){};
|
||||
};
|
||||
};
|
||||
|
||||
resumable f1(int &out, int *inst) {
|
||||
static void* dispatch_table[] = {&&inc, // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
&&suspend, // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
&&stop}; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
#define DISPATCH() goto *dispatch_table[*inst++]
|
||||
inc:
|
||||
out++;
|
||||
DISPATCH();
|
||||
|
||||
suspend:
|
||||
co_await std::suspend_always{};
|
||||
DISPATCH();
|
||||
|
||||
stop:
|
||||
co_return;
|
||||
}
|
||||
|
||||
resumable f2(int &out, int *inst) {
|
||||
void* dispatch_table[] = {nullptr, nullptr, nullptr};
|
||||
dispatch_table[0] = &&inc; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
dispatch_table[1] = &&suspend; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
dispatch_table[2] = &&stop; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
#define DISPATCH() goto *dispatch_table[*inst++]
|
||||
inc:
|
||||
out++;
|
||||
DISPATCH();
|
||||
|
||||
suspend:
|
||||
co_await std::suspend_always{};
|
||||
DISPATCH();
|
||||
|
||||
stop:
|
||||
co_return;
|
||||
}
|
||||
|
||||
resumable f3(int &out, int *inst) {
|
||||
void* dispatch_table[] = {nullptr, nullptr, nullptr};
|
||||
[&]() -> resumable {
|
||||
dispatch_table[0] = &&inc; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
dispatch_table[1] = &&suspend; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
dispatch_table[2] = &&stop; // expected-error {{the GNU address of label extension is not allowed in coroutines.}}
|
||||
#define DISPATCH() goto *dispatch_table[*inst++]
|
||||
inc:
|
||||
out++;
|
||||
DISPATCH();
|
||||
|
||||
suspend:
|
||||
co_await std::suspend_always{};
|
||||
DISPATCH();
|
||||
|
||||
stop:
|
||||
co_return;
|
||||
}();
|
||||
|
||||
co_return;
|
||||
}
|
Loading…
Reference in New Issue
Block a user