[clang] 65b34b7 - [clang][pr55896]:co_yield/co_await thread-safety

Nathan Sidwell via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 9 04:42:27 PDT 2022


Author: Nathan Sidwell
Date: 2022-06-09T04:42:10-07:00
New Revision: 65b34b78f8dafbfd97836af3165e73c5b316c6b5

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

LOG: [clang][pr55896]:co_yield/co_await thread-safety

co_await and co_yield are represented by (classes derived from)
CoroutineSuspendExpr.  That has a number of child nodes, not all of
which are used for code-generation.  In particular the operand is
represented multiple times, and, like the problem with co_return
(55406) it must only be emitted in the CFG exactly once.  The operand
also appears inside OpaqueValueExprs, but that's ok.

This adds a visitor for SuspendExprs to emit the required children in
the correct order.  Note that this CFG is pre-coro xform.  We don't
have initial or final suspend points.

Reviewed By: bruno

Differential Revision: https://reviews.llvm.org/D127236

Added: 
    

Modified: 
    clang/lib/Analysis/CFG.cpp
    clang/test/SemaCXX/thread-safety-coro.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 1417b95aad93..8379e108fa27 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -597,6 +597,8 @@ class CFGBuilder {
   CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
   CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
   CFGBlock *VisitReturnStmt(Stmt *S);
+  CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
+                                      AddStmtChoice asc);
   CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
   CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
   CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
@@ -2297,6 +2299,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
     case Stmt::CoreturnStmtClass:
       return VisitReturnStmt(S);
 
+    case Stmt::CoyieldExprClass:
+    case Stmt::CoawaitExprClass:
+      return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
+
     case Stmt::SEHExceptStmtClass:
       return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
 
@@ -3152,6 +3158,27 @@ CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
   return B;
 }
 
+CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
+                                                AddStmtChoice asc) {
+  // We're modelling the pre-coro-xform CFG. Thus just evalate the various
+  // active components of the co_await or co_yield. Note we do not model the
+  // edge from the builtin_suspend to the exit node.
+  if (asc.alwaysAdd(*this, E)) {
+    autoCreateBlock();
+    appendStmt(Block, E);
+  }
+  CFGBlock *B = Block;
+  if (auto *R = Visit(E->getResumeExpr()))
+    B = R;
+  if (auto *R = Visit(E->getSuspendExpr()))
+    B = R;
+  if (auto *R = Visit(E->getReadyExpr()))
+    B = R;
+  if (auto *R = Visit(E->getCommonExpr()))
+    B = R;
+  return B;
+}
+
 CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
   // SEHExceptStmt are treated like labels, so they are the first statement in a
   // block.

diff  --git a/clang/test/SemaCXX/thread-safety-coro.cpp b/clang/test/SemaCXX/thread-safety-coro.cpp
index a500ad5435e4..9d40c3bf492a 100644
--- a/clang/test/SemaCXX/thread-safety-coro.cpp
+++ b/clang/test/SemaCXX/thread-safety-coro.cpp
@@ -38,10 +38,14 @@ class Task {
     Task get_return_object() noexcept;
     void unhandled_exception() noexcept;
     void return_value(int value) noexcept;
+
+    std::suspend_always yield_value(int value) noexcept;
   };
 };
 
 Task Foo() noexcept {
   // ICE'd
+  co_yield({ int frame = 0; 0; });
+  co_await({ int frame = 0; std::suspend_always(); });
   co_return({ int frame = 0; 0; });
 }


        


More information about the cfe-commits mailing list