Why is the `_Generic` keyword in my macro not working? - c

Probably I'm doing some very basic thing wrong here, but I just cannot figure out what that could be. I can explain my code snippet, but I think it is pretty obvious what I'm trying to do here: create a type-generic macro overload "print function" for my DynamicArray's dynarr_printf method. The question is: why isn't it working?
Thanks in advance!
ENV:
// Mac OS X 10.9.2
// Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
cc -Wall -v -g -std=c11 -I/usr/local/include -c -o build/tmp/main.o main.c
CODE:
void
__dynarr_printf(DynamicArray *dynarr,
void (*print_func)(int, void*));
#define __line_fmt__(fmt) " [%d] " fmt "\n"
static inline void
__dynarr_printf_i(int i, int *v)
{
printf(__line_fmt__("%d"), i, *v);
}
// tons of type specific functions ...
static inline void
__dynarr_printf_def(int i, void *v)
{
printf(__line_fmt__("ptr(%p)"), i, v);
}
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
// tons of type specific funcs ...
default: __dynarr_printf_def)
#define dynarr_printf(dynarr, type) \
(__dynarr_printf(dynarr, __dynarr_typef(type)))
OUTPUT:
main.c:102:5: error: expected expression
dynarr_printf(dynarr, float);
^
./dynarr.h:168:31: note: expanded from macro 'dynarr_printf'
(__dynarr_printf(dynarr, __dynarr_typef(type)))
^
./dynarr.h:157:45: note: expanded from macro '__dynarr_typef'
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
^
1 error generated.

The syntax of a generic selection is:
_Generic ( assignment-expression , generic-assoc-list )
(For the definition of a generic-assoc-list and more information about generic selections, see N1570 section 6.5.1.1.)
The first "operand" is an expression, not a type name. It selects on the type of that expression.
If the type is always scalar, you could change
_Generic((type), ...)
to
_Generic((type)0), ...)

Related

GObject Compilation Error in Macro Expansion While Defining Class

