Fix null pointer constants
an expression like 'i*0', even though it's value is constant and can be evaluated at compile time is not an integer constant expression, and hence no null pointer constant, and therefore the conditional operator doesn't select the other type.
This commit is contained in:
parent
c3e3a07ed4
commit
aa9093a144
3 changed files with 10 additions and 1 deletions
2
tcc.h
2
tcc.h
|
@ -1029,6 +1029,8 @@ struct filespec {
|
||||||
#define VT_SYM 0x0200 /* a symbol value is added */
|
#define VT_SYM 0x0200 /* a symbol value is added */
|
||||||
#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
|
#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
|
||||||
char/short stored in integer registers) */
|
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
|
#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
|
||||||
dereferencing value */
|
dereferencing value */
|
||||||
#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
|
#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
|
||||||
|
|
6
tccgen.c
6
tccgen.c
|
@ -2187,6 +2187,7 @@ static void gen_opic(int op)
|
||||||
int t2 = v2->type.t & VT_BTYPE;
|
int t2 = v2->type.t & VT_BTYPE;
|
||||||
int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
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 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 l1 = c1 ? v1->c.i : 0;
|
||||||
uint64_t l2 = c2 ? v2->c.i : 0;
|
uint64_t l2 = c2 ? v2->c.i : 0;
|
||||||
int shm = (t1 == VT_LLONG) ? 63 : 31;
|
int shm = (t1 == VT_LLONG) ? 63 : 31;
|
||||||
|
@ -2253,6 +2254,7 @@ static void gen_opic(int op)
|
||||||
v1->c.i = l1;
|
v1->c.i = l1;
|
||||||
vtop--;
|
vtop--;
|
||||||
} else {
|
} else {
|
||||||
|
nonconst = VT_NONCONST;
|
||||||
/* if commutative ops, put c2 as constant */
|
/* if commutative ops, put c2 as constant */
|
||||||
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
||||||
op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) {
|
op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) {
|
||||||
|
@ -2326,6 +2328,8 @@ static void gen_opic(int op)
|
||||||
gen_opi(op);
|
gen_opi(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (vtop->r == VT_CONST)
|
||||||
|
vtop->r |= nonconst;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
|
#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)
|
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 0;
|
||||||
return ((p->type.t & VT_BTYPE) == VT_INT && (uint32_t)p->c.i == 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) ||
|
((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) ||
|
||||||
|
|
|
@ -92,6 +92,9 @@ int main()
|
||||||
|
|
||||||
//void ptrs get chosen preferentially; qualifs still combine
|
//void ptrs get chosen preferentially; qualifs still combine
|
||||||
_Generic( 0?(int volatile*)0: (void const*)1, void volatile const*: (void)0);
|
_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)
|
//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);
|
_Generic( 0?(int volatile*)0: (void const*)0, void volatile const*: (void)0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue