]> Cypherpunks repositories - gostls13.git/commitdiff
gc: unsafe.Pointer is not a pointer
authorRuss Cox <rsc@golang.org>
Mon, 7 Mar 2011 20:10:01 +0000 (15:10 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 7 Mar 2011 20:10:01 +0000 (15:10 -0500)
Change unsafe.Pointer to be its own kind of
type, instead of making it equivalent to *any.
The change complicates import and export
but avoids the need to find all the places that
operate on pointers but should not operate on
unsafe.Pointer.

Fixes #1566. (a different way)
Fixes #1582.

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

src/cmd/gc/align.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/const.c
src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/reflect.c
src/cmd/gc/subr.c
src/cmd/gc/typecheck.c
src/cmd/gc/unsafe.go
test/fixedbugs/bug325.go

index 833eba19aeadcb73ccadcd6a7ca0d236636b1161..a01e2ea46b0fb9854d354deaf5f65a26fca37cd4 100644 (file)
@@ -172,6 +172,9 @@ dowidth(Type *t)
                w = 8;
                checkwidth(t->type);
                break;
+       case TUNSAFEPTR:
+               w = widthptr;
+               break;
        case TINTER:            // implemented as 2 pointers
                w = 2*widthptr;
                t->align = widthptr;
@@ -400,6 +403,13 @@ typeinit(void)
 
        types[TPTR64] = typ(TPTR64);
        dowidth(types[TPTR64]);
+       
+       t = typ(TUNSAFEPTR);
+       types[TUNSAFEPTR] = t;
+       t->sym = pkglookup("Pointer", unsafepkg);
+       t->sym->def = typenod(t);
+       
+       dowidth(types[TUNSAFEPTR]);
 
        tptr = TPTR32;
        if(widthptr == 8)
@@ -481,6 +491,7 @@ typeinit(void)
 
        okforeq[TPTR32] = 1;
        okforeq[TPTR64] = 1;
+       okforeq[TUNSAFEPTR] = 1;
        okforeq[TINTER] = 1;
        okforeq[TMAP] = 1;
        okforeq[TCHAN] = 1;
@@ -570,6 +581,7 @@ typeinit(void)
        simtype[TMAP] = tptr;
        simtype[TCHAN] = tptr;
        simtype[TFUNC] = tptr;
+       simtype[TUNSAFEPTR] = tptr;
 
        /* pick up the backend typedefs */
        for(i=0; typedefs[i].name; i++) {
index 48f45293fc819ff3cf81f32cd9b1f7cf153d89d9..6fe2c8b69bf9e3eef606b0a7b2950ab90b6721a4 100644 (file)
@@ -96,7 +96,7 @@ char *runtimeimport =
        "$$\n";
 char *unsafeimport =
        "package unsafe\n"
-       "type \"\".Pointer *any\n"
+       "type \"\".Pointer uintptr\n"
        "func \"\".Offsetof (? any) int\n"
        "func \"\".Sizeof (? any) int\n"
        "func \"\".Alignof (? any) int\n"
index a54c40f6cc209ac83ea72edf1ba3feca8895bb40..0cc26fc3b51d5dc019fe4003b138a0f1aef987c0 100644 (file)
@@ -155,6 +155,7 @@ convlit1(Node **np, Type *t, int explicit)
                case TMAP:
                case TCHAN:
                case TFUNC:
+               case TUNSAFEPTR:
                        break;
                }
                break;
index a71272aa222173f70fa34afd2e08fb80638538d2..2aa1bc817017296778901fbc02088e6db01cf9da 100644 (file)
@@ -656,10 +656,19 @@ typedcl2(Type *pt, Type *t)
 {
        Node *n;
 
+       // override declaration in unsafe.go for Pointer.
+       // there is no way in Go code to define unsafe.Pointer
+       // so we have to supply it.
+       if(incannedimport &&
+          strcmp(importpkg->name, "unsafe") == 0 &&
+          strcmp(pt->nod->sym->name, "Pointer") == 0) {
+               t = types[TUNSAFEPTR];
+       }
+
        if(pt->etype == TFORW)
                goto ok;
        if(!eqtype(pt->orig, t))
-               yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
+               yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
        return;
 
 ok:
index bf84c12a13aa8dd99ffd3635d8d74655a27fed4e..abc9e829c77e687b988aabc17582dc97a47c1c1d 100644 (file)
@@ -459,9 +459,10 @@ enum
        TFIELD,
        TANY,
        TSTRING,
+       TUNSAFEPTR,
 
        // pseudo-types for literals
-       TIDEAL,                 // 32
+       TIDEAL,                 // 33
        TNIL,
        TBLANK,
 
index 8129bf1ce7dc41c83accaab7391285774e1e5a0b..6b86462c44120d2fa3f3dc0e21c21072bc161779 100644 (file)
@@ -466,6 +466,7 @@ kinds[] =
        [TFUNC]         = KindFunc,
        [TCOMPLEX64]    = KindComplex64,
        [TCOMPLEX128]   = KindComplex128,
+       [TUNSAFEPTR]    = KindUnsafePointer,
 };
 
 static char*
@@ -488,6 +489,7 @@ structnames[] =
        [TFLOAT64]      = "*runtime.FloatType",
        [TBOOL]         = "*runtime.BoolType",
        [TSTRING]       = "*runtime.StringType",
+       [TUNSAFEPTR] =  "*runtime.UnsafePointerType",
 
        [TPTR32]        = "*runtime.PtrType",
        [TPTR64]        = "*runtime.PtrType",
@@ -514,9 +516,6 @@ typestruct(Type *t)
        if(isslice(t))
                name = "*runtime.SliceType";
 
-       if(isptr[et] && t->type->etype == TANY)
-               name = "*runtime.UnsafePointerType";
-
        return pkglookup(name, typepkg);
 }
 
