w = 8;
checkwidth(t->type);
break;
+ case TUNSAFEPTR:
+ w = widthptr;
+ break;
case TINTER: // implemented as 2 pointers
w = 2*widthptr;
t->align = widthptr;
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)
okforeq[TPTR32] = 1;
okforeq[TPTR64] = 1;
+ okforeq[TUNSAFEPTR] = 1;
okforeq[TINTER] = 1;
okforeq[TMAP] = 1;
okforeq[TCHAN] = 1;
simtype[TMAP] = tptr;
simtype[TCHAN] = tptr;
simtype[TFUNC] = tptr;
+ simtype[TUNSAFEPTR] = tptr;
/* pick up the backend typedefs */
for(i=0; typedefs[i].name; i++) {
"$$\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"
case TMAP:
case TCHAN:
case TFUNC:
+ case TUNSAFEPTR:
break;
}
break;
{
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:
TFIELD,
TANY,
TSTRING,
+ TUNSAFEPTR,
// pseudo-types for literals
- TIDEAL, // 32
+ TIDEAL, // 33
TNIL,
TBLANK,
[TFUNC] = KindFunc,
[TCOMPLEX64] = KindComplex64,
[TCOMPLEX128] = KindComplex128,
+ [TUNSAFEPTR] = KindUnsafePointer,
};
static char*
[TFLOAT64] = "*runtime.FloatType",
[TBOOL] = "*runtime.BoolType",
[TSTRING] = "*runtime.StringType",
+ [TUNSAFEPTR] = "*runtime.UnsafePointerType",
[TPTR32] = "*runtime.PtrType",
[TPTR64] = "*runtime.PtrType",
if(isslice(t))
name = "*runtime.SliceType";
- if(isptr[et] && t->type->etype == TANY)
- name = "*runtime.UnsafePointerType";
-
return pkglookup(name, typepkg);
}
case TSTRING:
case TPTR32:
case TPTR64:
+ case TUNSAFEPTR:
case TINTER:
case TCHAN:
case TMAP:
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
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)
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);
&& 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)
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.
}
}
+ if(sharp || exporting)
+ fatal("missing %E case during export", t->etype);
+
et = t->etype;
fmtprint(fp, "%E ", et);
if(t->sym != S)
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();
}
}
// 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;
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;
}
// 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);
package PACKAGE
-type Pointer *any
+type Pointer uintptr // not really; filled in by compiler
func Offsetof(any) int
func Sizeof(any) int
func main() {
var x unsafe.Pointer
println(*x) // ERROR "invalid indirect.*unsafe.Pointer"
+ var _ = (unsafe.Pointer)(nil).foo // ERROR "no field or method foo"
}