shithub: riscv

Download patch

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;