Declaring anonymous struct in for loop, clang fails to compile

Viewed 1688

Code declaring anonymous structs in a for loop worked fine in gcc with -std=c99/gnu99

for (struct {int foo; int bar;} i = {0}; i.foo < 10; i.foo++);

However when I switch to clang instead I got the error:

error: declaration of non-local variable in 'for' loop

Why is this an error? Why would it allow some types (e.g. "int") but not others (e.g. struct {int foo;}) ? This seems inconsistent. Does clang fail to implement c99 correctly or is that code invalid c99 and gcc just happens to support it?

Does anyone know of a way to declare more than one type of variable in a for loop that is supported by clang? (This is useful for macros.)

EDIT:

Since people asked why this is useful I will paste some example code:

#define TREE_EACH(head, node, field, iterator) for ( \
    /* initialize */ \
    struct { \
        node* cur; \
        node* stack[((head)->th_root == 0? 0: (head)->th_root->field.avl_height) + 1]; \
        uint32_t stack_size; \
    } iterator = {.cur = (head)->th_root, .stack_size = 0}; \
    /* while */ \
    iterator.cur != 0; \
    /* iterate */ \
    (iterator.stack_size += (iterator.cur->field.avl_right != 0) \
        ? (iterator.stack[iterator.stack_size] = avl_right, 1) \
        : 0), \
    (iterator.cur = (iterator.cur->field.avl_left == 0) \
        ? iterator.cur->field.avl_left \
        : (iterator.stack_size > 0? (iterator.stack_size--, iterator.stack[iterator.stack_size]): 0)) \
)

This is a really convenient macro that I wrote which iterates over an AVL tree in depth-first order on the stack. Since declaring anonymous structs in the for loop is not allowed though I have to make the macro less intuitive to use. I could not possible out-source the declaration to the rest of the tree since it uses a variable length array.

5 Answers

I needed something similar for a small piece of code (https://github.com/kutoga/CArr) and there is a simple solution for your problem / code:

for (__auto_type i = ({
      struct {int foo; int bar;} _i = {0};
      _i;
    }); i.foo < 10; i.foo++)

The solution is to put the anonymous type in ({...}) and assign it to an __auto_type. That works fine with gcc and clang.

Related