#include #include // Proof of concept for resumption exception handling. // Names, checks promises and so on all would have to be improved. struct resume_group; // Stackwise information (global for single stack) struct code_stack_data { struct resume_group * top_resume; struct resume_group * current_resume; } stack = {NULL, NULL}; // private exception header begin ============================================ struct resume_group { struct resume_group * next; bool (*try_to_handle)(int); }; void __resume_group_dtor(struct resume_group * this) { stack.top_resume = this->next; } void __cfa_eh__throw_resume(int except) { struct resume_group * original_head = stack.current_resume; struct resume_group * current = (original_head) ? original_head->next : stack.top_resume; for ( ; current ; current = current->next) { stack.current_resume = current; if (current->try_to_handle(except)) { stack.current_resume = original_head; return; } } printf("Unhandled exception %d\n", except); } // private exception header end ============================================== // Set up of unwind checker type. struct type_raii_t { char * msg; }; void dtor( struct type_raii_t * this ) { printf("%s\n", this->msg); } #define raii_t __attribute__((cleanup(dtor))) struct type_raii_t void bar() { raii_t a = { "Bar dtor" }; __cfa_eh__throw_resume( 3 ); } void foo() { raii_t a = { "Foo dtor" }; { bool foo_catch_resume(int exception_id) { if (exception_id == 3) { printf("Exception caught\n"); return true; } return false; } struct resume_group __attribute__((cleanup(__resume_group_dtor))) foo_try_resume = {stack.top_resume, foo_catch_resume}; stack.top_resume = &foo_try_resume; { raii_t b = { "Foo try dtor" }; bar(); printf("Called bar successfully\n"); } } printf( "Foo exited normally\n" ); } // Not in main.cfa void foe() { raii_t a = { "Foe dtor" }; printf("Foe throws\n"); __cfa_eh__throw_resume( 4 ); printf("Foe exits normally\n"); } void fy() { raii_t a = { "Fy dtor" }; { bool fy_catch_resume(int exception_id) { if (4 == exception_id) { printf("Rethrow in fy\n"); __cfa_eh__throw_resume(exception_id); return true; } return false; } struct resume_group __attribute__((cleanup(__resume_group_dtor))) fy_try_resume = {stack.top_resume, fy_catch_resume}; stack.top_resume = &fy_try_resume; { raii_t b = { "Fy try dtor" }; foe(); } } printf("Fy exits normally\n"); } void fee() { raii_t a = { "Fee dtor" }; { bool fee_catch_resume(int exception_id) { if (4 == exception_id) { printf("fee caught exception\n"); return true; } return false; } struct resume_group __attribute__((cleanup(__resume_group_dtor))) fee_try_resume = {stack.top_resume, fee_catch_resume}; stack.top_resume = &fee_try_resume; { raii_t b = { "Fee try dtor" }; fy(); } } printf("Fee exits normally\n"); } // End not in main.cfa int main() { raii_t a = { "Main dtor" }; foo(); fee(); printf("End of program reached\n"); }