2

I can't seem to pass the arguments to functions expecting different arguments (or to other _Generic macros which implement a subset of the types of the first one).

#define DEBUG_PRINT(x,...) _Generic((x),                    \
    debug_print_options *: DEBUG_PRINT_CUSTOM_TYPE(x,  __VA_ARGS__),    \
    default: DEBUG_PRINT_BASIC_TYPE(x, __VA_ARGS__))


#define DEBUG_PRINT_BASIC_TYPE(x,...) debug_print_printf_specifier((#x), (x), TYPE_TO_PRINTF_SPECIFIER(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))
#define DEBUG_PRINT_CUSTOM_TYPE(x,...) debug_print_custom_to_debug_string((#x), (x), GET_CREATE_DEBUG_STRING_FUNC(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))

gives a compile error:

debug_print.h:123:46: error: ‘_Generic’ selector of type ‘struct debug_print_options *’ is not compatible with any association

which makes it seem like it's getting evaluated at every branch. If I comment out the default it compiles.

Is there a way to work around this?

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
Roman A. Taycher
  • 18,619
  • 19
  • 86
  • 141
  • Also if each branch is evaluated, why??? – Roman A. Taycher Mar 20 '15 at 06:57
  • possible duplicate of [Incompatible pointer types passing in \_Generic macro](http://stackoverflow.com/questions/24743520/incompatible-pointer-types-passing-in-generic-macro), and to answer your "why" question: this is the same if you have something like `if(0) something; else other;` here also all branches must be valid. See that as a feature, potentially all branches could be active for some platform so better check them syntactically. – Jens Gustedt Mar 20 '15 at 07:39
  • @JensGustedt : I truly believe the C WG14 committee should improve _Generic with a new behaviour that prevents from requiring valid evaluation of unselected branches, considering that the selection is static rather than dynamic. The current _Generic causes tons of trouble because of that very unfortunate decision. I have to disable compiler warnings just for _Generic expressions because of that (or embed the code in inline functions: absurd overkill just because of _Generic not having a proper design). IMHO, _Generic is a very needed feature, but very poorly designed. – cesss Aug 28 '22 at 09:38
  • @cesss, the design is perhaps not what you expect, but it is proper and there are good reasons to have it as it is. Formulating in standardeze what you'd expect to have if the other branches are not valid C is not trivial at all. The general idea is that if you have difficulties with that as it is, you should perhaps factorize the different parts into inline functions and have the generic expression just return one of these functions. Usually optimizers are good enough to optimize such code seamlessly. – Jens Gustedt Aug 29 '22 at 18:59

1 Answers1

4

Your compiler error is not comming from the macros themselves, but from some invocation of them. So, it would help if you posted the invocation that is causing the error. That being said, I will address what seem to be your general questions on _Generic expressions.

The standard says the following (6.5.1.1, under 'semantics'):

The controlling expression of a generic selection is not evaluated. If a generic selection has a generic association with a type name that is compatible with the type of the controlling expression, then the result expression of the generic selection is the expression in that generic association. Otherwise, the result expression of the generic selection is the expression in the default generic association. None of the expressions from any other generic association of the generic selection is evaluated.

So, in answer to your comment add on to your question, no, only the selected branch is evaluated.

_Generic expressions are expressions, not macros. A macro does not need to have proper syntax. It does not even need to be parenthetically balanced. The only think a macro needs to do is expand into valid code each time it is used. Expressions are different. They need to match the syntax of the language.

In the case of a _Generic expression, the syntax of each item can be any valid C expression that does not have a comma operator that is not parenthetically (or conditional operator) shielded. If your _Generic meets this criteria, and the selected statement does not cause a problem, then it will work. So, as long as the syntax is valid, it will work.

Having proper syntax when you don't know the type of your variable can be a little tricky. If you are having trouble with that, you can insert explicit casts on 'x' where needed, casting it to the type it would be on that branch. This way the code is valid, and the casts are redundant and will be optimized out.

As for the particular error you got, it sounds like the error you'd get if you did not have a type that matched your input and you had no default statement. Again, without seeing your invocation, it is hard to say. But I'd make sure you are matching the type exactly including qualifiers. One particular question I'd ask is if debug_print_options is a typedef, as if it is only defined as a structure tag then you need to put 'struct' in your _Generic to correctly identify the type.

jack
  • 282
  • 2
  • 9
  • It is typedef for simplicity. I ended up casting to void * and back to satisfy all branches: https://github.com/rtaycher/debug_print_h/blob/master/debug_print.h – Roman A. Taycher May 01 '15 at 05:35
  • 1
    Well, it is hard to say what the problem is without seeing the invocation of the macro that is causing the problem. A macro is basically an abbreviation, to answer the question the actual code needs to be given, not just the abbreviation rule without seeing how it is used. – jack May 02 '15 at 04:19