Psycho C struct

I was compiling something that relies on Translate-C. When I accidentally used aarch64-linux instead of aarch64-linux-gnu as the target, I got an “opaque types have unknown size and therefore cannot be directly embedded in structs” error caused by the following definition in lib/libc/include/aarch64-linux-musl/bits/alltypes.h:

#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif

The bit-field causes Translate-C to define timespec as opaque which in turns breaks the stat struct and everything.

What could possibly be the reasoning behind defining a standard struct in such a psychotic manner?

A 32-bit time_t can only go to year 2038, so it would run into a new Y2K bug. Because of that, even 32-bit systems use 64-bit time_t. But if long is 32 bits, this leaves a 32-bit padding, which creates ambiguity. Defining it this way makes it so tv_ns always lives in the 32 low significant bits of this 64-bit space, with the other 32 bits being an unnamed bitfield, which is the only way to create an anonymous field in C.

8 Likes

Expanding upon @LucasSantos91’s answer, you there’s no portable sizeof equivalent for preprocessor #if conditions. Otherwise, the struct might have been defined like this (ignoring all the obscure edge cases the below won’t cover):

struct timespec { 
    time_t tv_sec; 
#if (sizeof(long) == 4 && __BYTE_ORDER == 4321)
    int32_t _padding;
#endif
    long tv_nsec;
#if (sizeof(long) == 4 && __BYTE_ORDER != 4321)
    int32_t _padding;
#endif
 };

Using bit fields with computed sizes is a hackish solution to the problem.

2 Likes
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
struct timespec { 
    time_t tv_sec; 
    int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); 
    long tv_nsec; 
    int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321);
 };
#define __DEFINED_struct_timespec
#endif

For those who would like a clearer view, thought I don’t think it provided me with much clarity.

2 Likes

This gets translated to opaque{} so that is where your error is coming from I think.