-
Notifications
You must be signed in to change notification settings - Fork 184
Description
With the way the headers are designed we can create a scenario in which macros are defined as internal and prevent code from compiling. The root cause of this issue is impossible to decipher when the compiler fails. Only when running through just the preprocessor does the macro expansion issue become apparent.
example.c
#include <criterion/parameterized.h>
#include <criterion/criterion.h>
TestSuite(suite);
Test(suite, test)
{
}
gcc -c example.c -o example.o
example.c:7:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
7 | {
| ^
As we can see above it's not clear what the issue is when compiling.
gcc -c example.c -E | tail -n 11
internal
# 4 "example.c"
;
# 6 "example.c" 3 4
internal
# 7 "example.c"
{
}
However when we just run it through the preprocessor we can see that Test and TestSuite expand to internal. When going through the headers I noticed that #include <criterion/parameterized.h> includes #include <criterion/internal/test.h> which defines the real internal values of the macros in question here. Then when we get to #include <criterion/criterion.h> the macros Test and TestSuite get defined to internal values, but is unable to undef and redefine them again to their real internal values as #include <criterion/internal/test.h> has already been called earlier by #include <criterion/parameterized.h>.
So if we switch the order of includes we will no longer have a problem as shown below:
example_fixed.c
#include <criterion/criterion.h>
#include <criterion/parameterized.h>
TestSuite(suite);
Test(suite, test)
{
}
gcc -c example_fixed.c -o example_fixed.o && echo $?
0