Problem
Using GObject and C, I am trying to create a subclass of the class GObject named "Bar" in module "Foo". However, the macro "G_DECLARE_FINAL_TYPE" (defined in gobject/gtype.h) expands incorrectly. Instead of expanding into FOO_BAR, it expands into nothing. So instead of expanding into:
... FooBar * FOO_BAR (gpointer ptr) { ...
It instead expands into:
... FooBar * (gpointer ptr) { ...
Error Message
I expect it to compile but instead gcc gives a syntax error:
In file included from /usr/include/glib-2.0/gobject/gobject.h:24,
from /usr/include/glib-2.0/gobject/gbinding.h:29,
from /usr/include/glib-2.0/glib-object.h:22,
from foo-bar.h:4,
from foo-bar.c:1:
/usr/include/glib-2.0/gobject/gtype.h:1407:77: error: expected ‘)’ before ‘ptr’
1407 | USED static inline ModuleObjName * MODULE##_##OBJ_NAME (gpointer ptr) { \
| ^~~
foo-bar.h:10:1: note: in expansion of macro ‘G_DECLARE_FINAL_TYPE’
10 | G_DECLARE_FINAL_TYPE (FooBar, foo_bar, FOO, BAR, GObject)
| ^~~~~~~~~~~~~~~~~~~~
Definition of Macro
This definition comes from the glib 2.66.7 library. I did not define it myself. I include it for the sake of completeness.
#define G_DECLARE_FINAL_TYPE(ModuleObjName, module_obj_name, MODULE, OBJ_NAME, ParentName) \
GType module_obj_name##_get_type (void); \
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
typedef struct _##ModuleObjName ModuleObjName; \
typedef struct { ParentName##Class parent_class; } ModuleObjName##Class; \
\
_GLIB_DEFINE_AUTOPTR_CHAINUP (ModuleObjName, ParentName) \
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ModuleObjName##Class, g_type_class_unref) \
\
G_GNUC_UNUSED static inline ModuleObjName * MODULE##_##OBJ_NAME (gpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_CAST (ptr, module_obj_name##_get_type (), ModuleObjName); }\
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME (gpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_TYPE (ptr, module_obj_name##_get_type ()); } \
G_GNUC_END_IGNORE_DEPRECATIONS
Partial Pre-Processor Output
I included the definition that contains the syntax error and formatted it for readability:
__attribute__((__unused__)) static inline FooBar * (gpointer ptr) {
return (((FooBar*) g_type_check_instance_cast ((GTypeInstance*) (ptr), (foo_bar_get_type ()))));
}
What's odd is that the definition following does get pre-processed correctly:
__attribute__((__unused__)) static inline gboolean FOO_IS_BAR (gpointer ptr) {
return ((__extension__ ({
GTypeInstance *__inst = (GTypeInstance*) (ptr);
GType __t = (foo_bar_get_type ());
gboolean __r;
if (!__inst) __r = (0);
else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0));
else __r = g_type_check_instance_is_a (__inst, __t); __r; })));
}
Full Minimal Example
I have included a minimal example that causes my error below.
foo-bar.h
#ifndef FOO_BAR
#define FOO_BAR
#include <glib-object.h>
G_BEGIN_DECLS
#define FOO_TYPE_BAR (foo_bar_get_type ())
G_DECLARE_FINAL_TYPE (FooBar, foo_bar, FOO, BAR, GObject)
G_END_DECLS
#endif /* FOO_BAR */
foo-bar.c
#include "foo-bar.h"
struct _FooBar
{
GObject parent_instance;
};
G_DEFINE_TYPE (FooBar, foo_bar, G_TYPE_OBJECT);
static void foo_bar_class_init (FooBarClass *klass)
{
}
static void foo_bar_init (FooBar *app)
{
}
makefile
foo-bar.o: foo-bar.c
gcc -c foo-bar.c $(shell pkg-config --cflags gobject-2.0) -o foo-bar.o
# included to debug the macro
foo-bar.pp: foo-bar.c
gcc -E foo-bar.c $(shell pkg-config --cflags gobject-2.0) -o foo-bar.pp
Versions
glib 2.66.7
gcc 10.2.1
Linux (Fedora 33)
What I have tried
I have studied glib's documentation on how to create a new class and as far as I can tell I am doing it correctly. I have also looked up how token pasting and macro expansion work, and also tried googling my error. It must be something obvious, but I cannot figure out what. I also tried declaring a derivable class with private data, but while finding a minimal example I changed it to a final class without private data and still have the same error. I read about the ## operator here and still cannot tell what is going wrong.
Related Stack Overflow Questions
Finally, I have looked at the following related stackoverflow posts:
My error is that concatenated tokens are not being emitted by the pre-processor. In this post the user defines their own macro and asks why one invocation works and the other doesn't. I am using a library and not my own macro.
This question is asking about why a macro expands differently in unicode mode versus ascii mode. I am not dealing with unicode so it is not relevant.
I am not using C++, only C which does not have syntax for generics, so this question does not apply to me.
Since I am not using XCode this question does not solve my problem.
I understand how macro expansion is supposed to work, so this question does tell me anything I don't already know.
I am not defining any new macros and do not have and problems with namespace collision, unlike this question.
In this and this question the user is not aware of the concatenation operator in macros. I am, and my problem is that it does not work the way I expect it too. So saying the operator exists does not help me.
This question is close to my problem, but it is occuring because an argument to a macro was not provided. I am providing all arguments so it does not help me.
This question the user is using the pasting operator when they don't need to.. In my case the pasting operator is necessary.
Well, it was something dumb. Posting this in case anyone runs across this answer.
The problem is my include guard. It should be FOO_BAR_H since the name of the file is foo-bar.h. However, it is defined as FOO_BAR. When gobject generates the token "FOO_BAR" the pre-processor realizes that it is a macro that has already been defined, but in this case the definition is empty. Nevertheless, it replaces the macro with its definition.
The solution is just replacing "FOO_BAR" with "FOO_BAR_H" in the include guard.

How to define general function to take input in C using _Generic?

I was trying to define a general function to take input using _Generic in C, This is what I wrote
#include <stdio.h>
#define readlong(x) scanf("%lld",&x);
#define read(x) scanf("%lld",&x);
#define scan(x) _Generic((x), \
long long: readlong, \
default: read \
)(x)
but when I compile it using gcc test.c -std=C11 on gcc 5.3.0, I get error:
error: 'readlong' undeclared (first use in this function)
You can define your helpers to be functions instead of macros. I modified scan so that it would pass the address to the matched function.
static inline int readlong (long long *x) { return scanf("%lld", x); }
static inline int readshort (short *x) { return scanf("%hd", x); }
static inline int unknown (void) { return 0; }
#define scan(x) _Generic((x), \
long long: readlong, \
short: readshort, \
default: unknown \
)(&x)
readlong
is not the variable that you have declared. In:
#define readlong(x) scanf("%11d",&x);
you added (x). This will not let you use readlong without them.

Is function pointer type in _Generic assoc-list not working as expected?

