[clang] [CIR] Simplify try-catch handling (PR #180857)

Henrich Lauko via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 10 23:58:39 PST 2026


================
@@ -280,224 +286,87 @@ mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
         scopeIP = builder.saveInsertionPoint();
       });
 
+  // Set personality function if not already set
+  auto funcOp = mlir::cast<cir::FuncOp>(curFn);
+  if (!funcOp.getPersonality())
+    funcOp.setPersonality(getPersonalityFn(cgm, EHPersonality::get(*this)));
+
   mlir::OpBuilder::InsertionGuard guard(builder);
   builder.restoreInsertionPoint(scopeIP);
-  mlir::LogicalResult result = emitCXXTryStmtUnderScope(s);
-  cir::YieldOp::create(builder, loc);
-  return result;
-}
 
-mlir::LogicalResult
-CIRGenFunction::emitCXXTryStmtUnderScope(const CXXTryStmt &s) {
   const llvm::Triple &t = getTarget().getTriple();
   // If we encounter a try statement on in an OpenMP target region offloaded to
   // a GPU, we treat it as a basic block.
   const bool isTargetDevice =
       (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
   if (isTargetDevice) {
-    cgm.errorNYI(
-        "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
+    cgm.errorNYI("emitCXXTryStmt: OpenMP target region offloaded to GPU");
     return mlir::success();
   }
 
-  unsigned numHandlers = s.getNumHandlers();
   mlir::Location tryLoc = getLoc(s.getBeginLoc());
-  mlir::OpBuilder::InsertPoint beginInsertTryBody;
+  SmallVector<mlir::Attribute> handlerAttrs;
 
-  bool hasCatchAll = false;
-  for (unsigned i = 0; i != numHandlers; ++i) {
-    hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;
-    if (hasCatchAll)
-      break;
-  }
+  CIRGenFunction::LexicalScope tryBodyScope{*this, tryLoc,
+                                            builder.getInsertionBlock()};
 
-  // Create the scope to represent only the C/C++ `try {}` part. However,
-  // don't populate right away. Create regions for the catch handlers,
-  // but don't emit the handler bodies yet. For now, only make sure the
-  // scope returns the exception information.
+  // Create the try operation.
+  mlir::LogicalResult tryRes = mlir::success();
   auto tryOp = cir::TryOp::create(
       builder, tryLoc,
       /*tryBuilder=*/
       [&](mlir::OpBuilder &b, mlir::Location loc) {
-        beginInsertTryBody = builder.saveInsertionPoint();
+        if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())
+          tryRes = mlir::failure();
+        cir::YieldOp::create(builder, loc);
       },
       /*handlersBuilder=*/
       [&](mlir::OpBuilder &b, mlir::Location loc,
           mlir::OperationState &result) {
         mlir::OpBuilder::InsertionGuard guard(b);
-
-        // We create an extra region for an unwind catch handler in case the
-        // catch-all handler doesn't exists
-        unsigned numRegionsToCreate =
-            hasCatchAll ? numHandlers : numHandlers + 1;
-
-        for (unsigned i = 0; i != numRegionsToCreate; ++i) {
+        bool hasCatchAll = false;
+        unsigned numHandlers = s.getNumHandlers();
+        for (unsigned i = 0; i != numHandlers; ++i) {
+          const CXXCatchStmt *catchStmt = s.getHandler(i);
+          if (!catchStmt->getExceptionDecl())
+            hasCatchAll = true;
+          mlir::Region *region = result.addRegion();
+          builder.createBlock(region);
+          addCatchHandlerAttr(region, catchStmt, handlerAttrs);
+        }
+        if (!hasCatchAll) {
+          // Create unwind region.
           mlir::Region *region = result.addRegion();
           builder.createBlock(region);
+          cir::ResumeOp::create(builder, loc);
+          handlerAttrs.push_back(cir::UnwindAttr::get(&getMLIRContext()));
         }
       });
 
-  // Finally emit the body for try/catch.
-  {
-    mlir::Location loc = tryOp.getLoc();
-    mlir::OpBuilder::InsertionGuard guard(builder);
-    builder.restoreInsertionPoint(beginInsertTryBody);
-    CIRGenFunction::LexicalScope tryScope{*this, loc,
-                                          builder.getInsertionBlock()};
-
-    tryScope.setAsTry(tryOp);
-
-    // Attach the basic blocks for the catch regions.
-    enterCXXTryStmt(s, tryOp);
-
-    // Emit the body for the `try {}` part.
-    {
-      mlir::OpBuilder::InsertionGuard guard(builder);
-      CIRGenFunction::LexicalScope tryBodyScope{*this, loc,
-                                                builder.getInsertionBlock()};
-      if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())
-        return mlir::failure();
-    }
+  if (tryRes.failed())
+    return mlir::failure();
 
-    // Emit catch clauses.
-    exitCXXTryStmt(s);
-  }
+  // Add final array of clauses into TryOp.
+  tryOp.setHandlerTypesAttr(
+      mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
 
-  return mlir::success();
-}
-
-/// Emit the structure of the dispatch block for the given catch scope.
-/// It is an invariant that the dispatch block already exists.
-static void emitCatchDispatchBlock(CIRGenFunction &cgf,
-                                   EHCatchScope &catchScope, cir::TryOp tryOp) {
-  if (EHPersonality::get(cgf).isWasmPersonality()) {
-    cgf.cgm.errorNYI("emitCatchDispatchBlock: WasmPersonality");
-    return;
-  }
-
-  if (EHPersonality::get(cgf).usesFuncletPads()) {
-    cgf.cgm.errorNYI("emitCatchDispatchBlock: usesFuncletPads");
-    return;
-  }
-
-  assert(std::find_if(catchScope.begin(), catchScope.end(),
-                      [](const auto &handler) {
-                        return !handler.type.rtti && handler.type.flags != 0;
-                      }) == catchScope.end() &&
-         "catch handler without type value or with not supported flags");
-
-  // There was no catch all handler, populate th EH regions for the
-  // enclosing scope.
-  if (!std::prev(catchScope.end())->isCatchAll())
-    cgf.populateEHCatchRegions(catchScope.getEnclosingEHScope(), tryOp);
-}
-
-void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
-                                     bool isFnTryBlock) {
+  // Emit the catch handler bodies. This has to be done after the try op is
+  // created and in place so that we can find the insertion point for the
+  // catch parameter alloca.
   unsigned numHandlers = s.getNumHandlers();
-  EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);
   for (unsigned i = 0; i != numHandlers; ++i) {
     const CXXCatchStmt *catchStmt = s.getHandler(i);
     mlir::Region *handler = &tryOp.getHandlerRegions()[i];
-    if (catchStmt->getExceptionDecl()) {
-      // FIXME: Dropping the reference type on the type into makes it
-      // impossible to correctly implement catch-by-reference
-      // semantics for pointers.  Unfortunately, this is what all
-      // existing compilers do, and it's not clear that the standard
-      // personality routine is capable of doing this right.  See C++ DR 388:
-      //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
-      Qualifiers caughtTypeQuals;
-      QualType caughtType = cgm.getASTContext().getUnqualifiedArrayType(
-          catchStmt->getCaughtType().getNonReferenceType(), caughtTypeQuals);
-      if (caughtType->isObjCObjectPointerType()) {
-        cgm.errorNYI("enterCXXTryStmt: caughtType ObjCObjectPointerType");
-        return;
-      }
-
-      CatchTypeInfo typeInfo = cgm.getCXXABI().getAddrOfCXXCatchHandlerType(
-          getLoc(catchStmt->getSourceRange()), caughtType,
-          catchStmt->getCaughtType());
-      catchScope->setHandler(i, typeInfo, handler, catchStmt);
-    } else {
-      // No exception decl indicates '...', a catch-all.
-      catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,
-                             s.getHandler(i));
-    }
-
-    // Under async exceptions, catch(...) needs to catch HW exception too
-    // Mark scope with SehTryBegin as a SEH __try scope
-    if (getLangOpts().EHAsynch) {
----------------
xlauko wrote:

This is no longer covered enywhere. I would expect we should still report `cgm.errorNYI("enterCXXTryStmt: EHAsynch")` somewhere?

https://github.com/llvm/llvm-project/pull/180857


More information about the cfe-commits mailing list