It's possible to do this by using the tricks from How to create type safe enums? Taking the trick of type safe assignment described in the accepted answer:
typedef union
{
day_t monday;
day_t tuesday;
day_t wednesday;
day_t thursday;
day_t friday;
day_t saturday;
day_t sunday;
} typesafe_day_t;
#define day_assign(var, val) _Generic((var), day_t: (var) = (typesafe_day_t){ .val = val }.val)
Then given some function void set_day (day_t day)
, we can design a safe version using a wrapper macro:
#define set_day_s(day) set_day( day_assign((day_t){0},day) )
This makes a temporary copy of the passed argument and runs that through the type safety macro, blocking everything that isn't one of the mentioned enum constants.
Full example:
typedef enum
{
monday = 1,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday
} day_t;
typedef union
{
day_t monday;
day_t tuesday;
day_t wednesday;
day_t thursday;
day_t friday;
day_t saturday;
day_t sunday;
} typesafe_day_t;
#define day_assign(var, val) _Generic((var), day_t: (var) = (typesafe_day_t){ .val = val }.val)
void set_day (day_t day){ /* ... */ }
#define set_day_s(day) set_day( day_assign((day_t){0},day) )
int main (void)
{
set_day_s(monday); // OK
day_t d=monday;
// set_day_s(d); // compiler error
// set_day_s(1); // compiler error
}