Bug と言えるような言えないような
#define SCM_GC_PROTECTED_CALL_INTERNAL(exp_ret, ret_type, func, args) \ do { \ /* ensure that func is uninlined */ \ ret_type (*volatile fp)() = (ret_type (*)())&func; \ ← ScmObj *stack_start; \ \ if (0) exp_ret func args; /* compile-time type check */ \ stack_start = scm_gc_protect_stack(NULL); \ exp_ret (*fp)args; \ scm_gc_unprotect_stack(stack_start); \ } while (/* CONSTCOND */ 0)
すげーややこしいのな、これ。これに対して
void func(void); void (*fp)(void) = func; SCM_GC_PROTECTED_CALL(exp_ret, ret_type, fp, ());
とかすると fp の address を取って call するから、stack を実行しようとして死ぬ。Cast があるから型 check も効かない。
C99 rationale には "the C89 Committee saw no real harm" と書いてあるが、なかなか痛い corner case があるではないか。ここは *fp とするのが正着か、それとも &func の & を取る方がいいか。まあ後者の方が versatile か。恐や恐や…