- 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
-------------------------------------------------
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 {
/// 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.
///
ModifiedNonNullParams.clear();
Blocks.clear();
ByrefBlockVars.clear();
+ AddrLabels.clear();
}
static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
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();
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() {
--- /dev/null
+// 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;
+}