@@ -553,6 +552,7 @@ haspointers(Type *t)
        case TSTRING:
        case TPTR32:
        case TPTR64:
+       case TUNSAFEPTR:
        case TINTER:
        case TCHAN:
        case TMAP:
@@ -612,8 +612,6 @@ dcommontype(Sym *s, int ot, Type *t)
        i = kinds[t->etype];
        if(t->etype == TARRAY && t->bound < 0)
                i = KindSlice;
-       if(isptr[t->etype] && t->type->etype == TANY)
-               i = KindUnsafePointer;
        if(!haspointers(t))
                i |= KindNoPointers;
        ot = duint8(s, ot, i);  // kind
@@ -714,12 +712,8 @@ dtypesym(Type *t)
                tbase = t->type;
        dupok = tbase->sym == S;
 
-       if(compiling_runtime) {
-               if(tbase == types[tbase->etype])        // int, float, etc
-                       goto ok;
-               if(tbase->etype == tptr && tbase->type->etype == TANY)  // unsafe.Pointer
-                       goto ok;
-       }
+       if(compiling_runtime && tbase == types[tbase->etype])   // int, float, etc
+               goto ok;
 
        // named types from other files are defined only by those files
        if(tbase->sym && !tbase->local)
@@ -908,7 +902,7 @@ dumptypestructs(void)
                for(i=1; i<=TBOOL; i++)
                        dtypesym(ptrto(types[i]));
                dtypesym(ptrto(types[TSTRING]));
-               dtypesym(ptrto(pkglookup("Pointer", unsafepkg)->def->type));
+               dtypesym(ptrto(types[TUNSAFEPTR]));
                
                // add paths for runtime and main, which 6l imports implicitly.
                dimportpath(runtimepkg);
index 142e5ba41efb063ce6663aca6fb61ddfa2cdf79a..54051598d7f98dc5acf5f252e49cf1b6004ffc7c 100644 (file)
@@ -1144,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
        && t->sym != S
        && !(fp->flags&FmtLong)) {
                s = t->sym;
-               if(t == types[t->etype])
+               if(t == types[t->etype] && t->etype != TUNSAFEPTR)
                        return fmtprint(fp, "%s", s->name);
                if(exporting) {
                        if(fp->flags & FmtShort)
@@ -1304,6 +1304,11 @@ Tpretty(Fmt *fp, Type *t)
                if(t->sym)
                        return fmtprint(fp, "undefined %S", t->sym);
                return fmtprint(fp, "undefined");
+       
+       case TUNSAFEPTR:
+               if(exporting)
+                       return fmtprint(fp, "\"unsafe\".Pointer");
+               return fmtprint(fp, "unsafe.Pointer");
        }
 
        // Don't know how to handle - fall back to detailed prints.
@@ -1346,6 +1351,9 @@ Tconv(Fmt *fp)
                }
        }
 
+       if(sharp || exporting)
+               fatal("missing %E case during export", t->etype);
+
        et = t->etype;
        fmtprint(fp, "%E ", et);
        if(t->sym != S)
@@ -1864,7 +1872,7 @@ assignop(Type *src, Type *dst, char **why)
        if(why != nil)
                *why = "";
 
-       if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
+       if(safemode && src != T && src->etype == TUNSAFEPTR) {
                yyerror("cannot use unsafe.Pointer");
                errorexit();
        }
@@ -2028,11 +2036,11 @@ convertop(Type *src, Type *dst, char **why)
        }
        
        // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
-       if((isptr[src->etype] || src->etype == TUINTPTR) && isptrto(dst, TANY))
+       if((isptr[src->etype] || src->etype == TUINTPTR) && dst->etype == TUNSAFEPTR)
                return OCONVNOP;
 
        // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
-       if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
+       if(src->etype == TUNSAFEPTR && (isptr[dst->etype] || dst->etype == TUINTPTR))
                return OCONVNOP;
 
        return 0;
index 3e8f358770cd17d42e11c2cb293f2ca23494cc6a..2c4f4dbbfffe81319f4a1be0ab586a029f71a560 100644 (file)
@@ -318,7 +318,7 @@ reswitch:
                        n->left = N;
                        goto ret;
                }
-               if(!isptr[t->etype] || (t->type != T && t->type->etype == TANY) /* unsafe.Pointer */) {
+               if(!isptr[t->etype]) {
                        yyerror("invalid indirect of %+N", n->left);
                        goto error;
                }
@@ -1316,7 +1316,7 @@ ret:
 
        // TODO(rsc): should not need to check importpkg,
        // but reflect mentions unsafe.Pointer.
-       if(safemode && !incannedimport && !importpkg && isptrto(t, TANY))
+       if(safemode && !incannedimport && !importpkg && t->etype == TUNSAFEPTR)
                yyerror("cannot use unsafe.Pointer");
 
        evconst(n);
index bd7b7771a7938ddb35345a6e014bc894d6e8ee7b..b2a341d39154e32dee260ade9ff93348a2c9dfb1 100644 (file)
@@ -8,7 +8,7 @@
 
 package PACKAGE
 
-type Pointer *any
+type Pointer uintptr // not really; filled in by compiler
 
 func Offsetof(any) int
 func Sizeof(any) int
index 23dbc8b3cb8d0a0cd93f7e6fe07264510b1e3aae..205b836b0839e9c4086444d51f59e2fe5b09cd65 100644 (file)
@@ -11,4 +11,5 @@ import "unsafe"
 func main() {
        var x unsafe.Pointer
        println(*x) // ERROR "invalid indirect.*unsafe.Pointer"
+       var _ = (unsafe.Pointer)(nil).foo  // ERROR "no field or method foo"
 }