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 か。恐や恐や…