Handmade Hero»Forums»Code
30 posts
anonymous structs and Clang
Hi, folks.

I'm following along with the series, currently at day 042. Seeing as I have encountered anonymous unions/structs twice now, thought I'd ask.

I'm working on Mac OS X. I took this platform implementation as the base: https://github.com/vbo/handmadehero_osx_platform_layer. However, since I have zero knowledge of Objective-C and OS X API, I've rewritten the platform using SFML 2.4.

I am compiling using clang and the following piece of code gives errors:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef struct game_controller_input
{
    bool32 IsConnected;
    bool32 IsAnalog;
    real32 StickAverageX;
    real32 StickAverageY;

    union
    {
        game_button_state Buttons[12];
        struct
        {
            game_button_state MoveUp;
            game_button_state MoveDown;
            game_button_state MoveLeft;
            game_button_state MoveRight;

            game_button_state ActionUp;
            game_button_state ActionDown;
            game_button_state ActionLeft;
            game_button_state ActionRight;

            game_button_state LeftShoulder;
            game_button_state RightShoulder;

            game_button_state Back;
            game_button_state Start;

            game_button_state Terminator;
        };
    };
} game_controller_input;


Error message:
1
2
3
4
./src/game_platform.h:168:9: error: anonymous structs are a GNU extension [-Werror,-Wgnu-anonymous-struct]
        struct
        ^
./src/game_platform.h:168:9: error: anonymous types declared in an anonymous union are an extension [-Werror,-Wnested-anon-types]


Here's how I compile:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/usr/bin/clang++ \
    ./src/main.cpp \
    -g \
    -Wall -Werror \
    -pedantic \
    -Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations \
    -DGAME_INTERNAL=1 -DGAME_SLOW=1 \
    -lsfml-window -lsfml-system -lsfml-graphics -lsfml-audio -lstdc++ \
    -std=c++11 \
    -o ./build/game


I did some research but found no way to make this work. In the end I've had to assign names to the union and the structure, which makes the code explicit, but clunky:
1
osxProcessKeyUpDown(&keyboardController->game_buttons.button_states.MoveUp, isDown);

I also don't understand why the following vector definition works fine, which also an anonymous struct, if I understand correctly:
1
2
3
4
5
6
7
8
union v2
{
    struct
    {
        real32 X, Y;
    };
    real32 E[2];
};


I am an experienced engineer, but C is not my area of competence. One of the reasons I took up following this series is to increase and solidify my knowledge of C, maths, low-level programming and so on. My inability to figure this out is driving me crazy :)

I suspect that this is because I'm compiling in C++/11 but giving it up would mean abandoning features like function overload which are used in the code, right? Casey mentions on the recording of Day 42 that there were some reports on the issues with LLVM, but provides no solution.

Maybe he addresses the subject in later episodes, but I'd love to have it working right now before I move on.

I hope someone could shed some light on both subjects.

Thanks in advance.
Simon Anciaux
1341 posts
anonymous structs and Clang
Edited by Simon Anciaux on Reason: More infos
I don't know why it's not allowed and I don't have clang so I don't know if it'll work but did you try adding the compiler flags from the error message (-Wgnu-anonymous-struct and -Wnested-anon-types) ?

EDIT: According to the doc you need to type -Wno-gnu-anonymous-struct -Wno-nested-anon-types

Here is the doc and the warning flags
30 posts
anonymous structs and Clang
Well, now I feel really stupid for not thinking of the simplest answer. I tried adding the flags mentioned in the compiler's error message but they did not help, probably being negated by another flag such as pedantic. But your solution worked, thank you.

Still not sure though why the vector definition has worked regardless of the compiler flags. Guess it's time to hit the docs once more, the answers are probably there, I just have to find it.
Simon Anciaux
1341 posts
anonymous structs and Clang
I just compiled the following code with clang on arch linux (clang test.cpp -std=c++11 -pedantic) and I get a warning for the anonymous struct in the V2 union (plus the two others).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef struct Test {
    
    float zz;
    float zx;
    
    union {
        int x[ 10 ];
        struct { int a, b, c, d, e, f, g, h, i, j; };
    };
} Test;

union V2 {
    struct {
        float x, y;
    };
    float e[ 2 ];
};

int main( void ) {
    
    Test t;
    V2 v;
    
    return 0;
}


By the way, if you only need function overloading, you don't need C++11. Any version of C++ supports function overloading (But C doesn't). Casey doesn't use C++11 in handmade hero (I believe previous version is either C++98 or C++03) and he uses only a few features of C++.
Mārtiņš Možeiko
2562 posts / 2 projects
anonymous structs and Clang
Actually he uses C++11 features. At least two of them.

1) aggregate initialization - https://github.com/HandmadeHero/c...ter/code/win32_handmade.cpp#L2152
2) raw string literals - https://github.com/HandmadeHero/c...ter/code/handmade_opengl.cpp#L736
Simon Anciaux
1341 posts
anonymous structs and Clang
My bad. And now that I thing about it he also uses "round" that I think was not available before C++11.