Files
libakgl/tests/headers.c
Andrew Kesterson 57bf1c7649 Include actor.h from controller.h so the header compiles on its own
controller.h declares three handler pointers taking an akgl_Actor * and
included nothing that declares that type, so any translation unit reaching
for it before akgl/actor.h failed with "unknown type name 'akgl_Actor'".
src/controller.c never noticed because it includes akgl/game.h first, and
tests/controller.c carried a comment explaining the workaround.

Included rather than forward-declared: akgl_Actor is a typedef of a named
struct and repeating a typedef is C11, not C99. It closes no cycle --
actor.h reaches only types.h and character.h.

tests/headers.c is a whole suite for one #include on purpose. A second
#include after the first proves nothing about the second, because by then
the first has dragged its dependencies in; covering another header means
another file shaped like this one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 12:53:09 -04:00

38 lines
1.3 KiB
C

/**
* @file headers.c
* @brief Checks that a public header can be the first thing a caller includes.
*
* The assertion here is the compile, not anything main() does. `akgl/controller.h`
* declares its binding handlers as taking an `akgl_Actor *` and once did not
* declare that type, so every translation unit that reached for it before
* `akgl/actor.h` failed with "unknown type name 'akgl_Actor'". `src/controller.c`
* never noticed, because it includes `akgl/game.h` first.
*
* One header per file, deliberately. A second `#include` after the first proves
* nothing about the second: by then the first has already dragged its
* dependencies in. Covering another header means another file like this one.
*/
#include <akgl/controller.h>
#include <string.h>
int main(void)
{
akgl_Control control;
// Enough to require the akgl_Actor declaration to be complete rather than
// merely present: the handler signature names it, and a control map holds
// one by value.
memset(&control, 0x00, sizeof(akgl_Control));
control.key = SDLK_LEFT;
control.handler_on = &akgl_Actor_cmhf_left_on;
if ( control.handler_on == NULL ) {
return 1;
}
if ( sizeof(GAME_ControlMaps) != (sizeof(akgl_ControlMap) * AKGL_MAX_CONTROL_MAPS) ) {
return 1;
}
return 0;
}