Commit 5c2666c1 authored by Russ Cox's avatar Russ Cox

gc: unsafe.Pointer is not a pointer

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
parent 22c45c55
......@@ -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;
......@@ -401,6 +404,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)
tptr = TPTR64;
......@@ -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++) {
......
......@@ -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"
......
......@@ -155,6 +155,7 @@ convlit1(Node **np, Type *t, int explicit)
case TMAP:
case TCHAN:
case TFUNC:
case TUNSAFEPTR:
break;
}
break;
......
......@@ -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:
......
......@@ -459,9 +459,10 @@ enum
TFIELD,
TANY,
TSTRING,
TUNSAFEPTR,
// pseudo-types for literals
TIDEAL, // 32
TIDEAL, // 33
TNIL,
TBLANK,
......
......@@ -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
if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
goto ok;
if(tbase->etype == tptr && tbase->type->etype == TANY) // unsafe.Pointer
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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -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"
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment