[clang] cc526e3 - [C++20] [Coroutines] Disable to take the address of labels in coroutines

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 16 19:36:02 PST 2023


Author: Chuanqi Xu
Date: 2023-01-17T11:35:32+08:00
New Revision: cc526e346debbaf1d2d32a59230288a4e98294c7

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

LOG: [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

Added: 
    clang/test/SemaCXX/addr-label-in-coroutines.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/ScopeInfo.h
    clang/lib/Sema/ScopeInfo.cpp
    clang/lib/Sema/SemaCoroutine.cpp
    clang/lib/Sema/SemaExpr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3bbab951e8a8c..de038fe2d13ec 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 -------------------------------------------------

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 02afb098b2395..50050e1885ae8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 {

diff  --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 363fbf454879d..65fa18fbb2903 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -233,6 +233,9 @@ class FunctionScopeInfo {
   /// 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.
   ///

diff  --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp
index f4dda9f194e78..e313052b3ab38 100644
--- a/clang/lib/Sema/ScopeInfo.cpp
+++ b/clang/lib/Sema/ScopeInfo.cpp
@@ -56,6 +56,7 @@ void FunctionScopeInfo::Clear() {
   ModifiedNonNullParams.clear();
   Blocks.clear();
   ByrefBlockVars.clear();
+  AddrLabels.clear();
 }
 
 static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 4cedd53a76785..79c08adb8fabc 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -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();

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d90c28432a6b6..be3a6bd321edc 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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() {

diff  --git a/clang/test/SemaCXX/addr-label-in-coroutines.cpp b/clang/test/SemaCXX/addr-label-in-coroutines.cpp
new file mode 100644
index 0000000000000..e37ee64134378
--- /dev/null
+++ b/clang/test/SemaCXX/addr-label-in-coroutines.cpp
@@ -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;
+}


        


More information about the cfe-commits mailing list