ref: 3df95385bcc5294a212534d0991f1ffef1454aca
parent: 0f9666ae162f7c330850fa513e8ed3bd5fd995df
author: Ori Bernstein <[email protected]'>
date: Thu Feb 27 10:09:10 EST 2020
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.
--- a/sys/src/cmd/cc/cc.h
+++ b/sys/src/cmd/cc/cc.h
@@ -691,6 +691,7 @@
void typeext(Type*, Node*);
void typeext1(Type*, Node*);
int side(Node*);
+int zpconst(Node*);
int vconst(Node*);
int log2(uvlong);
int vlog(Node*);
--- a/sys/src/cmd/cc/com.c
+++ b/sys/src/cmd/cc/com.c
@@ -341,11 +341,13 @@
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;
}
--- a/sys/src/cmd/cc/sub.c
+++ b/sys/src/cmd/cc/sub.c
@@ -1026,6 +1026,21 @@
}
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)
{
int i;