I am defining a macro like the following and my goal is to complete the TODO
.
#define TEST(_expr, args...) \
do { \
\ // TODO _Static_assert to make sure __xyz is not declared
int __xyz = _expr; \
if (__xyz < 0) { \
\ // do some error handling stuff utilizing args and __xyz
} \
} while (0)
Macro runs _expr
(usually a function call) and does some error handling stuff in the case of failure. the stuff done utilize __xyz
and args...
. The corner case is that the developer using this macro might have the variable __xyz
defined on a higher scope and pass it as one of the args...
. Here is an example.
int foo(void);
int bar() {
int __xyz;
// .... some lines of code
TEST(foo(), x, y, z, __xyz);
// .... some more lines of code
return 0;
}
In this example, there would be a silent issue. I want to use _Static_assert
to make sure that no variable __xyz
is defined in any of the parent scopes. Basically, the macro TEST
would cause a compile-time error at the above function because __xyz
is defined at the beginning of the scope.
Theoretically, this should be possible because whether some word is declared/defined at some line is compile-time information.
Thank you all in advance!!
Although @aschepler's comment is practically adequate, it is not technically bulletproof. The OCD in me came up with this answer. We can use -Wshadow and treat it as an error in the macro
#define TEST(_expr, args...) \
do { \
_Pragma(GCC diagnostic push) \
_Pragma(GCC diagnostic error "-Wshadow") \
int TEST_MACRO_PV_xyz = _expr; \
_Pragma(GCC diagnostic pop) \
if (TEST_MACRO_PV_xyz < 0) { \
handle_and_propagate_error(TEST_MACRO_PV_xyz, ##args); \
} \
} while (0)
Note that for different compilers and different versions you need to enable/disable this error differently.