Hello everyone,
I ran into a problem with Clang with a C program, where several of the cases in a switch statement were mapped to the default case (which is an abort in my example). This only happens when the function is inlined (so at least -O1) and started with Clang 13. Here is a (stripped-down) program on Godbolt’s Compiler Explorer, where cases 2, 4, 6 and 8 are mapped to the default case (and also the other cases don’t look quite right, I would expect a jmp after the call…): Compiler Explorer
Is there something (some kind of undefined behavior?) I’m missing or is this a bug in Clang?
With thanks and best regards,
Alex
typedef struct svalue_s svalue_t;
int get_type_1_hash(long int val);
int get_type_3_hash(long int val);
int get_type_5_hash(long int val);
int get_type_7_hash(long int val);
struct svalue_s
{
short int type;
union u {
long int t1;
long int t2;
long int t3;
long int t4;
long int t5;
long int t6;
long int t7;
long int t8;
} u;
};
extern void fatal (const char *, ...) __attribute__((format (printf,1,2))) __attribute__((noreturn));
static inline int
svalue_hash (svalue_t *svp, int bits)
{
long int result;
switch (svp->type)
{
default:
fatal("Illegal svalue type %d\n", svp->type);
case 1:
result = get_type_1_hash(svp->u.t1);
break;
case 2:
result = svp->u.t2;
break;
case 3:
result = get_type_3_hash(svp->u.t3);
break;
case 4:
result = svp->u.t4;
break;
case 5:
result = get_type_5_hash(svp->u.t5);
break;
case 6:
result = svp->u.t6;
break;
case 7:
result = get_type_7_hash(svp->u.t7);
break;
case 8:
result = svp->u.t8;
break;
}
return result & ((1<<bits) - 1);
}
typedef struct mapping_hash_s mapping_hash_t;
typedef struct map_chain_s map_chain_t;
struct mapping_hash_s {
int mask;
map_chain_t * chains[];
};
struct map_chain_s {
map_chain_t * next;
svalue_t data[];
};
svalue_t *get_map_lvalue (mapping_hash_t *hm, svalue_t *map_index)
{
if (hm)
{
int idx = svalue_hash(map_index, 32) & hm->mask;
return hm->chains[idx]->data;
}
return ((void*)0);
}