diff --git a/tcc.h b/tcc.h index bfac0638..8369c9ff 100644 --- a/tcc.h +++ b/tcc.h @@ -1029,6 +1029,8 @@ struct filespec { #define VT_SYM 0x0200 /* a symbol value is added */ #define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for char/short stored in integer registers) */ +#define VT_NONCONST 0x1000 /* VT_CONST, but not an (C standard) integer + constant expression */ #define VT_MUSTBOUND 0x4000 /* bound checking must be done before dereferencing value */ #define VT_BOUNDED 0x8000 /* value is bounded. The address of the diff --git a/tccgen.c b/tccgen.c index 54fb38ad..4b2c4912 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2187,6 +2187,7 @@ static void gen_opic(int op) int t2 = v2->type.t & VT_BTYPE; int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; + int nonconst = (v1->r | v2->r) & VT_NONCONST; uint64_t l1 = c1 ? v1->c.i : 0; uint64_t l2 = c2 ? v2->c.i : 0; int shm = (t1 == VT_LLONG) ? 63 : 31; @@ -2253,6 +2254,7 @@ static void gen_opic(int op) v1->c.i = l1; vtop--; } else { + nonconst = VT_NONCONST; /* if commutative ops, put c2 as constant */ if (c1 && (op == '+' || op == '&' || op == '^' || op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) { @@ -2326,6 +2328,8 @@ static void gen_opic(int op) gen_opi(op); } } + if (vtop->r == VT_CONST) + vtop->r |= nonconst; } #if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 @@ -2609,7 +2613,7 @@ static int pointed_size(CType *type) static inline int is_null_pointer(SValue *p) { - if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM | VT_NONCONST)) != VT_CONST) return 0; return ((p->type.t & VT_BTYPE) == VT_INT && (uint32_t)p->c.i == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) || diff --git a/tests/tests2/94_generic.c b/tests/tests2/94_generic.c index 4a68bcdd..1cb01641 100644 --- a/tests/tests2/94_generic.c +++ b/tests/tests2/94_generic.c @@ -92,6 +92,9 @@ int main() //void ptrs get chosen preferentially; qualifs still combine _Generic( 0?(int volatile*)0: (void const*)1, void volatile const*: (void)0); + //but this is no null-ptr constant, so fallback to void-choice + i = 0; + _Generic( 1?(void*)(i*0LL):&i, void*:0); //like gcc but not clang, don't treat (void* const as the null-ptr constant) _Generic( 0?(int volatile*)0: (void const*)0, void volatile const*: (void)0);