I was experimenting with "hacking" the type-system, by not restricting the function pointer argument to accept a function with a specific type of arguments. However, I still wanted to make it type-safe, so I thought I will combine this "hack" with the possibilities of the _Generic keyword.
I have the following four functions:
#include <stdio.h> /* printf() */
#include <stdlib.h> /* EXIT_SUCCESS */
static void
function_i(int *i)
{
printf("%d\n", *i);
}
static void
function_f(float *f)
{
printf("%.2ff\n", *f);
}
static void
caller(void(*func)(),
void *arg)
{
func(arg);
}
static void
except(void(*func)(),
void *arg)
{
printf("unsupported type\n");
}
The first and second will be passed to the third, and I want to make sure, if the type of the function and the argument passed to the third is not right, then the fourth function will be called. Therefore I created the following _Generic selector:
#define handler(func, arg) _Generic((func), \
void(*)(int*): _Generic((arg), \
int* : caller, \
default : except), \
void(*)(float*): _Generic((arg), \
float* : caller, \
default : except), \
default: except)(func, arg)
And then I called them:
int main(void)
{
int i = 12;
float f = 3.14f;
void(*func_ptr_i)(int*) = function_i;
void(*func_ptr_f)(float*) = function_f;
handler(function_i, &i);
handler(function_f, &f);
handler(func_ptr_i, &i);
handler(func_ptr_f, &f);
return EXIT_SUCCESS;
}
The output is very interesting:
unsupported type
unsupported type
12
3.14f
I expected this to work for the first two cases as well, without the need to create a specific function pointer variable for the passed functions. The question is: is this an implementation error in clang's _Generic, or this is the expected behavior? Is so, I'm very curious about why exactly? And how to make it work without creating extra function pointers?
Thanks in advance!
SYS-INFO:
compiler: Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
flags: cc -std=c11 -Wall -v -g
The problem that you are facing is that the choice expression of _Generic is not evaluated. If it would be, your function names would decay to function pointers and everything would work.
Adding a & to your choice expression should fix that.

GCC typeof extension

I don't understand why this works:
/* gcc range extension */
__extension__ static int fn(int n)
{
switch (n) {
case 0: return 0;
case 1 ... 1000: return 1;
default: return -1;
}
}
But this does not:
/* gcc typeof extension */
__extension__ static void fn(int n)
{
typeof(n) a = n;
printf("%d\n", a);
}
gcc returns:
demo.c:14: warning: implicit declaration of function ‘typeof’
demo.c:14: warning: nested extern declaration of ‘typeof’
demo.c:14: error: expected ‘;’ before ‘a’
demo.c:16: error: ‘a’ undeclared (first use in this function)
demo.c:16: error: (Each undeclared identifier is reported only once
demo.c:16: error: for each function it appears in.)
I know I can compile with -std=gnu99 to avoid the error but the first one works with -std=c99 and uses also an extension
Non-ANSI compatible keywords are not ever reenabled by __extension__ (the only effect of __extension__ is warning suppression for -pedantic). Use __typeof__ if you want to compile in ANSI mode.
If you are writing a header file that must work when included in ISO C programs, write __typeof__ instead of typeof.
Refer to this link for a more elaborate description and the possible fixes.
Note: __extension__ has no effect aside from suppressing the warnings when using ANSI C -pedantic mode.
So something like this:
/* gcc typeof extension */
__extension__ static void fn(int n)
{
__typeof__(n) a = n;
printf("%d\n", a);
}

How to check `typeof` for void value at compile time?

