vendredi 8 mai 2015

Have C generate an error inside a _Generic

I've been working on some code (related to linear algebra). I have a number of types that one should be able to multiply with each other.

Naturally I thought "let's use _Generic" for this. Well it works, as long as the combination of argument types are valid. According to search engines, some libraries have resorted to using attributes on dummy functions to generate errors:

#include "stdio.h"

// Example struct.
typedef struct mat3_s
{
    float m[9];
} mat3;

// Dummy function.
mat3 mult(mat3 const *A, mat3 const *B)
{   
    return *A;
}

mat3 mults(mat3 const *A, float const *B)
{
    return *A;
}

typedef mat3 (*dummyptr)(void *A, void *B);
extern dummyptr INCOMPATIBLE_TYPES() __attribute__((error("Crikey"))); 

#define LMULT(A, B)\
    _Generic((A),\
    mat3: \
        _Generic((B),\
            mat3: mult, \
            float: mults, \
            default: INCOMPATIBLE_TYPES()),\
    default: INCOMPATIBLE_TYPES()) (&(A), &(B))

int main(int argc, char *argv[])
{
    mat3 a = {{0}};
    mat3 b = {{0}};
    mat3 c = LMULT(a, b);

    mat3 d = LMULT(a, "not kosher");

    // Inhibit GCC from optimising away above variables.
    printf("%p %p %p %p\n", &a, &b, &c, &d);
    return 0;
}

The gymnastics involved is the "INCOMPATIBLE_TYPES" function. As it stands it doesn't work well (if at all). And it is GCC only, and fragile, and... just not nice.

_Pragma("gcc error \"Great heavens\"") will not work either since GCC expands _Pragma to the resulting macro. And that happens to be inside a _Generic-expression which of course is processed at a later stage.

I am about to give up and just give gibberish back (also called C++ error reporting) and hopefully it will give enough information as to what might be the problem.

Does anybody else have any ideas how to generate a user friendly enough message if two types are passed for which there is no corresponding function?

Aucun commentaire:

Enregistrer un commentaire