Using the C preprocessor to determine current scope?

clang, global-variables, nested-function, scope, static-variables

Solution

#define SCOPE_CHOOSER LOCAL || GLOBAL
#define CREATE_STATIC_VAR(Type, Name, DFLT) CREATE_STATIC_VAR_ ## SCOPE_CHOOSER(Type, Name, Dflt)

The biggest difficulty here is that the C preprocessor works by textual substitution, so even if you figured out how to get `SCOPE_CHOOSER` to do what you want, you'd end up with a macro expansion that looked something like

CREATE_STATIC_VAR_LOCAL || GLOBAL(Type, Name, Dflt);

There's no way to get the preprocessor to "constant-fold" macro expansions during substitution; the only time things are "folded" is when they appear in `#if` expressions. So your only hope (modulo slight handwaving) is to find a single construction that will work both inside and outside of a function.

Can you explain more about the ultimate goal here? I don't think you can load the variable's initial value with `__attribute__((constructor))`, but maybe there's a way to load the initial value the first time the function body is entered... or register all the addresses of these variables into a global list at compile-time and have a single `__attribute__((constructor))` function that traverses that list... or some mishmash of those approaches. I don't have any specific ideas in mind, but maybe if you give more information something will emerge.

EDIT: I don't think this helps you either, since it's not a preprocessor trick, but here is a constant-expression that will evaluate to 0 at function scope and 1 at global scope.

#define AT_GLOBAL_SCOPE __builtin_types_compatible_p(const char (*)[1], __typeof__(&__func__))

However, notice that I said "evaluate" and not "expand". These constructs are compile-time, not preprocessing-time.

Problem

I am developing an application in C / Objective-C (No C++ please, I already have a solution there), and I came across an interesting use case. Because clang does not support nested functions, my original approach will not work: ``` #define CREATE_STATIC_VAR(Type, Name, Dflt) static Type Name; __attribute__((constructor)) void static_ ## Type ## _ ## Name ## _init_var(void) { /* loading code here */ } ``` This code would compile fine with GCC, but because clang doesn't support nested functions, I get a compile error: Expected ';' at end of declaration. So, I found a solution that works for Clang on variables inside a function: ``` #define CREATE_STATIC_VAR_LOCAL(Type, Name, Dflt) static Type Name; ^{ /* loading code here */ }(); // anonymous block usage ``` However, I was wondering if there was a way to leverage macro concatenation to choose the appropriate one for the situation, something like: ``` #define CREATE_STATIC_VAR_GLOBAL(Type, Name, Dflt) static Type Name; __attribute__((constructor)) void static_ ## Type ## _ ## Name ## _init_var(void) { /* loading code here */ } #define CREATE_STATIC_VAR_LOCAL(Type, Name, Dflt) static Type Name; ^{ /* loading code here */ }(); // anonymous block usage #define SCOPE_CHOOSER LOCAL || GLOBAL #define CREATE_STATIC_VAR(Type, Name, DFLT) CREATE_STATIC_VAR_ ## SCOPE_CHOOSER(Type, Name, Dflt) ``` Obviously, the ending implementation doesn't have to be exactly that, but something similar will suffice. I have attempted to use `__builtin_constant_p` with `__func__`, but because `__func__` is not a compile-time constant, that wasn't working. I have also tried to use `__builtin_choose_expr`, but that doesn't appear to work at the global scope. Is there something else I am missing in the docs? Seems like this should be something fairly easy to do, and yet, I cannot seem to figure it out. Note: I am aware that I could simply type `CREATE_STATIC_VAR_GLOBAL` or `CREATE_STATIC_VAR_LOCAL` instead of messing with macro concatenation, but this is me attempting to push the limits of the compiler. I am also aware that I could use C++ and get this over with right away, but that's not my goal here.

Original source

Related problems