diff --git a/src/hx/cppia/Cppia.cpp b/src/hx/cppia/Cppia.cpp index 3c7dc2cec..ad37f40d8 100644 --- a/src/hx/cppia/Cppia.cpp +++ b/src/hx/cppia/Cppia.cpp @@ -439,7 +439,7 @@ struct BlockExpr : public CppiaExpr return; CppiaExpr **e = &expressions[0]; CppiaExpr **end = e+expressions.size(); - for(;ebreakContReturn;e++) + for(;ebreakContReturn && !ctx->exception;e++) { CPPIA_STACK_LINE((*e)); (*e)->runVoid(ctx); @@ -800,8 +800,7 @@ struct CallFunExpr : public CppiaExpr { unsigned char *pointer = ctx->pointer; function->pushArgs(ctx,thisExpr?thisExpr->runObject(ctx):ctx->getThis(false),args); - if (ctx->breakContReturn) - return; + BCR_VCHECK; AutoStack save(ctx,pointer); ctx->runVoid(function); @@ -5948,7 +5947,7 @@ struct TVars : public CppiaVoidExpr { CppiaExpr **v = &vars[0]; CppiaExpr **end = v + vars.size(); - for(;vbreakContReturn;v++) + for(;vbreakContReturn && !ctx->exception;v++) (*v)->runVoid(ctx); } @@ -5998,8 +5997,14 @@ struct ForExpr : public CppiaVoidExpr while(hasNext()) { + if (ctx->exception) + return; var.set(ctx,getNext()); + if (ctx->exception) + return; loop->runVoid(ctx); + if (ctx->exception) + return; if (ctx->breakContReturn) { @@ -6045,6 +6050,9 @@ struct WhileExpr : public CppiaVoidExpr { loop->runVoid(ctx); + if (ctx->exception) + break; + if (ctx->breakContReturn) { if (ctx->breakContReturn & (bcrBreak|bcrReturn)) @@ -6053,7 +6061,7 @@ struct WhileExpr : public CppiaVoidExpr ctx->breakContReturn = 0; } - if (!condition->runInt(ctx) || ctx->breakContReturn) + if (!condition->runInt(ctx) || ctx->breakContReturn || ctx->exception) break; } ctx->breakContReturn &= ~bcrLoop; @@ -6338,30 +6346,38 @@ struct TryExpr : public CppiaVoidExpr } return this; } + + void handleException(CppiaCtx* ctx, Dynamic caught) { + //Class cls = caught.mPtr ? caught->__GetClass() : 0; + for(int i=0;iisClassOf(caught) ) + { + ctx->exception = nullptr; + HX_STACK_BEGIN_CATCH + c.var.set(ctx,caught); + c.body->runVoid(ctx); + return; + } + } + HX_STACK_DO_THROW(caught); + } + // TODO - return types... void runVoid(CppiaCtx *ctx) { try { body->runVoid(ctx); - BCR_VCHECK; } catch(Dynamic caught) { - //Class cls = caught.mPtr ? caught->__GetClass() : 0; - for(int i=0;iisClassOf(caught) ) - { - HX_STACK_BEGIN_CATCH - c.var.set(ctx,caught); - c.body->runVoid(ctx); - return; - } - } - HX_STACK_DO_THROW(caught); + handleException(ctx,caught); + return; } + if (ctx->exception) + handleException(ctx,ctx->exception); } #ifdef CPPIA_JIT diff --git a/src/hx/cppia/Cppia.h b/src/hx/cppia/Cppia.h index 0cdb7207b..b8361537c 100644 --- a/src/hx/cppia/Cppia.h +++ b/src/hx/cppia/Cppia.h @@ -834,9 +834,9 @@ struct BCRReturn }; -#define BCR_CHECK if (ctx->breakContReturn) return BCRReturn(); +#define BCR_CHECK if (ctx->breakContReturn || ctx->exception) return BCRReturn(); #define BCR_CHECK_RET(x) if (ctx->breakContReturn) return x; -#define BCR_VCHECK if (ctx->breakContReturn) return; +#define BCR_VCHECK if (ctx->breakContReturn || ctx->exception) return; diff --git a/test/cppia/Client.hx b/test/cppia/Client.hx index 85a8b274a..f74a2a0d2 100644 --- a/test/cppia/Client.hx +++ b/test/cppia/Client.hx @@ -159,6 +159,26 @@ class Client return; } + switch LocalFunctionExceptions.testLocalCallingStatic() { + case Error(message): + Common.status = 'Failed test for throw in static called by local: ' + message; + return; + default: + } + + switch LocalFunctionExceptions.testCatchWithinLocal() { + case Error(message): + Common.status = 'Failed test for catch in local function: ' + message; + return; + default: + } + + switch LocalFunctionExceptions.testCatchFromLocal() { + case Error(message): + Common.status = 'Failed test for catching exception from local function: ' + message; + return; + default: + } final extending = new ClientExtendedExtendedRoot(); diff --git a/test/cppia/LocalFunctionExceptions.hx b/test/cppia/LocalFunctionExceptions.hx new file mode 100644 index 000000000..3caae76bc --- /dev/null +++ b/test/cppia/LocalFunctionExceptions.hx @@ -0,0 +1,68 @@ +enum Status { + Ok; + Error(message:String); +} + +class LocalFunctionExceptions { + static function staticFunction() { + throw 'Thrown from static'; + } + + public static function testLocalCallingStatic():Status { + function localFunction() { + staticFunction(); + throw 'Thrown from local'; + } + + try { + localFunction(); + } catch (e:String) { + if (e == 'Thrown from static') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call"); + } + } + + return Error("No exception caught"); + } + + public static function testCatchWithinLocal():Status { + function localFunction() { + try { + staticFunction(); + } catch (e:String) { + if (e == 'Thrown from static') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call"); + } + } + return Error("Exception from static function not caught"); + } + + return try { + localFunction(); + } catch (e) { + Error('Exception leaked from local function: $e'); + }; + } + + public static function testCatchFromLocal():Status { + function localFunction() { + throw 'Thrown from local'; + } + + try { + localFunction(); + } catch (e:String) { + if (e == 'Thrown from local') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call"); + } + } + + return Error("No exception caught"); + } +}