← Back to context

Comment by Joker_vD

3 days ago

From what I can see in the codegen, defer is not implemented "properly": the deferred statements are only executed when the block exits normally; leaving the block via "return", "break", "continue" (including their labelled variants! those interact subtly with outer defers), or "goto" skips them entirely. Which, arguably, should not happen:

    var f = fopen("file.txt", "r");
    defer fclose(f);

    if fread(&ch, 1, 1, f) <= 0 { return -1; }
    return 0;

would not close file if it was empty. In fact, I am not sure how it works even for normal "return 0": it looks like the deferred statements are emitted after the "return", textually, so they only properly work in void-returning function and internal blocks.

Did you manage to compile this example?

  • Yes, actually:

        $ cat kekw.zc
        include <stdio.h>
        
        fn main() {
            var f = fopen("file.txt", "r");
            defer fclose(f);
        
            var ch: byte;
            if fread(&ch, 1, 1, f) <= 0 { return -1; }
            return 0;
        }
        $ ./zc --emit-c kekw.zc
        [zc] Compiling kekw.zc...
        $ tail -n 12 out.c
        int main()
        {
            {
            __auto_type f = fopen("file.txt", "r");
            uint8_t ch;
        if ((fread((&ch), 1, 1, f) <= 0))     {
            return (-1);
            }
            return 0;
        fclose(f);
            }
        }