go.tools/go/types: unsafe.Offsetof must deref named pointers to structs

R=adonovan
CC=golang-dev
https://golang.org/cl/11889043
This commit is contained in:
Robert Griesemer 2013-07-26 09:53:47 -07:00
parent 4da31df1c8
commit bf6a1e674e
3 changed files with 17 additions and 2 deletions

View File

@ -340,7 +340,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
if x.mode == invalid {
goto Error
}
base, _ := deref(x.typ)
base := derefStructPtr(x.typ)
sel := arg.Sel.Name
obj, index, indirect := LookupFieldOrMethod(base, check.pkg, arg.Sel.Name)
switch obj.(type) {

View File

@ -292,7 +292,7 @@ func MissingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
return
}
// Deref dereferences typ if it is a pointer and returns its base and true.
// deref dereferences typ if it is a *Pointer and returns its base and true.
// Otherwise it returns (typ, false).
func deref(typ Type) (Type, bool) {
if p, _ := typ.(*Pointer); p != nil {
@ -301,6 +301,17 @@ func deref(typ Type) (Type, bool) {
return typ, false
}
// derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
// (named or unnamed) struct and returns its base. Otherwise it returns typ.
func derefStructPtr(typ Type) Type {
if p, _ := typ.Underlying().(*Pointer); p != nil {
if _, ok := p.base.Underlying().(*Struct); ok {
return p.base
}
}
return typ
}
// concat returns the result of concatenating list and i.
// The result does not share its underlying array with list.
func concat(list []int, i int) []int {

View File

@ -373,6 +373,10 @@ func _Offsetof() {
var y1p *S1
assert(unsafe.Offsetof(y1p.S0) == 32)
type P *S1
var p P = y1p
assert(unsafe.Offsetof(p.S0) == 32)
var y2 S2
assert(unsafe.Offsetof(y2.S1) == 0)
_ = unsafe.Offsetof(y2 /* ERROR "embedded via a pointer" */ .x)