Compile-time check for existence of an enum member

Viewed 148

This question is rather theoretical, I don't have a real life example at hand, it's just somethig I had encountered a couple of times and wondered if there's a generic way to solve.

Let's say I have a program interfacing with a library that exposes an enum. Depending on the library version, some enum members may exist, and some may not. I want to compile conditional code based on their existence. I know there are other best-practices, like #if-ing on the library version. In some cases, however, it's cleanest and easiest to just check the existence of enums.

Some code I've seen follow this convention when declaring enums:

enum foo {
    foo_bar = 1
#define foo_bar foo_bar
    foo_baz = 2
#define foo_baz foo_baz
    ...
};

this lets me use #ifdef foo_XXX to check the existence of a member of enum foo. But it's not always available, of course.

Is there any way to test for the definition of a "name" in the current lexical scope? I'm specifically targeting enums but a more general answer is accepted as well :) I assume there's no "standard C" way to do so, thus GCC-only or clang-only solutions apply as well.

EDIT: After contemplating a bit on it, I implemented a small GCC "builtin" that I called __builtin_compile_time_ifdef. It accepts a name as astring and returns 1 if the name is defined. It works fine. The problem that remains is that in all constructs I know of that provide conditional evaluation (__builtin_choose_expr, _Generic), the non-evaluated branch is still checked for undeclared names. So if I want to use the name (and not just check for existence), I can't.

2 Answers

I've never heard of such a feature, and the GNU cpp manual doesn't describe anything of the sort. Indeed, in the description of #if, they explicitly say that enum constants are not recognized.

Moreover, such a feature would be contrary to the overall design scheme of the preprocessor. cpp is not supposed to attempt to parse its input as C; it only looks for preprocessor directives and macros to expand. Indeed, people often use cpp to preprocess code in other languages (e.g. assembly). If the preprocessor tried to recognize the enum keyword and parse its syntax, it would be likely to be horribly confused by other languages that might use the string enum in completely different ways, contrary to people's expectations. So I wouldn't think there's any chance that someone would have created what you're looking for.

This is a problem that people are expected to solve in other ways (which you mentioned in comments that you already know about).

For future reference, I wrote a PoC plugin demonstrating what I needed:

#include <stdio.h>

enum x {
    v1 = 1,
    // v2 = 2
};

void main(void) {
    enum x v1 = (enum x)__builtin_lookup_name("v1", (enum x)-1);
    enum x v2 = (enum x)__builtin_lookup_name("v2", (enum x)-1);

    printf("%d %d\n", v1, v2); // prints "1 -1"
}
Related