[clang] 616c806 - [C++20] [Coroutines] Handle function-try-block in SemaCoroutine

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 6 00:11:56 PDT 2023


Author: Chuanqi Xu
Date: 2023-04-06T15:11:34+08:00
New Revision: 616c8067071316a9e17524b14b3ab0e04a511e71

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

LOG: [C++20] [Coroutines] Handle function-try-block in SemaCoroutine

In https://reviews.llvm.org/D146758, we handled the rare case that the
coroutine has a function-try-block. But it will be better to handle it
in the Sema part. This patch handles the preprocess.

Added: 
    

Modified: 
    clang/include/clang/AST/StmtCXX.h
    clang/lib/CodeGen/CGCoroutine.cpp
    clang/lib/Sema/SemaCoroutine.cpp
    clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/StmtCXX.h b/clang/include/clang/AST/StmtCXX.h
index 288ffc28f40ee..60fc3f3a63f49 100644
--- a/clang/include/clang/AST/StmtCXX.h
+++ b/clang/include/clang/AST/StmtCXX.h
@@ -375,9 +375,10 @@ class CoroutineBodyStmt final
   }
 
   /// Retrieve the body of the coroutine as written. This will be either
-  /// a CompoundStmt or a TryStmt.
-  Stmt *getBody() const {
-    return getStoredStmts()[SubStmt::Body];
+  /// a CompoundStmt. If the coroutine is in function-try-block, we will
+  /// wrap the CXXTryStmt into a CompoundStmt to keep consistency.
+  CompoundStmt *getBody() const {
+    return cast<CompoundStmt>(getStoredStmts()[SubStmt::Body]);
   }
 
   Stmt *getPromiseDeclStmt() const {

diff  --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index 90ab82ed88a11..da3da5e600104 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -593,18 +593,6 @@ static void emitBodyAndFallthrough(CodeGenFunction &CGF,
       CGF.EmitStmt(OnFallthrough);
 }
 
-static CompoundStmt *CoroutineStmtBuilder(ASTContext &Context,
-                                          const CoroutineBodyStmt &S) {
-  Stmt *Stmt = S.getBody();
-  if (CompoundStmt *Body = dyn_cast<CompoundStmt>(Stmt))
-    return Body;
-  // We are about to create a `CXXTryStmt` which requires a `CompoundStmt`.
-  // If the function body is not a `CompoundStmt` yet then we have to create
-  // a new one. This happens for cases like the "function-try-block" syntax.
-  return CompoundStmt::Create(Context, {Stmt}, FPOptionsOverride(),
-                              SourceLocation(), SourceLocation());
-}
-
 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
   auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
   auto &TI = CGM.getContext().getTargetInfo();
@@ -733,8 +721,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
       auto Loc = S.getBeginLoc();
       CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr,
                          CurCoro.Data->ExceptionHandler);
-      CompoundStmt *Body = CoroutineStmtBuilder(getContext(), S);
-      auto *TryStmt = CXXTryStmt::Create(getContext(), Loc, Body, &Catch);
+      auto *TryStmt =
+          CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch);
 
       EnterCXXTryStmt(*TryStmt);
       emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock());

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index e87f2a78e2394..deb67337a2aec 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1137,6 +1137,18 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
   Body = CoroutineBodyStmt::Create(Context, Builder);
 }
 
+static CompoundStmt *buildCoroutineBody(Stmt *Body, ASTContext &Context) {
+  if (auto *CS = dyn_cast<CompoundStmt>(Body))
+    return CS;
+
+  // The body of the coroutine may be a try statement if it is in
+  // 'function-try-block' syntax. Here we wrap it into a compound
+  // statement for consistency.
+  assert(isa<CXXTryStmt>(Body) && "Unimaged coroutine body type");
+  return CompoundStmt::Create(Context, {Body}, FPOptionsOverride(),
+                              SourceLocation(), SourceLocation());
+}
+
 CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
                                            sema::FunctionScopeInfo &Fn,
                                            Stmt *Body)
@@ -1144,7 +1156,7 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
       IsPromiseDependentType(
           !Fn.CoroutinePromise ||
           Fn.CoroutinePromise->getType()->isDependentType()) {
-  this->Body = Body;
+  this->Body = buildCoroutineBody(Body, S.getASTContext());
 
   for (auto KV : Fn.CoroutineParameterMoves)
     this->ParamMovesVector.push_back(KV.second);

diff  --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index e6d2bb46dfcd3..89954711804aa 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -717,8 +717,8 @@ void coro() try {
 )cpp";
   EXPECT_TRUE(matchesConditionally(
       CoroWithTryCatchDeclCode,
-      coroutineBodyStmt(hasBody(cxxTryStmt(has(compoundStmt(has(
-          declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))),
+      coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(
+          declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),
       true, {"-std=c++20", "-I/"}, M));
 }
 


        


More information about the cfe-commits mailing list