let's say that I want to have C macro that works on any type.
I'm using GCC compiler (>= 4.6) and can use GNU99 macros.
//code...
any_type_t *retVal = function_that_runs_very_long_time(a, b, &&c, **d, &e, *f);
//other code...
usage of macro for TIMER can look for example like this
//code...
any_type_t *retVal =
TIMER(
function_that_runs_very_long_time(a, b, &&c, **d, &e, *f),
"TIMING FOR VALUE <%d, %d>", a, b
);
//other code...
So TIMER has to return value of given function and print duration of its run.
There is problem with functions that have void return type.
I can obviously have two macros like TIMER_TYPE and TIMER_VOID, but I want to use single one to time function with any return value.
Thank you for suggestions.
Edited example of this TIMER macro
#define TIMER(expr, fmt_msg, ...) \
({ \
struct timeval before, after; \
uint64_t time_span; \
int time_span_sec, time_span_usec; \
gettimeofday(&before, NULL); \
typeof(expr) _timer_expr__ = (expr); \ // <- static if?
gettimeofday(&after, NULL); \
time_span = (after.tv_sec * 1000000 + after.tv_usec) \
- (before.tv_sec * 1000000 + before.tv_usec); \
time_span_sec = time_span / 1000000; \
time_span_usec = time_span % 1000000; \
TRACE(fmt_msg "\n%s : %d.%d seconds", \
#expr, time_span_sec, time_span_usec, ...); \
_timer_expr__; \
})
What an interesting question, kudos!
After few experiments, I found a solution which uses __builtin_types_compatible_p and __builtin_choose_expr intrinsics of GCC.
__builtin_types_compatible_p
Quoting GCC manual:
Built-in Function: int __builtin_types_compatible_p (type1, type2)
You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.
This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.
This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.
So here is how we can check for "voidness".
#define __type_is_void(expr) __builtin_types_compatible_p(typeof(expr), void)
__builtin_choose_expr
Built-in Function: type __builtin_choose_expr (const_exp, exp1, exp2)
You can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if const_exp, which is an integer constant expression, is nonzero. Otherwise it returns exp2.
This built-in function is analogous to the ? : operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in function does not evaluate the expression that is not chosen. For example, if const_exp evaluates to true, exp2 is not evaluated even if it has side-effects.
If exp1 is returned, the return type is the same as exp1's type. Similarly, if exp2 is returned, its return type is the same as exp2.
So __builtin_choose_expr intrinsic is something like a "static switch" evaluated at compile-time.
Preparation
I don't paste here your TIMER macro, but I assume it is able to split it into two versions: one for void expr and one for the rest. Here are just stubs which evaluate the expression and yield the result of the same type.
#define __DO(expr) \
({ typeof(expr) __ret; __ret = (expr); __ret; })
#define __DO_VOID(expr) \
(void) (expr)
Naive solution
Now we can statically switch between two implementations, depending on the actual type of the expression. But in fact the naive solution doesn't work, see below.
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(expr)) # won't work
Attempt to compile this code passing a void expression gives the following error:
test.c:28:9: error: variable or field ‘__ret’ declared void
test.c:28:9: error: void value not ignored as it ought to be
Although __DO_VOID is chosen, __DO generates errors. This behavior is described in manual:
... the unused expression (exp1 or exp2 depending on the value of const_exp) may still generate syntax errors. This may change in future revisions.
Working solution
The trick is to substitute the original void expr with some non-void value to be able to compile the __DO case (which is anyway a dead code when expr is void).
#define __expr_or_zero(expr) __builtin_choose_expr(__type_is_void(expr), 0, (expr))
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(__expr_or_zero(expr))) # works fine!
That's it! Here is the complete source code on Ideone: http://ideone.com/EFy4pE
can you accept an answer of "this isn't really possible" ?
not the part about returning from a macro. but the part about conditionally testing expr for its return type.
in effect, you're asking for something like the following:
let's say instead of some magical check called "is_expr_type_void(expr)", you instead simply pass a 1 or a 0 at the time of the call to indicate is_void or !is_void in the following variation of your macro:
#define TIMER(is_void, expr, fmt_msg, ...) \
({ \
struct timeval before, after; \
uint64_t time_span; \
int time_span_sec, time_span_usec; \
gettimeofday(&before, NULL); \
if (is_void) \
(expr) \
else \
typeof(expr) _timer_expr__ = (expr); \ // <- static if?
gettimeofday(&after, NULL); \
time_span = (after.tv_sec * 1000000 + after.tv_usec) \
- (before.tv_sec * 1000000 + before.tv_usec); \
time_span_sec = time_span / 1000000; \
time_span_usec = time_span % 1000000; \
TRACE(fmt_msg "\n%s : %d.%d seconds", \
#expr, time_span_sec, time_span_usec, ...); \
if (!is_void) \
_timer_expr__; \
})
this simply cannot work. the preprocessor would create code for that if-else conditional in all cases, both void and non-void function calls. and both sides would compile fine for non-void functions. but the compiler would always choke on the "else" part of the conditional when TIMER is invoked with a void function … despite the fact that the code would never be called.
(now if there existed a really smart compiler that could both identify that it would be dead code and dead-strip it prior to flagging it as a compile time error, you'd be in luck! but i don't think gcc 4.6 is that smart … )
this leaves you with what would be a preferred option of a #if (is_void) conditional inside the #define. but that's simply not allowed. since, as this answer points out in attempting to answer a similar question about conditional preprocessing, the preprocessor is not turing-complete.
so … despite your desire to have a single macro, i think your simplest answer is to create one for void functions, and one for functions with return values.
As long as you've got typeof and _Generic, you can do also do it without __builtin_types_compatible_p or __builtin_choose_expr.
The caveat is that _Generic won't let you match void so instead of matching Expr against void, match (typeof(Expr)*){0} against void*.
Below is eldar-abusalimov example modified to use _Generic instead of __builtin_types_compatible_p and __builtin_choose_expr:
#include <stdio.h>
#define __type_is_void(expr) _Generic((typeof(expr)*){0}, void*:1, default:0)
#define __expr_or_zero(expr) _Generic((typeof(expr)*){0}, void*:0, default:(expr))
#define DO(expr) \
_Generic((typeof(expr)*){0}, \
void*:__DO_VOID(expr), \
default:__DO(__expr_or_zero(expr)))
#define __DO(expr) \
({ typeof(expr) __ret; puts("do nonvoid"); __ret = (expr); __ret; })
#define __DO_VOID(expr) \
(void)({ puts("do void"); (void)(expr); })
void foo(void) { }
int bar(void) { return 1; }
int main(void)
{
DO(foo());
DO(bar());
return 0;
}
If you really need to return from macro, use inline function instead.

Resources