mirror of
https://github.com/golang/go
synced 2024-11-21 19:14:44 -07:00
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
This commit is contained in:
parent
22c45c558b
commit
5c2666c18c
@ -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++) {
|
||||
|
@ -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
|
||||
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);
|
||||
|
@ -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"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user