mirror of https://github.com/golang/go.git
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;
|
w = 8;
|
||||||
checkwidth(t->type);
|
checkwidth(t->type);
|
||||||
break;
|
break;
|
||||||
|
case TUNSAFEPTR:
|
||||||
|
w = widthptr;
|
||||||
|
break;
|
||||||
case TINTER: // implemented as 2 pointers
|
case TINTER: // implemented as 2 pointers
|
||||||
w = 2*widthptr;
|
w = 2*widthptr;
|
||||||
t->align = widthptr;
|
t->align = widthptr;
|
||||||
|
|
@ -400,6 +403,13 @@ typeinit(void)
|
||||||
|
|
||||||
types[TPTR64] = typ(TPTR64);
|
types[TPTR64] = typ(TPTR64);
|
||||||
dowidth(types[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;
|
tptr = TPTR32;
|
||||||
if(widthptr == 8)
|
if(widthptr == 8)
|
||||||
|
|
@ -481,6 +491,7 @@ typeinit(void)
|
||||||
|
|
||||||
okforeq[TPTR32] = 1;
|
okforeq[TPTR32] = 1;
|
||||||
okforeq[TPTR64] = 1;
|
okforeq[TPTR64] = 1;
|
||||||
|
okforeq[TUNSAFEPTR] = 1;
|
||||||
okforeq[TINTER] = 1;
|
okforeq[TINTER] = 1;
|
||||||
okforeq[TMAP] = 1;
|
okforeq[TMAP] = 1;
|
||||||
okforeq[TCHAN] = 1;
|
okforeq[TCHAN] = 1;
|
||||||
|
|
@ -570,6 +581,7 @@ typeinit(void)
|
||||||
simtype[TMAP] = tptr;
|
simtype[TMAP] = tptr;
|
||||||
simtype[TCHAN] = tptr;
|
simtype[TCHAN] = tptr;
|
||||||
simtype[TFUNC] = tptr;
|
simtype[TFUNC] = tptr;
|
||||||
|
simtype[TUNSAFEPTR] = tptr;
|
||||||
|
|
||||||
/* pick up the backend typedefs */
|
/* pick up the backend typedefs */
|
||||||
for(i=0; typedefs[i].name; i++) {
|
for(i=0; typedefs[i].name; i++) {
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ char *runtimeimport =
|
||||||
"$$\n";
|
"$$\n";
|
||||||
char *unsafeimport =
|
char *unsafeimport =
|
||||||
"package unsafe\n"
|
"package unsafe\n"
|
||||||
"type \"\".Pointer *any\n"
|
"type \"\".Pointer uintptr\n"
|
||||||
"func \"\".Offsetof (? any) int\n"
|
"func \"\".Offsetof (? any) int\n"
|
||||||
"func \"\".Sizeof (? any) int\n"
|
"func \"\".Sizeof (? any) int\n"
|
||||||
"func \"\".Alignof (? any) int\n"
|
"func \"\".Alignof (? any) int\n"
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ convlit1(Node **np, Type *t, int explicit)
|
||||||
case TMAP:
|
case TMAP:
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
case TFUNC:
|
case TFUNC:
|
||||||
|
case TUNSAFEPTR:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -656,10 +656,19 @@ typedcl2(Type *pt, Type *t)
|
||||||
{
|
{
|
||||||
Node *n;
|
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)
|
if(pt->etype == TFORW)
|
||||||
goto ok;
|
goto ok;
|
||||||
if(!eqtype(pt->orig, t))
|
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;
|
return;
|
||||||
|
|
||||||
ok:
|
ok:
|
||||||
|
|
|
||||||
|
|
@ -459,9 +459,10 @@ enum
|
||||||
TFIELD,
|
TFIELD,
|
||||||
TANY,
|
TANY,
|
||||||
TSTRING,
|
TSTRING,
|
||||||
|
TUNSAFEPTR,
|
||||||
|
|
||||||
// pseudo-types for literals
|
// pseudo-types for literals
|
||||||
TIDEAL, // 32
|
TIDEAL, // 33
|
||||||
TNIL,
|
TNIL,
|
||||||
TBLANK,
|
TBLANK,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,7 @@ kinds[] =
|
||||||
[TFUNC] = KindFunc,
|
[TFUNC] = KindFunc,
|
||||||
[TCOMPLEX64] = KindComplex64,
|
[TCOMPLEX64] = KindComplex64,
|
||||||
[TCOMPLEX128] = KindComplex128,
|
[TCOMPLEX128] = KindComplex128,
|
||||||
|
[TUNSAFEPTR] = KindUnsafePointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
|
|
@ -488,6 +489,7 @@ structnames[] =
|
||||||
[TFLOAT64] = "*runtime.FloatType",
|
[TFLOAT64] = "*runtime.FloatType",
|
||||||
[TBOOL] = "*runtime.BoolType",
|
[TBOOL] = "*runtime.BoolType",
|
||||||
[TSTRING] = "*runtime.StringType",
|
[TSTRING] = "*runtime.StringType",
|
||||||
|
[TUNSAFEPTR] = "*runtime.UnsafePointerType",
|
||||||
|
|
||||||
[TPTR32] = "*runtime.PtrType",
|
[TPTR32] = "*runtime.PtrType",
|
||||||
[TPTR64] = "*runtime.PtrType",
|
[TPTR64] = "*runtime.PtrType",
|
||||||
|
|
@ -514,9 +516,6 @@ typestruct(Type *t)
|
||||||
if(isslice(t))
|
if(isslice(t))
|
||||||
name = "*runtime.SliceType";
|
name = "*runtime.SliceType";
|
||||||
|
|
||||||
if(isptr[et] && t->type->etype == TANY)
|
|
||||||
name = "*runtime.UnsafePointerType";
|
|
||||||
|
|
||||||
return pkglookup(name, typepkg);
|
return pkglookup(name, typepkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,6 +552,7 @@ haspointers(Type *t)
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
case TPTR32:
|
case TPTR32:
|
||||||
case TPTR64:
|
case TPTR64:
|
||||||
|
case TUNSAFEPTR:
|
||||||
case TINTER:
|
case TINTER:
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
case TMAP:
|
case TMAP:
|
||||||
|
|
@ -612,8 +612,6 @@ dcommontype(Sym *s, int ot, Type *t)
|
||||||
i = kinds[t->etype];
|
i = kinds[t->etype];
|
||||||
if(t->etype == TARRAY && t->bound < 0)
|
if(t->etype == TARRAY && t->bound < 0)
|
||||||
i = KindSlice;
|
i = KindSlice;
|
||||||
if(isptr[t->etype] && t->type->etype == TANY)
|
|
||||||
i = KindUnsafePointer;
|
|
||||||
if(!haspointers(t))
|
if(!haspointers(t))
|
||||||
i |= KindNoPointers;
|
i |= KindNoPointers;
|
||||||
ot = duint8(s, ot, i); // kind
|
ot = duint8(s, ot, i); // kind
|
||||||
|
|
@ -714,12 +712,8 @@ dtypesym(Type *t)
|
||||||
tbase = t->type;
|
tbase = t->type;
|
||||||
dupok = tbase->sym == S;
|
dupok = tbase->sym == S;
|
||||||
|
|
||||||
if(compiling_runtime) {
|
if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
|
||||||
if(tbase == types[tbase->etype]) // int, float, etc
|
goto ok;
|
||||||
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
|
// named types from other files are defined only by those files
|
||||||
if(tbase->sym && !tbase->local)
|
if(tbase->sym && !tbase->local)
|
||||||
|
|
@ -908,7 +902,7 @@ dumptypestructs(void)
|
||||||
for(i=1; i<=TBOOL; i++)
|
for(i=1; i<=TBOOL; i++)
|
||||||
dtypesym(ptrto(types[i]));
|
dtypesym(ptrto(types[i]));
|
||||||
dtypesym(ptrto(types[TSTRING]));
|
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.
|
// add paths for runtime and main, which 6l imports implicitly.
|
||||||
dimportpath(runtimepkg);
|
dimportpath(runtimepkg);
|
||||||
|
|
|
||||||
|
|
@ -1144,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
|
||||||
&& t->sym != S
|
&& t->sym != S
|
||||||
&& !(fp->flags&FmtLong)) {
|
&& !(fp->flags&FmtLong)) {
|
||||||
s = t->sym;
|
s = t->sym;
|
||||||
if(t == types[t->etype])
|
if(t == types[t->etype] && t->etype != TUNSAFEPTR)
|
||||||
return fmtprint(fp, "%s", s->name);
|
return fmtprint(fp, "%s", s->name);
|
||||||
if(exporting) {
|
if(exporting) {
|
||||||
if(fp->flags & FmtShort)
|
if(fp->flags & FmtShort)
|
||||||
|
|
@ -1304,6 +1304,11 @@ Tpretty(Fmt *fp, Type *t)
|
||||||
if(t->sym)
|
if(t->sym)
|
||||||
return fmtprint(fp, "undefined %S", t->sym);
|
return fmtprint(fp, "undefined %S", t->sym);
|
||||||
return fmtprint(fp, "undefined");
|
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.
|
// 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;
|
et = t->etype;
|
||||||
fmtprint(fp, "%E ", et);
|
fmtprint(fp, "%E ", et);
|
||||||
if(t->sym != S)
|
if(t->sym != S)
|
||||||
|
|
@ -1864,7 +1872,7 @@ assignop(Type *src, Type *dst, char **why)
|
||||||
if(why != nil)
|
if(why != nil)
|
||||||
*why = "";
|
*why = "";
|
||||||
|
|
||||||
if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
|
if(safemode && src != T && src->etype == TUNSAFEPTR) {
|
||||||
yyerror("cannot use unsafe.Pointer");
|
yyerror("cannot use unsafe.Pointer");
|
||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
|
|
@ -2028,11 +2036,11 @@ convertop(Type *src, Type *dst, char **why)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
|
// 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;
|
return OCONVNOP;
|
||||||
|
|
||||||
// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
|
// 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 OCONVNOP;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ reswitch:
|
||||||
n->left = N;
|
n->left = N;
|
||||||
goto ret;
|
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);
|
yyerror("invalid indirect of %+N", n->left);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
@ -1316,7 +1316,7 @@ ret:
|
||||||
|
|
||||||
// TODO(rsc): should not need to check importpkg,
|
// TODO(rsc): should not need to check importpkg,
|
||||||
// but reflect mentions unsafe.Pointer.
|
// but reflect mentions unsafe.Pointer.
|
||||||
if(safemode && !incannedimport && !importpkg && isptrto(t, TANY))
|
if(safemode && !incannedimport && !importpkg && t->etype == TUNSAFEPTR)
|
||||||
yyerror("cannot use unsafe.Pointer");
|
yyerror("cannot use unsafe.Pointer");
|
||||||
|
|
||||||
evconst(n);
|
evconst(n);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
package PACKAGE
|
package PACKAGE
|
||||||
|
|
||||||
type Pointer *any
|
type Pointer uintptr // not really; filled in by compiler
|
||||||
|
|
||||||
func Offsetof(any) int
|
func Offsetof(any) int
|
||||||
func Sizeof(any) int
|
func Sizeof(any) int
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,5 @@ import "unsafe"
|
||||||
func main() {
|
func main() {
|
||||||
var x unsafe.Pointer
|
var x unsafe.Pointer
|
||||||
println(*x) // ERROR "invalid indirect.*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