================
@@ -3746,10 +3757,134 @@ bool Compiler<Emitter>::VisitPredefinedExpr(const
PredefinedExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
- if (E->getSubExpr() && !this->discard(E->getSubExpr()))
+ const Expr *SubExpr = E->getSubExpr();
+ if (!Ctx.ExceptionsEnabled) {
+ if (SubExpr && !this->discard(SubExpr))
+ return false;
+ return this->emitInvalid(E);
+ }
+
+ if (!SubExpr)
+ return this->emitReThrow(E);
+
+ QualType ExceptionType = SubExpr->getType();
+ OptPrimType ExceptionT = classify(SubExpr);
+
+ const Descriptor *Desc;
+ if (ExceptionT)
+ Desc = P.createDescriptor(SubExpr, *ExceptionT);
+ else
+ Desc = P.createDescriptor(SubExpr, ExceptionType.getTypePtr(),
std::nullopt,
+ /*IsConst=*/false);
+
+ if (!this->emitAllocException(Desc, E))
+ return false;
+
+ if (ExceptionT) {
+ if (!this->visit(SubExpr))
+ return false;
+ if (!this->emitInit(*ExceptionT, E))
+ return false;
+ } else {
+ if (!this->visitInitializer(SubExpr))
+ return false;
+ }
+
+ OptPrimType T = classify(E->getSubExpr()->getType());
+ if (!this->emitSaveException(ExceptionType.getTypePtr(), T, E))
return false;
- return this->emitInvalid(E);
+ this->VarScope->destroyLocals();
+
+ return this->emitThrow(E);
+}
+
+template <class Emitter>
+bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
+ if (!Ctx.ExceptionsEnabled) {
+ // Ignore all handlers.
+ return this->visitStmt(S->getTryBlock());
+ }
+
+ unsigned NumHandlers = S->getNumHandlers();
+
+ // When an exception is thrown in the middle of a try{} block, we use this
+ // throw trap to pop all values from the stack that have been added during
+ // the try block before the throw.
+ if (!this->emitThrowTrap(S))
+ return false;
+
+ // For the try block, we record the bytecode offset before and
+ // after it. When an exception is thrown, we check if the offset
+ // at that point is between the start/end of the appropriate catch
+ // handler for this try block. If we find such a handler, we jump to it.
+ unsigned TryBlockStart = this->currentCodeSize();
+ {
+ const auto *TryBlock = cast<CompoundStmt>(S->getTryBlock());
+ if (!this->visitStmt(TryBlock))
+ return false;
+ }
+ unsigned TryBlockEnd = this->currentCodeSize();
+
+ // Jump after handlers if nothing was thrown.
+ LabelTy EndLabel = this->getLabel();
+ this->jump(EndLabel, S);
+
+ // Register and emit all handlers.
+ for (unsigned I = 0; I != NumHandlers; ++I) {
+ const CXXCatchStmt *Handler = S->getHandler(I);
+ const Stmt *HandlerBlock = Handler->getHandlerBlock();
+ const VarDecl *ExceptionDecl = Handler->getExceptionDecl();
+ QualType CatchType = Handler->getCaughtType();
+ UnsignedOrNone ExceptionDeclOffset = std::nullopt;
+
+ unsigned HandlerOffset = this->currentCodeSize();
+ if (ExceptionDecl) {
+ if (OptPrimType T = classify(CatchType)) {
+ unsigned LocalOffset = allocateLocalPrimitive(ExceptionDecl, *T,
+ /*IsConst=*/true);
+ if (CatchType->isReferenceType()) {
+ if (!this->emitGetPtrExceptionValue(S))
+ return false;
+ } else {
+ if (!this->emitGetExceptionValue(*T, S))
+ return false;
+ }
+ if (!this->emitSetLocal(*T, LocalOffset, S))
+ return false;
+ } else {
+ UnsignedOrNone LocalOffset = allocateLocal(ExceptionDecl, CatchType);
+ if (!LocalOffset)
+ return false;
+
+ if (!this->emitGetPtrLocal(*LocalOffset, Handler))
+ return false;
+ if (!this->emitGetPtrExceptionValue(Handler))
+ return false;
+ if (!this->emitMemcpy(Handler))
----------------
tbaederr wrote:
Yes :|
https://github.com/llvm/llvm-project/pull/189410
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits