diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | eval_intern.h | 27 |
2 files changed, 29 insertions, 4 deletions
@@ -1,3 +1,9 @@ +Mon Nov 4 10:08:17 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * eval_intern.h (TH_EXEC_TAG, TH_JUMP_TAG): get rid of undefined + behavior of setjmp() in rhs of assignment expression. + [ISO/IEC 9899:1999] 7.13.1.1 + Sun Nov 3 23:06:51 2013 Tanaka Akira <akr@fsij.org> * sample/test.rb: Make temporary file names unique. diff --git a/eval_intern.h b/eval_intern.h index 190ef9195c..b945848a7a 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -108,14 +108,33 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval #define PUSH_TAG() TH_PUSH_TAG(GET_THREAD()) #define POP_TAG() TH_POP_TAG() -#define TH_EXEC_TAG() ruby_setjmp(_th->tag->buf) +/* clear th->state, and return the value */ +static inline int +ruby_threadptr_tag_state(rb_thread_t *th) +{ + int state = th->state; + th->state = 0; + return state; +} + +NORETURN(static inline void ruby_threadptr_tag_jump(rb_thread_t *, int)); +static inline void +ruby_threadptr_tag_jump(rb_thread_t *th, int st) +{ + ruby_longjmp(th->tag->buf, (th->state = st)); +} + +/* + setjmp() in assignment expression rhs is undefined behavior + [ISO/IEC 9899:1999] 7.13.1.1 +*/ +#define TH_EXEC_TAG() \ + (ruby_setjmp(_th->tag->buf) ? ruby_threadptr_tag_state(_th) : 0) #define EXEC_TAG() \ TH_EXEC_TAG() -#define TH_JUMP_TAG(th, st) do { \ - ruby_longjmp((th)->tag->buf,(st)); \ -} while (0) +#define TH_JUMP_TAG(th, st) ruby_threadptr_tag_jump(th, st) #define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), (st)) |