Reconsidering pros and cons of C language extensions

Posted on Sun Apr 2, 2017

I’ve registered my CCExceptions project with Travis CI; it is the first project I integrated with Travis. It worked but I had to fight with the build script… the platform uses Ubuntu, and I know nothing of this distribution’s packages. For some reasons their default gnu+Linux build infrastructure does not come with the latest gnu Autoconf and gcc; the build script has to install them. The latest Autoconf (2.69) was released in 2012, we are now in 2017…

I want to attempt a build under Mac OS X: it will be more painful because I literally never used this platform.

I’ve also tried to integrate the project with Coverity. This failed very early. The reason is that the project makes use of gcc extensions that, as far as I can tell, are not recognised by Coverity’s tools. This was to be expected! It hurts me.

In this project: I want to use the features of the C11 standard; I want to mimic single–inheritance with nested structs; I do not want to use void* pointers to structs and cast them to the appropriate data type.

The latest requirement is the one that bites: to avoid cluttering the code with cast operators and still obtain static–types validation, we have to do something clever. Given the struct hierarchy:

typedef struct alpha_t  alpha_t;
typedef struct beta_t   beta_t;

struct alpha_t {
  int           A;
};

struct beta_t {
  alpha_t       parent;
  int           B;
};

there need to be two mechanisms:

  1. A way to obtain a pointer to alpha_t from a pointer to beta_t.
  2. A way to obtain a pointer to beta_t from a pointer to alpha_t.

Using gcc’s -fplan9-extensions is an easy and friendly solution; but it is not standard. So what do I do?

I’ve opened a new (at present private) branch in the project to attempt a port to the standard language and see what happens. This has led to reconsiderations, type name changes and so on.

The basic idea I’m experimenting with is to define preprocessor macros which expand to _Generic uses:

#define cast_to_alpha(S)        _Generic((S), ...)
#define cast_to_beta(S)         _Generic((S), ...)

so that:

this is done with cast functions, C language: cast functions.

About this solution: it is a bit verbose; it is not totally safe; it requires some hand–written code, whose generation can be automated; it is unfriendly to extend a hierarchy defined in a library with data types defined in another library.

Life is hard.