]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/gc: fix comparison of struct with _ field
authorRuss Cox <rsc@golang.org>
Fri, 17 Feb 2012 19:45:29 +0000 (14:45 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 17 Feb 2012 19:45:29 +0000 (14:45 -0500)
Fixes #2989.

R=ken2
CC=golang-dev
https://golang.org/cl/5674091

src/cmd/gc/go.h
src/cmd/gc/subr.c
test/cmp.go
test/cmp6.go

index bb909b953cfbd11a95fa8b19ccddbbd59a2b094f..fcbea2cd90c70247bc0ddd695c2a48f6b2673190 100644 (file)
@@ -1172,6 +1172,7 @@ int       implements(Type *t, Type *iface, Type **missing, Type **have, int *ptr);
 void   importdot(Pkg *opkg, Node *pack);
 int    is64(Type *t);
 int    isblank(Node *n);
+int    isblanksym(Sym *s);
 int    isfixedarray(Type *t);
 int    isideal(Type *t);
 int    isinter(Type *t);
index 3fd520931029085e16272bd6ce22ef79419d00e5..5621ed9d343fa62040dc4dc1babf805ef980dee2 100644 (file)
@@ -571,6 +571,8 @@ algtype1(Type *t, Type **bad)
                }
                ret = AMEM;
                for(t1=t->type; t1!=T; t1=t1->down) {
+                       if(isblanksym(t1->sym))
+                               continue;
                        a = algtype1(t1->type, bad);
                        if(a == ANOEQ)
                                return ANOEQ;  // not comparable
@@ -887,12 +889,20 @@ isslice(Type *t)
 
 int
 isblank(Node *n)
+{
+       if(n == N)
+               return 0;
+       return isblanksym(n->sym);
+}
+
+int
+isblanksym(Sym *s)
 {
        char *p;
 
-       if(n == N || n->sym == S)
+       if(s == S)
                return 0;
-       p = n->sym->name;
+       p = s->name;
        if(p == nil)
                return 0;
        return p[0] == '_' && p[1] == '\0';
@@ -2652,12 +2662,14 @@ genhash(Sym *sym, Type *t)
                // and calling specific hash functions for the others.
                first = T;
                for(t1=t->type;; t1=t1->down) {
-                       if(t1 != T && algtype1(t1->type, nil) == AMEM) {
+                       if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
                                if(first == T)
                                        first = t1;
                                continue;
                        }
                        // Run memhash for fields up to this one.
+                       while(first != T && isblanksym(first->sym))
+                               first = first->down;
                        if(first != T) {
                                if(first->down == t1)
                                        size = first->type->width;
@@ -2867,7 +2879,7 @@ geneq(Sym *sym, Type *t)
                // and calling specific equality tests for the others.
                first = T;
                for(t1=t->type;; t1=t1->down) {
-                       if(t1 != T && algtype1(t1->type, nil) == AMEM) {
+                       if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
                                if(first == T)
                                        first = t1;
                                continue;
@@ -2875,13 +2887,16 @@ geneq(Sym *sym, Type *t)
                        // Run memequal for fields up to this one.
                        // TODO(rsc): All the calls to newname are wrong for
                        // cross-package unexported fields.
+                       while(first != T && isblanksym(first->sym))
+                               first = first->down;
                        if(first != T) {
                                if(first->down == t1) {
                                        fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
                                } else if(first->down->down == t1) {
                                        fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
                                        first = first->down;
-                                       fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+                                       if(!isblanksym(first->sym))
+                                               fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
                                } else {
                                        // More than two fields: use memequal.
                                        if(t1 == T)
index 795245f2f5bf1712d8daa0b14e56a94586cd50ad..a9d0375b2485464baf108db5cb23a6f3cbbf0618 100644 (file)
@@ -281,6 +281,25 @@ func main() {
                isfalse(ix != z)
                isfalse(iz != x)
        }
+       
+       // structs with _ fields
+       {
+               var x = struct {
+                       x int
+                       _ []int
+                       y float64
+                       _ float64
+                       z int
+               }{
+                       x: 1, y: 2, z: 3,
+               }
+               var ix interface{} = x
+               
+               istrue(x == x)
+               istrue(x == ix)
+               istrue(ix == x)
+               istrue(ix == ix)
+       }
 
        // arrays
        {
index 71f1284812ec8a322f38b3a3c4d1dc0878edfc30..1e286750ab5c58b9956c0a023625031aceaba357 100644 (file)
@@ -15,6 +15,10 @@ type T3 struct{ z []int }
 
 var t3 T3
 
+type T4 struct { _ []int; a float64 }
+
+var t4 T4
+
 func main() {
        // Arguments to comparison must be
        // assignable one to the other (or vice versa)
@@ -46,6 +50,7 @@ func main() {
 
        // Comparison of structs should have a good message
        use(t3 == t3) // ERROR "struct|expected"
+       use(t4 == t4) // ok; the []int is a blank field
 
        // Slices, functions, and maps too.
        var x []int