cmd/gc: implement len(array) / cap(array) rule

The spec is looser than the current implementation.
The spec edit was made in CL 4444050 (May 2011)
but I never implemented it.

Fixes #3244.

R=ken2
CC=golang-dev
https://golang.org/cl/5785049
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 6dc3fd1..e98d538 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -190,6 +190,46 @@
 	return n;
 }
 
+/*
+ * does n contain a call or receive operation?
+ */
+static int callrecvlist(NodeList*);
+
+static int
+callrecv(Node *n)
+{
+	if(n == nil)
+		return 0;
+	
+	switch(n->op) {
+	case OCALL:
+	case OCALLMETH:
+	case OCALLINTER:
+	case OCALLFUNC:
+	case ORECV:
+		return 1;
+	}
+
+	return callrecv(n->left) ||
+		callrecv(n->right) ||
+		callrecv(n->ntest) ||
+		callrecv(n->nincr) ||
+		callrecvlist(n->ninit) ||
+		callrecvlist(n->nbody) ||
+		callrecvlist(n->nelse) ||
+		callrecvlist(n->list) ||
+		callrecvlist(n->rlist);
+}
+
+static int
+callrecvlist(NodeList *l)
+{
+	for(; l; l=l->next)
+		if(callrecv(l->n))
+			return 1;
+	return 0;
+}
+
 static void
 typecheck1(Node **np, int top)
 {
@@ -995,12 +1035,14 @@
 			}
 			break;
 		case TARRAY:
-			if(t->bound >= 0 && l->op == ONAME) {
-				r = nod(OXXX, N, N);
-				nodconst(r, types[TINT], t->bound);
-				r->orig = n;
-				n = r;
-			}
+			if(t->bound < 0) // slice
+				break;
+			if(callrecv(l)) // has call or receive
+				break;
+			r = nod(OXXX, N, N);
+			nodconst(r, types[TINT], t->bound);
+			r->orig = n;
+			n = r;
 			break;
 		}
 		n->type = types[TINT];