fix special case for null pointer constants in cond expressions

Section 6.5.15 of the C99 spec requires that if
	one argument of a ?: expression is a null pointer
	constant, and the other has a pointer type T*, then
	the type of the expression is T*.

	We were attempting to follow this rule, however,
	we only handled literal expressions when checking
	for null pointers.

	This change looks through casts, so 'nil' and 'NULL',
	and their expansion '(void*)0' are all detected as
	null pointer constants.
This commit is contained in:
Ori Bernstein 2020-02-27 15:09:10 -05:00
parent 0f9666ae16
commit 3df95385bc
3 changed files with 20 additions and 2 deletions

View file

@ -691,6 +691,7 @@ Type* copytyp(Type*);
void typeext(Type*, Node*);
void typeext1(Type*, Node*);
int side(Node*);
int zpconst(Node*);
int vconst(Node*);
int log2(uvlong);
int vlog(Node*);

View file

@ -341,11 +341,13 @@ tcomo(Node *n, int f)
o |= tcom(r->left);
if(o | tcom(r->right))
goto bad;
if(r->right->type->etype == TIND && vconst(r->left) == 0) {
if(r->right->type->etype == TIND && zpconst(r->left)) {
r->type = r->right->type;
r->left->type = r->right->type;
r->left->vconst = 0;
}
if(r->left->type->etype == TIND && vconst(r->right) == 0) {
if(r->left->type->etype == TIND && zpconst(r->right)) {
r->type = r->left->type;
r->right->type = r->left->type;
r->right->vconst = 0;
}

View file

@ -1025,6 +1025,21 @@ loop:
return 1;
}
int
zpconst(Node *n)
{
while(n->op == OCAST){
if(n->type == T)
break;
if(n->type->etype != TIND)
break;
if(n->type->link->etype != TVOID)
break;
n = n->left;
}
return vconst(n) == 0;
}
int
vconst(Node *n)
{